You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/11 19:20:23 UTC
[01/33] [KARAF-2852] Merge jdbc/core and jdbc/command
Repository: karaf
Updated Branches:
refs/heads/master 4b6b7afb1 -> fd4b3f677
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
new file mode 100644
index 0000000..090daee
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
+ <property name="driverClassName" value="${driver}"/>
+ <property name="url" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ <property name="maxIdle" value="1"/>
+ </bean>
+
+ <bean id="connectionFactory" class="org.apache.commons.dbcp.DataSourceConnectionFactory">
+ <argument ref="dataSource" />
+ </bean>
+
+ <bean id="connectionPool" class="org.apache.commons.pool.impl.GenericObjectPool" >
+ <!-- No default factory -->
+ <argument><null/></argument> <!-- factory -->
+ <!--
+ controls the maximum number of objects that can be allocated by the pool (checked out to clients, or
+ idle awaiting checkout) at a given time. When non-positive, there is no limit to the number of objects that can
+ be managed by the pool at one time. When maxActive is reached, the pool is said to be exhausted.
+ The default setting for this parameter is 8.
+ -->
+ <argument value="8" /> <!-- maxActive -->
+ <!--
+ specifies the behavior of the borrowObject() method when the pool is exhausted:
+
+ When whenExhaustedAction is WHEN_EXHAUSTED_FAIL, borrowObject() will throw a NoSuchElementException
+ When whenExhaustedAction is WHEN_EXHAUSTED_GROW, borrowObject() will create a new object and return it
+ (essentially making maxActive meaningless.)
+ When whenExhaustedAction is WHEN_EXHAUSTED_BLOCK, borrowObject() will block (invoke Object.wait()) until
+ a new or idle object is available. If a positive maxWait value is supplied, then borrowObject() will block for at most that many milliseconds, after which a NoSuchElementException will be thrown. If maxWait is non-positive, the borrowObject() method will block indefinitely.
+
+ The default whenExhaustedAction setting is WHEN_EXHAUSTED_BLOCK and the default maxWait setting is -1.
+ By default, therefore, borrowObject will block indefinitely until an idle instance becomes available.
+ -->
+ <argument value="WHEN_EXHAUSTED_BLOCK" /> <!-- whenExhaustedAction -->
+ <!--
+ the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction
+ is WHEN_EXHAUSTED_BLOCK (otherwise ignored)
+ -->
+ <argument value="-1" /> <!-- maxWait -->
+ <!--
+ controls the maximum number of objects that can sit idle in the pool at any time.
+ When negative, there is no limit to the number of objects that may be idle at one time.
+ The default setting for this parameter is 8.
+ -->
+ <argument value="8" /> <!-- maxIdle -->
+ <!--
+ sets the minimum number of objects allowed in the pool before the evictor thread (if active) spawns
+ new objects.
+ -->
+ <argument value="0" /> <!-- minIdle -->
+ <!--
+ when true, objects will be validated before being returned by the borrowObject() method.
+ -->
+ <argument value="false" /> <!-- testOnBorrow -->
+ <!--
+ when true, objects will be validated before being returned to the pool within the returnObject(T).
+ -->
+ <argument value="false" /> <!-- testOnReturn -->
+ <!--
+ sets the number of milliseconds to sleep between runs of the idle object evictor thread.
+ -->
+ <argument value="-1" /> <!-- timeBetweenEvictionRunsMillis -->
+ <!--
+ the number of idle objects to examine per run within the idle object eviction thread (if any)
+ -->
+ <argument value="3" /> <!-- numTestsPerEvictionRun -->
+ <!--
+ sets the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by
+ the idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle
+ time alone.
+ -->
+ <argument value="1800000" /> <!-- minEvictableIdleTimeMillis -->
+ <!--
+ when true, objects will be validated by the idle object evictor (if any). If an object fails to validate,
+ it will be dropped from the pool.
+ -->
+ <argument value="false" /> <!-- testWhileIdle -->
+ <!--
+ softMinEvictableIdleTimeMillis specifies the minimum amount of time an object may sit idle in the pool before
+ it is eligible for eviction by the idle object evictor (if any), with the extra condition that at least "minIdle"
+ object instances remain in the pool. When non-positive, no objects will be evicted from the pool due to idle time alone.
+ This setting has no effect unless timeBetweenEvictionRunsMillis > 0. and it is superceded by
+ minEvictableIdleTimeMillis (that is, if minEvictableIdleTimeMillis is positive, then
+ softMinEvictableIdleTimeMillis is ignored). The default setting for this parameter is -1 (disabled).
+ -->
+ <argument value="-1" /> <!-- softMinEvictableIdleTimeMillis -->
+ <!--
+ lifo determines whether or not the pool returns idle objects in last-in-first-out order. The default setting for this parameter is true.
+ -->
+ <argument value="true" /> <!-- lifo -->
+ </bean>
+
+ <bean id="pooledConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory" >
+ <argument ref="connectionFactory" />
+ <argument ref="connectionPool" />
+ <argument><null/></argument>
+ <!--
+ a query to use to validate Connections. Should return at least one row. Using null turns off validation.
+ -->
+ <argument><null/></argument> <!-- validationQuery -->
+ <!--
+ the default "read only" setting for borrowed connections
+ -->
+ <argument value="false" /> <!-- defaultReadOnly -->
+ <!--
+ the default "auto commit" setting for returned connections
+ -->
+ <argument value="true" /> <!-- defaultAutoCommit -->
+ </bean>
+
+ <bean id="pooledDataSource" class="org.apache.commons.dbcp.PoolingDataSource" depends-on="pooledConnectionFactory">
+ <argument ref="connectionPool" />
+ </bean>
+
+ <service ref="pooledDataSource" interface="javax.sql.DataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
new file mode 100644
index 0000000..19805f4
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="org.h2.jdbcx.JdbcDataSource">
+ <property name="URL" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
new file mode 100644
index 0000000..3ea9ba8
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="org.hsqldb.jdbc.JDBCDataSource">
+ <property name="url" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
new file mode 100644
index 0000000..35e6ed9
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="net.sourceforge.jtds.jdbcx.JtdsDataSource">
+ <property name="serverName" value="${url}"/>
+ <property name="databaseName" value="${name}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
new file mode 100644
index 0000000..012ecaf
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
+ <property name="url" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
new file mode 100644
index 0000000..8168b16
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
+ <property name="URL" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
new file mode 100644
index 0000000..1845c48
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
+ <property name="serverName" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ <property name="dataSourceName" value="${name}"/>
+ <property name="initialConnections" value="2"/>
+ <property name="maxConnections" value="4" />
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+</blueprint>
\ No newline at end of file
[17/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
deleted file mode 100644
index 9536ba1..0000000
--- a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
+++ /dev/null
@@ -1,239 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
-
--->
-<xs:schema elementFormDefault="qualified"
- targetNamespace="http://karaf.apache.org/xmlns/features/v1.0.0"
- xmlns:tns="http://karaf.apache.org/xmlns/features/v1.0.0"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
- <xs:annotation>
- <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
- ]]></xs:documentation>
- </xs:annotation>
-
- <xs:complexType name="features">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Root element of the Feature definition. It contains an optional attribute for
-designating the name of the repository of this feature. The Karaf shell will
-show the repository name when displaying information about the feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="repository" type="xs:anyURI">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="feature" type="tns:feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature definition.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:choice>
- <xs:attribute name="name" type="xs:string" />
- </xs:complexType>
-
- <xs:complexType name="feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="details" minOccurs="0" type="xs:string">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The help text shown for this feature when using the feature:info console command.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- </xs:choice>
- <xs:attribute name="name" type="tns:featureName" use="required" />
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- <xs:attribute name="description" type="xs:string" />
- <xs:attribute name="resolver" type="tns:resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="install" type="tns:install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If true, marks that the feature should start automatically when placed in the deploy folder.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for the bundles in this feature different
-from the default start level defined in Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="region" type="xs:string"/>
- </xs:complexType>
-
- <xs:complexType name="bundle">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Deployable element to install.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in Karaf's config.properties.
-
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start" type="xs:boolean" default="true">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If false, leaves the bundle in resolved state rather than the default active state.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="dependency" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="dependency">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Dependency of feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="tns:featureName">
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="config">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="configFile">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="finalname" type="xs:string" use="required">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The final destination path and name for the configuration file (relative to the KARAF_BASE).
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="override" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
-
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name="featureName">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature name should be non empty string.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
-
- <xs:simpleType name="resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which has following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:element name="features" type="tns:features" />
-
-</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
deleted file mode 100644
index 7138573..0000000
--- a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
+++ /dev/null
@@ -1,237 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
-
--->
-<xs:schema elementFormDefault="qualified"
- targetNamespace="http://karaf.apache.org/xmlns/features/v1.1.0"
- xmlns:tns="http://karaf.apache.org/xmlns/features/v1.1.0"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
- <xs:annotation>
- <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
- ]]></xs:documentation>
- </xs:annotation>
-
- <xs:complexType name="features">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="repository" type="xs:anyURI">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="feature" type="tns:feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature definition.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:choice>
- <xs:attribute name="name" type="xs:string" use="required"/>
- </xs:complexType>
-
- <xs:complexType name="feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="details" minOccurs="0" type="xs:string">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- </xs:choice>
- <xs:attribute name="name" type="tns:featureName" use="required" />
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- <xs:attribute name="description" type="xs:string" />
- <xs:attribute name="resolver" type="tns:resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="install" type="tns:install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
-
- <xs:complexType name="bundle">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Deployable element to install.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start" type="xs:boolean" default="true">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="dependency" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="dependency">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Dependency of feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="tns:featureName">
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="config">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="configFile">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="finalname" type="xs:string" use="required">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="override" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
-
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name="featureName">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature name should be non empty string.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
-
- <xs:simpleType name="resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:element name="features" type="tns:features" />
-
-</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
deleted file mode 100644
index dbc4bfa..0000000
--- a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
+++ /dev/null
@@ -1,254 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
-
--->
-<xs:schema elementFormDefault="qualified"
- targetNamespace="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:tns="http://karaf.apache.org/xmlns/features/v1.2.0"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
- <xs:annotation>
- <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
- ]]></xs:documentation>
- </xs:annotation>
-
- <xs:complexType name="features">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="repository" type="xs:anyURI">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="feature" type="tns:feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature definition.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:choice>
- <xs:attribute name="name" type="xs:string" use="required"/>
- </xs:complexType>
-
- <xs:complexType name="feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="details" minOccurs="0" type="xs:string">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- <xs:element name="conditional" type="tns:conditional" />
- </xs:choice>
- <xs:attribute name="name" type="tns:featureName" use="required" />
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- <xs:attribute name="description" type="xs:string" />
- <xs:attribute name="resolver" type="tns:resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="install" type="tns:install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
-
- <xs:complexType name="conditional">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Conditional.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
- </xs:choice>
- </xs:complexType>
-
-
- <xs:complexType name="bundle">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Deployable element to install.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start" type="xs:boolean" default="true">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="dependency" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="dependency">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Dependency of feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="tns:featureName">
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="config">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="configFile">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="finalname" type="xs:string" use="required">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="override" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
-
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name="featureName">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature name should be non empty string.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
-
- <xs:simpleType name="resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:element name="features" type="tns:features" />
-
-</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
deleted file mode 100644
index 60ec8d2..0000000
--- a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
+++ /dev/null
@@ -1,280 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
-
--->
-<xs:schema elementFormDefault="qualified"
- targetNamespace="http://karaf.apache.org/xmlns/features/v1.3.0"
- xmlns:tns="http://karaf.apache.org/xmlns/features/v1.3.0"
- xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
- <xs:annotation>
- <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
- ]]></xs:documentation>
- </xs:annotation>
-
- <xs:complexType name="features">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="repository" type="xs:anyURI">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="feature" type="tns:feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature definition.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:choice>
- <xs:attribute name="name" type="xs:string" use="required"/>
- </xs:complexType>
-
- <xs:complexType name="feature">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="details" minOccurs="0" type="xs:string">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- <xs:element name="conditional" type="tns:conditional" />
- <xs:element name="requirement" type="tns:requirement" />
- <xs:element name="capability" type="tns:capability" />
- </xs:choice>
- <xs:attribute name="name" type="tns:featureName" use="required" />
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- <xs:attribute name="description" type="xs:string" />
- <xs:attribute name="resolver" type="tns:resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="install" type="tns:install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
-
- <xs:complexType name="conditional">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Definition of the Conditional.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element name="config" type="tns:config" />
- <xs:element name="configfile" type="tns:configFile" />
- <xs:element name="feature" type="tns:dependency" />
- <xs:element name="bundle" type="tns:bundle" />
- <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
- </xs:choice>
- </xs:complexType>
-
-
- <xs:complexType name="bundle">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Deployable element to install.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="start-level" type="xs:int">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="start" type="xs:boolean" default="true">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="dependency" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
- ]]>
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="dependency">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Dependency of feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="tns:featureName">
- <xs:attribute name="version" type="xs:string" default="0.0.0" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="config">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="name" type="xs:string" use="required" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="configFile">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:anyURI">
- <xs:attribute name="finalname" type="xs:string" use="required">
- <xs:annotation>
- <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="override" type="xs:boolean">
- <xs:annotation>
- <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
- ]]></xs:documentation>
- </xs:annotation>
- </xs:attribute>
-
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="requirement">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional requirements of this feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:complexType name="capability">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Additional capability of this feature.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
-
- <xs:simpleType name="featureName">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Feature name should be non empty string.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
-
- <xs:simpleType name="resolver">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="install">
- <xs:annotation>
- <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
- ]]></xs:documentation>
- </xs:annotation>
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
- <xs:element name="features" type="tns:features" />
-
-</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/ConditionalTest.java b/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
deleted file mode 100644
index b103683..0000000
--- a/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import junit.framework.TestCase;
-import org.apache.karaf.features.internal.service.RepositoryImpl;
-
-
-public class ConditionalTest extends TestCase {
-
- public void testLoad() throws Exception {
- RepositoryImpl r = new RepositoryImpl(getClass().getResource("internal/service/f06.xml").toURI());
- // Check repo
- Feature[] features = r.getFeatures();
- assertNotNull(features);
- assertEquals(1, features.length);
- Feature feature = features[0];
-
- assertNotNull(feature.getConditional());
- assertEquals(2,feature.getConditional().size());
-
- Conditional conditional = feature.getConditional().get(0);
- assertNotNull(conditional.getCondition());
- assertEquals(1,conditional.getCondition().size());
- String dependency = conditional.getCondition().get(0);
- assertNotNull(dependency);
- assertEquals("http", dependency);
- assertNotNull(conditional.getBundles());
- assertEquals(1, feature.getConditional().get(0).getBundles().size());
-
- conditional = feature.getConditional().get(1);
- assertNotNull(conditional.getCondition());
- assertEquals(1,conditional.getCondition().size());
- dependency = conditional.getCondition().get(0);
- assertNotNull(dependency);
- assertEquals("req:osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(!(version>=1.7)))\"", dependency);
-
- String wrapperName = "my6/1.5.3-beta-3".replaceAll("[^A-Za-z0-9 ]", "_");
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/FeatureTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/FeatureTest.java b/features/src/test/java/org/apache/karaf/features/FeatureTest.java
deleted file mode 100644
index b7d4c27..0000000
--- a/features/src/test/java/org/apache/karaf/features/FeatureTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import junit.framework.TestCase;
-
-public class FeatureTest extends TestCase {
-
- public void testValueOf() {
- Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf("name" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + "version");
- assertEquals(feature.getName(), "name");
- assertEquals(feature.getVersion(), "version");
- feature = org.apache.karaf.features.internal.model.Feature.valueOf("name");
- assertEquals(feature.getName(), "name");
- assertEquals(feature.getVersion(), org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
deleted file mode 100644
index a74e3d0..0000000
--- a/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
-import org.apache.karaf.features.internal.service.StateStorage;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-public class FeaturesServiceTest extends TestBase {
- private static final String FEATURE_WITH_INVALID_BUNDLE = "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1'><bundle>%s</bundle><bundle>zfs:unknown</bundle></feature>"
- + " <feature name='f2'><bundle>%s</bundle></feature>"
- + "</features>";
-
- File dataFile;
-
- @Before
- public void setUp() throws IOException {
- dataFile = File.createTempFile("features", null, null);
- }
-
- private URI createTempRepo(String repoContent, Object ... variables) throws IOException {
- File tmp = File.createTempFile("karaf", ".feature");
- PrintWriter pw = new PrintWriter(new FileWriter(tmp));
- pw.printf(repoContent, variables);
- pw.close();
- return tmp.toURI();
- }
-
- /*
- TODO: migrate those tests
-
- @Test
- public void testInstallFeature() throws Exception {
- URI uri = createTempRepo(
- "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1'><bundle start='true'>bundle-f1</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- Bundle installedBundle = createDummyBundle(12345L, "bundle-f1", headers());
- FeaturesServiceImpl svc = testAddRepository("bundle-f1", uri, bundleManager, installedBundle);
-
- reset(bundleManager);
-
- expect(bundleManager.installBundleIfNeeded(eq("bundle-f1"), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true));
- expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
- ignoreRefreshes(bundleManager);
- replay(bundleManager);
- svc.installFeature("f1", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
- verify(bundleManager);
-
- Feature[] installed = svc.listInstalledFeatures();
- assertEquals(1, installed.length);
- assertEquals("f1", installed[0].getName());
- }
-
- private FeaturesServiceImpl testAddRepository(String name, URI uri, BundleManager bundleManager,
- Bundle installedBundle) throws IOException, BundleException, Exception {
- expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
- expect(bundleManager.installBundleIfNeeded(eq(name), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true)).anyTimes();
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
- Repository[] repositories = svc.listRepositories();
- verify(bundleManager);
-
- assertNotNull(repositories);
- assertEquals(1, repositories.length);
- assertNotNull(repositories[0]);
- Feature[] features = repositories[0].getFeatures();
- assertNotNull(features);
- assertEquals(1, features.length);
- assertNotNull(features[0]);
- assertEquals("f1", features[0].getName());
- assertNotNull(features[0].getDependencies());
- assertEquals(0, features[0].getDependencies().size());
- assertNotNull(features[0].getBundles());
- assertEquals(1, features[0].getBundles().size());
- assertEquals(name, features[0].getBundles().get(0).getLocation());
- assertTrue(features[0].getBundles().get(0).isStart());
- return svc;
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testUninstallFeatureWithTwoVersions() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><bundle>bundle-0.1</bundle></feature>"
- + " <feature name='f1' version='0.2'><bundle>bundle-0.1</bundle></feature>"
- + "</features>");
-
- Bundle bundlef101 = createDummyBundle(12345L, "bundle-0.1", headers());
-
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile).anyTimes();
- expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
- expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, false));
- expect(bundleManager.getBundleContext()).andReturn(bundleContext);
- ignoreRefreshes(bundleManager);
- bundleManager.uninstall(Collections.EMPTY_LIST, true);
- EasyMock.expectLastCall().times(2);
-
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
-
- try {
- svc.uninstallFeature("f1");
- fail("Uninstall should have failed as feature is not installed");
- } catch (Exception e) {
- // ok
- }
-
- svc.installFeature("f1", "0.1", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
- svc.installFeature("f1", "0.2", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
-
- try {
- svc.uninstallFeature("f1");
- fail("Uninstall should have failed as feature is installed in multiple versions");
- } catch (Exception e) {
- // ok
- }
-
- svc.uninstallFeature("f1", "0.1");
- svc.uninstallFeature("f1");
- verify(bundleManager);
- }
-
- @Test
- public void testAddAndRemoveRepository() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><bundle>bundle-f1-0.1</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- EasyMock.verify(bundleManager);
-
- svc.addRepository(uri);
- svc.removeRepository(uri);
- verify(bundleManager);
- }
-
- // Tests install of a Repository that includes a feature
- // with a feature dependency
- // The dependant feature is in the same repository
- // Tests uninstall of features
- @SuppressWarnings("unchecked")
- @Test
- public void testInstallFeatureWithDependantFeatures() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
- + " <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- Bundle bundlef101 = createDummyBundle(12345L, "bundle-f1-0.1", headers());
- Bundle bundlef201 = createDummyBundle(54321L, "bundle-f2-0.1", headers());
- expect(bundleManager.getDataFile(EasyMock.<String> anyObject())).andReturn(dataFile).anyTimes();
- expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null))
- .andReturn(new BundleInstallerResult(bundlef101, true));
- expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null))
- .andReturn(new BundleInstallerResult(bundlef201, true));
- expect(bundleManager.getBundleContext()).andReturn(bundleContext).anyTimes();
- expect(bundleContext.getBundle(12345)).andReturn(bundlef101).anyTimes();
- ignoreRefreshes(bundleManager);
- bundleManager.uninstall(Collections.EMPTY_LIST, true);
-
- EasyMock.expectLastCall().anyTimes();
- replay(bundleManager);
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
- svc.installFeature("f1", "0.1");
- svc.uninstallFeature("f1", "0.1");
- verify(bundleManager);
-
- }
-
- @SuppressWarnings("unchecked")
- private BundleManager prepareBundleManagerForInstallUninstall(String bundleUri, String bundlename) throws Exception {
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- Bundle installedBundle = createDummyBundle(12345L, bundlename, headers());
- expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
- expect(bundleManager.installBundleIfNeeded(bundleUri, 0, null)).andReturn(new BundleInstallerResult(installedBundle, true));
- expect(bundleManager.getBundleContext()).andReturn(bundleContext);
- ignoreRefreshes(bundleManager);
- bundleManager.uninstall(Collections.EMPTY_LIST, true);
- EasyMock.expectLastCall().times(2);
- return bundleManager;
- }
-
- @Test
- public void testInstallFeatureWithDependantFeaturesAndVersionWithoutPreinstall() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><feature version='0.1'>f2</feature></feature>"
- + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
- + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.1", "bundle-0.1");
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
- svc.installFeature("f1", "0.1");
- svc.uninstallFeature("f1", "0.1");
- svc.uninstallFeature("f2", "0.1");
- verify(bundleManager);
- }
-
- @Test
- public void testInstallFeatureWithDependantFeaturesAndNoVersionWithoutPreinstall() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><feature>f2</feature></feature>"
- + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
- + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.2", "bundle-0.2");
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
- svc.installFeature("f1", "0.1");
- svc.uninstallFeature("f1", "0.1");
- svc.uninstallFeature("f2", "0.2");
- verify(bundleManager);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testInstallFeatureWithDependantFeaturesAndRangeWithoutPreinstall() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
- + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
- + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
- + "</features>");
-
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- Bundle bundleVer02 = createDummyBundle(54321L, "bundleVer02", headers());
- expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
- expect(bundleManager.installBundleIfNeeded("bundle-0.2", 0, null)).andReturn(new BundleInstallerResult(bundleVer02, true));
- expect(bundleManager.getBundleContext()).andReturn(bundleContext);
- ignoreRefreshes(bundleManager);
- bundleManager.uninstall(Collections.EMPTY_LIST, true);
-
- EasyMock.expectLastCall().times(2);
-
- replay(bundleManager);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
- svc.addRepository(uri);
- svc.installFeature("f1", "0.1");
- svc.uninstallFeature("f1", "0.1");
- svc.uninstallFeature("f2", "0.2");
- verify(bundleManager);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- public void testInstallFeatureWithDependantFeaturesAndRangeWithPreinstall() throws Exception {
- String bundleVer01Uri = "bundle-0.1";
- String bundleVer02Uri = "bundle-0.2";
-
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + "<feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
- + " <feature name='f2' version='0.1'><bundle>%s</bundle></feature>"
- + " <feature name='f2' version='0.2'><bundle>%s</bundle></feature>"
- + "</features>", bundleVer01Uri, bundleVer02Uri);
-
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
- replay(bundleContext);
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null);
- svc.addRepository(uri);
- svc.installFeature("f2", "0.1");
- svc.installFeature("f1", "0.1");
- svc.uninstallFeature("f1", "0.1");
- svc.uninstallFeature("f2", "0.1");
-
- verify(bundleContext);
- }
- */
-
- @Test
- public void testGetFeaturesShouldHandleDifferentVersionPatterns() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
- + " <feature name='f2' version='0.1'><bundle>bundle1</bundle></feature>"
- + " <feature name='f2' version='0.2'><bundle>bundle2</bundle></feature>"
- + "</features>");
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
- svc.addRepository(uri);
-
- assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "[0.1,0.3)"));
- assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.0.0"));
- assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.2"));
- assertNull(svc.getFeature("f2", "0.3"));
- }
-
- @Test
- public void testInstallBatchFeatureWithFailure() throws Exception {
- String bundle1Uri = "file:bundle1";
- String bundle2Uri = "file:bundle2";
-
- URI uri = createTempRepo(FEATURE_WITH_INVALID_BUNDLE, bundle1Uri, bundle2Uri);
-
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
- replay(bundleContext);
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null);
- svc.addRepository(uri);
- try {
- List<String> features = new ArrayList<String>();
- for (Feature feature : svc.listFeatures()) {
- features.add(feature.getId());
- }
- Collections.reverse(features);
- svc.installFeatures(new CopyOnWriteArraySet<String>(features),
- EnumSet.noneOf(FeaturesService.Option.class));
- fail("Call should have thrown an exception");
- } catch (MalformedURLException e) {
- }
- verify(bundleContext);
- }
-
- /**
- * This test checks schema validation of submited uri.
- */
- @Test
- public void testSchemaValidation() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <featur><bundle>somebundle</bundle></featur></features>");
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
- try {
- svc.addRepository(uri);
- fail("exception expected");
- } catch (Exception e) {
- assertTrue(e.getMessage().contains("Unable to validate"));
- }
- }
-
- /**
- * This test checks feature service behavior with old, non namespaced descriptor.
- */
- @Test
- public void testLoadOldFeatureFile() throws Exception {
- URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
- + " <feature name='f1'><bundle>file:bundle1</bundle><bundle>file:bundle2</bundle></feature>"
- + "</features>");
-
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
- svc.addRepository(uri);
- Feature feature = svc.getFeature("f1");
- Assert.assertNotNull("No feature named fi found", feature);
- List<BundleInfo> bundles = feature.getBundles();
- Assert.assertEquals(2, bundles.size());
- }
-
- static class Storage extends StateStorage {
- @Override
- protected InputStream getInputStream() throws IOException {
- return null;
- }
- @Override
- protected OutputStream getOutputStream() throws IOException {
- return null;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/RepositoryTest.java b/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
deleted file mode 100644
index 164dc79..0000000
--- a/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.net.URI;
-
-import junit.framework.TestCase;
-import org.apache.karaf.features.internal.resolver.FeatureResource;
-import org.apache.karaf.features.internal.service.RepositoryImpl;
-import org.osgi.resource.Resource;
-
-
-public class RepositoryTest extends TestCase {
-
- public void testLoad() throws Exception {
- RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo1.xml").toURI());
- // Check repo
- URI[] repos = r.getRepositories();
- assertNotNull(repos);
- assertEquals(1, repos.length);
- assertEquals(URI.create("urn:r1"), repos[0]);
- // Check features
- Feature[] features = r.getFeatures();
- assertNotNull(features);
- assertEquals(3, features.length);
- assertNotNull(features[0]);
- assertEquals("f1", features[0].getName());
- assertNotNull(features[0].getConfigurations());
- assertEquals(1, features[0].getConfigurations().size());
- assertNotNull(features[0].getConfigurations().get("c1"));
- assertEquals(1, features[0].getConfigurations().get("c1").size());
- assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
- assertNotNull(features[0].getDependencies());
- assertEquals(0, features[0].getDependencies().size());
- assertNotNull(features[0].getBundles());
- assertEquals(2, features[0].getBundles().size());
- assertEquals("b1", features[0].getBundles().get(0).getLocation());
- assertEquals("b2", features[0].getBundles().get(1).getLocation());
- assertNotNull(features[1]);
- assertEquals("f2", features[1].getName());
- assertNotNull(features[1].getConfigurations());
- assertEquals(0, features[1].getConfigurations().size());
- assertNotNull(features[1].getDependencies());
- assertEquals(1, features[1].getDependencies().size());
- assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
- assertNotNull(features[1].getBundles());
- assertEquals(1, features[1].getBundles().size());
- assertEquals("b3", features[1].getBundles().get(0).getLocation());
- assertEquals("f3", features[2].getName());
- assertNotNull(features[2].getConfigurationFiles());
- assertEquals(1, features[2].getConfigurationFiles().size());
- assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
- assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
- assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
- }
-
- public void testLoadFormattedRepo() throws Exception {
- RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo2.xml").toURI());
- // Check repo
- URI[] repos = r.getRepositories();
- assertNotNull(repos);
- assertEquals(1, repos.length);
- assertEquals(URI.create("urn:r1"), repos[0]);
- // Check features
- Feature[] features = r.getFeatures();
- assertNotNull(features);
- assertEquals(3, features.length);
- assertNotNull(features[0]);
- assertEquals("f1", features[0].getName());
- assertNotNull(features[0].getConfigurations());
- assertEquals(1, features[0].getConfigurations().size());
- assertNotNull(features[0].getConfigurations().get("c1"));
- assertEquals(1, features[0].getConfigurations().get("c1").size());
- assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
- assertNotNull(features[0].getDependencies());
- assertEquals(0, features[0].getDependencies().size());
- assertNotNull(features[0].getBundles());
- assertEquals(2, features[0].getBundles().size());
- assertEquals("b1", features[0].getBundles().get(0).getLocation());
- assertEquals("b2", features[0].getBundles().get(1).getLocation());
- assertNotNull(features[1]);
- assertEquals("f2", features[1].getName());
- assertNotNull(features[1].getConfigurations());
- assertEquals(0, features[1].getConfigurations().size());
- assertNotNull(features[1].getDependencies());
- assertEquals(1, features[1].getDependencies().size());
- assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
- assertNotNull(features[1].getBundles());
- assertEquals(1, features[1].getBundles().size());
- assertEquals("b3", features[1].getBundles().get(0).getLocation());
- assertEquals("f3", features[2].getName());
- assertNotNull(features[2].getConfigurationFiles());
- assertEquals(1, features[2].getConfigurationFiles().size());
- assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
- assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
- assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
- }
-
- public void testLoadRepoWithCapabilitiesAndRequirement() throws Exception {
- RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo3.xml").toURI());
- // Check features
- Feature[] features = r.getFeatures();
- assertNotNull(features);
- assertEquals(1, features.length);
- assertNotNull(features[0]);
- assertEquals("f1", features[0].getName());
- assertEquals(1, features[0].getCapabilities().size());
- assertEquals("cap", features[0].getCapabilities().get(0).getValue().trim());
- assertEquals(1, features[0].getRequirements().size());
- assertEquals("req", features[0].getRequirements().get(0).getValue().trim());
-
- Resource res = FeatureResource.build(features[0], null, null);
- assertEquals(1, res.getCapabilities("cap").size());
- assertEquals(1, res.getRequirements("req").size());
- }
-
- public void testShowWrongUriInException() throws Exception {
- String uri = "src/test/resources/org/apache/karaf/shell/features/repo1.xml";
- RepositoryImpl r = new RepositoryImpl(new URI(uri));
- try {
- r.load();
- } catch (Exception e) {
- assertTrue(e.getMessage().contains(uri));
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/TestBase.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/TestBase.java b/features/src/test/java/org/apache/karaf/features/TestBase.java
deleted file mode 100644
index ac8f3d9..0000000
--- a/features/src/test/java/org/apache/karaf/features/TestBase.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Set;
-
-import org.easymock.EasyMock;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.startlevel.BundleStartLevel;
-
-import static java.util.Arrays.asList;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-public class TestBase {
- public Bundle createDummyBundle(long id, final String symbolicName, Dictionary<String,String> headers) {
- Bundle bundle = EasyMock.createNiceMock(Bundle.class);
-
- // Be aware that this means all bundles are treated as different
- expect(bundle.compareTo(EasyMock.<Bundle>anyObject())).andReturn(1).anyTimes();
-
- expect(bundle.getBundleId()).andReturn(id).anyTimes();
- expect(bundle.getSymbolicName()).andReturn(symbolicName).anyTimes();
- expect(bundle.getHeaders()).andReturn(headers).anyTimes();
- BundleStartLevel sl = EasyMock.createMock(BundleStartLevel.class);
- expect(sl.isPersistentlyStarted()).andReturn(true).anyTimes();
- expect(bundle.adapt(BundleStartLevel.class)).andReturn(sl).anyTimes();
- replay(bundle, sl);
- return bundle;
- }
-
- public Dictionary<String, String> headers(String ... keyAndHeader) {
- Hashtable<String, String> headersTable = new Hashtable<String, String>();
- int c=0;
- while (c < keyAndHeader.length) {
- String key = keyAndHeader[c++];
- String value = keyAndHeader[c++];
- headersTable.put(key, value);
- }
- return headersTable;
- }
-
- public Map<String, Map<String, Feature>> features(Feature ... features) {
- final Map<String, Map<String, Feature>> featuresMap = new HashMap<String, Map<String,Feature>>();
- for (Feature feature : features) {
- Map<String, Feature> featureVersion = getOrCreate(featuresMap, feature);
- featureVersion.put(feature.getVersion(), feature);
- }
- return featuresMap;
- }
-
- private Map<String, Feature> getOrCreate(final Map<String, Map<String, Feature>> featuresMap, Feature feature) {
- Map<String, Feature> featureVersion = featuresMap.get(feature.getName());
- if (featureVersion == null) {
- featureVersion = new HashMap<String, Feature>();
- featuresMap.put(feature.getName(), featureVersion);
- }
- return featureVersion;
- }
-
- public Feature feature(String name) {
- return feature(name, null);
- }
-
- public Feature feature(String name, String version) {
- return new org.apache.karaf.features.internal.model.Feature(name, version);
- }
-
- public Set<Bundle> setOf(Bundle ... elements) {
- return new HashSet<Bundle>(Arrays.asList(elements));
- }
-
- public Set<Long> setOf(Long ... elements) {
- return new HashSet<Long>(Arrays.asList(elements));
- }
-
- public Set<String> setOf(String ... elements) {
- return new HashSet<String>(asList(elements));
- }
-
- public Set<Feature> setOf(Feature ... elements) {
- return new HashSet<Feature>(Arrays.asList(elements));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
deleted file mode 100644
index 31f4f29..0000000
--- a/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import static java.util.Arrays.asList;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.fail;
-
-import java.net.URI;
-import java.util.EnumSet;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService.Option;
-import org.apache.karaf.features.TestBase;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class BootFeaturesInstallerTest extends TestBase {
-
- @Test
- @SuppressWarnings("unchecked")
- public void testParser() {
- BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, "", "", false);
- Assert.assertEquals(asList(setOf("test1", "test2"),setOf("test3")), installer.parseBootFeatures("(test1, test2), test3"));
- Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures("test1, test2, test3"));
- }
-
- @Test
- public void testDefaultBootFeatures() throws Exception {
- FeaturesServiceImpl impl = EasyMock.createMock(FeaturesServiceImpl.class);
-
- impl.installFeatures(setOf("config", "standard", "region"), EnumSet.of(Option.NoFailOnFeatureNotFound));
- EasyMock.expectLastCall();
-
- impl.bootDone();
- EasyMock.expectLastCall();
-
- replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "", "config,standard,region", false);
- bootFeatures.installBootFeatures();
- EasyMock.verify(impl);
- }
-
- @Test
- public void testStagedBoot() throws Exception {
- FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
-
- impl.installFeatures(setOf("transaction"), EnumSet.of(Option.NoFailOnFeatureNotFound));
- EasyMock.expectLastCall();
- impl.installFeatures(setOf("ssh"), EnumSet.of(Option.NoFailOnFeatureNotFound));
- EasyMock.expectLastCall();
-
- impl.bootDone();
- EasyMock.expectLastCall();
-
- replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , "", "(transaction), ssh", false);
- bootFeatures.installBootFeatures();
- EasyMock.verify(impl);
- }
-
- @Test
- public void testStartDoesNotFailWithOneInvalidUri() throws Exception {
- FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
- impl.addRepository(URI.create("mvn:inexistent/features/1.0/xml/features"));
- EasyMock.expectLastCall().andThrow(new IllegalArgumentException());
-
- impl.bootDone();
- EasyMock.expectLastCall();
-
- replay(impl);
- BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "mvn:inexistent/features/1.0/xml/features", "", false);
- bootFeatures.installBootFeatures();
- EasyMock.verify(impl);
- }
-
-}
[03/33] git commit: [KARAF-2852] Merge jdbc/core and jdbc/command
Posted by gn...@apache.org.
[KARAF-2852] Merge jdbc/core and jdbc/command
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/a9b763f2
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/a9b763f2
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/a9b763f2
Branch: refs/heads/master
Commit: a9b763f2b759d0d018697cdac0f21f4a09445b5b
Parents: 0f53437
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 08:38:47 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:02 2014 +0200
----------------------------------------------------------------------
.../enterprise/src/main/feature/feature.xml | 1 -
jdbc/NOTICE | 71 ++++++
jdbc/command/NOTICE | 71 ------
jdbc/command/pom.xml | 87 -------
.../karaf/jdbc/command/CreateCommand.java | 61 -----
.../karaf/jdbc/command/DataSourcesCommand.java | 50 ----
.../karaf/jdbc/command/DeleteCommand.java | 39 ----
.../karaf/jdbc/command/ExecuteCommand.java | 42 ----
.../apache/karaf/jdbc/command/InfoCommand.java | 53 -----
.../karaf/jdbc/command/JdbcCommandSupport.java | 36 ---
.../apache/karaf/jdbc/command/QueryCommand.java | 64 -----
.../karaf/jdbc/command/TablesCommand.java | 61 -----
.../DataSourcesFileNameCompleter.java | 59 -----
.../completers/DataSourcesNameCompleter.java | 59 -----
.../src/main/resources/OSGI-INF/bundle.info | 26 ---
jdbc/core/NOTICE | 71 ------
jdbc/core/pom.xml | 87 -------
.../java/org/apache/karaf/jdbc/JdbcMBean.java | 96 --------
.../java/org/apache/karaf/jdbc/JdbcService.java | 95 --------
.../karaf/jdbc/internal/JdbcConnector.java | 146 ------------
.../karaf/jdbc/internal/JdbcMBeanImpl.java | 168 --------------
.../karaf/jdbc/internal/JdbcServiceImpl.java | 231 -------------------
.../resources/OSGI-INF/blueprint/jdbc-core.xml | 41 ----
.../src/main/resources/OSGI-INF/bundle.info | 18 --
.../karaf/jdbc/internal/datasource-db2.xml | 32 ---
.../karaf/jdbc/internal/datasource-derby.xml | 39 ----
.../karaf/jdbc/internal/datasource-generic.xml | 141 -----------
.../karaf/jdbc/internal/datasource-h2.xml | 31 ---
.../karaf/jdbc/internal/datasource-hsql.xml | 31 ---
.../karaf/jdbc/internal/datasource-mssql.xml | 32 ---
.../karaf/jdbc/internal/datasource-mysql.xml | 31 ---
.../karaf/jdbc/internal/datasource-oracle.xml | 31 ---
.../karaf/jdbc/internal/datasource-postgres.xml | 34 ---
jdbc/pom.xml | 71 +++++-
.../java/org/apache/karaf/jdbc/JdbcMBean.java | 96 ++++++++
.../java/org/apache/karaf/jdbc/JdbcService.java | 95 ++++++++
.../karaf/jdbc/command/CreateCommand.java | 61 +++++
.../karaf/jdbc/command/DataSourcesCommand.java | 50 ++++
.../karaf/jdbc/command/DeleteCommand.java | 39 ++++
.../karaf/jdbc/command/ExecuteCommand.java | 42 ++++
.../apache/karaf/jdbc/command/InfoCommand.java | 53 +++++
.../karaf/jdbc/command/JdbcCommandSupport.java | 36 +++
.../apache/karaf/jdbc/command/QueryCommand.java | 64 +++++
.../karaf/jdbc/command/TablesCommand.java | 61 +++++
.../DataSourcesFileNameCompleter.java | 59 +++++
.../completers/DataSourcesNameCompleter.java | 59 +++++
.../karaf/jdbc/internal/JdbcConnector.java | 146 ++++++++++++
.../karaf/jdbc/internal/JdbcMBeanImpl.java | 168 ++++++++++++++
.../karaf/jdbc/internal/JdbcServiceImpl.java | 231 +++++++++++++++++++
.../resources/OSGI-INF/blueprint/jdbc-core.xml | 41 ++++
jdbc/src/main/resources/OSGI-INF/bundle.info | 18 ++
.../karaf/jdbc/internal/datasource-db2.xml | 32 +++
.../karaf/jdbc/internal/datasource-derby.xml | 39 ++++
.../karaf/jdbc/internal/datasource-generic.xml | 141 +++++++++++
.../karaf/jdbc/internal/datasource-h2.xml | 31 +++
.../karaf/jdbc/internal/datasource-hsql.xml | 31 +++
.../karaf/jdbc/internal/datasource-mssql.xml | 32 +++
.../karaf/jdbc/internal/datasource-mysql.xml | 31 +++
.../karaf/jdbc/internal/datasource-oracle.xml | 31 +++
.../karaf/jdbc/internal/datasource-postgres.xml | 34 +++
60 files changed, 1855 insertions(+), 2072 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/assemblies/features/enterprise/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/feature/feature.xml b/assemblies/features/enterprise/src/main/feature/feature.xml
index c68017f..24c4136 100644
--- a/assemblies/features/enterprise/src/main/feature/feature.xml
+++ b/assemblies/features/enterprise/src/main/feature/feature.xml
@@ -190,7 +190,6 @@
<bundle>mvn:commons-pool/commons-pool/${commons-pool.version}</bundle>
<bundle>mvn:commons-dbcp/commons-dbcp/${commons-dbcp.version}</bundle>
<bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.core/${project.version}</bundle>
- <bundle>mvn:org.apache.karaf.jdbc/org.apache.karaf.jdbc.command/${project.version}</bundle>
</feature>
<feature name="jms" description="JMS service and commands" version="${project.version}" resolver="(obr)">
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/NOTICE
----------------------------------------------------------------------
diff --git a/jdbc/NOTICE b/jdbc/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/jdbc/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/NOTICE
----------------------------------------------------------------------
diff --git a/jdbc/command/NOTICE b/jdbc/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jdbc/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/pom.xml
----------------------------------------------------------------------
diff --git a/jdbc/command/pom.xml b/jdbc/command/pom.xml
deleted file mode 100644
index b459a13..0000000
--- a/jdbc/command/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.jdbc</groupId>
- <artifactId>jdbc</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.jdbc.command</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: JDBC :: Command</name>
- <description>This bundle provides shell commands to manipulate the JDBC service</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.karaf.jdbc</groupId>
- <artifactId>org.apache.karaf.jdbc.core</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.core</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>!*</Export-Package>
- <Karaf-Commands>*</Karaf-Commands>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
deleted file mode 100644
index 89ed49c..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-@Command(scope = "jdbc", name = "create", description = "Create a JDBC datasource")
-@Service
-public class CreateCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "name", description = "The JDBC datasource name", required = true, multiValued = false)
- String name;
-
- @Option(name = "-t", aliases = { "--type" }, description = "The JDBC datasource type (generic, MySQL, Oracle, Postgres, H2, HSQL, Derby, MSSQL)", required = false, multiValued = false)
- @Completion(value = StringsCompleter.class, values = { "db2", "derby", "generic", "h2", "hsql", "mysql", "oracle", "postgres", "mssql" })
- String type;
-
- @Option(name = "-d", aliases = { "--driver" }, description = "The classname of the JDBC driver to use. NB: this option is used only the type generic", required = false, multiValued = false)
- String driver;
-
- @Option(name = "-v", aliases = { "--version" }, description = "The version of the driver to use", required = false, multiValued = false)
- String version;
-
- @Option(name = "-url", description = "The JDBC URL to use", required = false, multiValued = false)
- String url;
-
- @Option(name = "-u", aliases = { "--username" }, description = "The database username", required = false, multiValued = false)
- String username;
-
- @Option(name = "-p", aliases = { "--password" }, description = "The database password", required = false, multiValued = false)
- String password;
-
- @Option(name = "-i", aliases = { "--install-bundles" }, description = "Try to install the bundles providing the JDBC driver", required = false, multiValued = false)
- boolean installBundles = false;
-
- @Override
- public Object execute() throws Exception {
- this.getJdbcService().create(name, type, driver, version, url, username, password, installBundles);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
deleted file mode 100644
index cb3edad..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jdbc", name = "datasources", description = "List the JDBC datasources")
-@Service
-public class DataSourcesCommand extends JdbcCommandSupport {
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- table.column("Name");
- table.column("Product");
- table.column("Version");
- table.column("URL");
-
- List<String> datasources = this.getJdbcService().datasources();
- for (String datasource : datasources) {
- Map<String, String> info = this.getJdbcService().info(datasource);
- table.addRow().addContent(datasource, info.get("db.product"), info.get("db.version"), info.get("url"));
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
deleted file mode 100644
index 6bf7236..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import org.apache.karaf.jdbc.command.completers.DataSourcesFileNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jdbc", name = "delete", description = "Delete a JDBC datasource")
-@Service
-public class DeleteCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "name", description = "The JDBC datasource name (the one used at creation time)", required = true, multiValued = false)
- @Completion(DataSourcesFileNameCompleter.class)
- String name;
-
- @Override
- public Object execute() throws Exception {
- this.getJdbcService().delete(name);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
deleted file mode 100644
index 480ab51..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jdbc", name = "execute", description = "Execute a SQL command on a given JDBC datasource")
-@Service
-public class ExecuteCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "datasource", description = "The JDBC datasource", required = true, multiValued = false)
- @Completion(DataSourcesNameCompleter.class)
- String datasource;
-
- @Argument(index = 1, name = "command", description = "The SQL command to execute", required = true, multiValued = false)
- String command;
-
- @Override
- public Object execute() throws Exception {
- this.getJdbcService().execute(datasource, command);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
deleted file mode 100644
index e53bbab..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-import java.util.Map;
-
-@Command(scope = "jdbc", name = "info", description = "Display details about a JDBC datasource")
-@Service
-public class InfoCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "datasource", description = "The JDBC datasource name", required = true, multiValued = false)
- @Completion(DataSourcesNameCompleter.class)
- String datasource;
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- table.column("Property");
- table.column("Value");
-
- Map<String, String> info = this.getJdbcService().info(datasource);
- for (String property : info.keySet()) {
- table.addRow().addContent(property, info.get(property));
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
deleted file mode 100644
index cf1eb58..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import org.apache.karaf.jdbc.JdbcService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-
-public abstract class JdbcCommandSupport implements Action {
-
- @Reference
- private JdbcService jdbcService;
-
- public JdbcService getJdbcService() {
- return jdbcService;
- }
-
- public void setJdbcService(JdbcService jdbcService) {
- this.jdbcService = jdbcService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
deleted file mode 100644
index 297288b..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Row;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jdbc", name = "query", description = "Execute a SQL query on a JDBC datasource")
-@Service
-public class QueryCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "datasource", description = "The JDBC datasource to use", required = true, multiValued = false)
- @Completion(DataSourcesNameCompleter.class)
- String datasource;
-
- @Argument(index = 1, name = "query", description = "The SQL query to execute", required = true, multiValued = false)
- String query;
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- Map<String, List<String>> map = this.getJdbcService().query(datasource, query);
- int rowCount = 0;
- for (String column : map.keySet()) {
- table.column(column);
- rowCount = map.get(column).size();
- }
-
- for (int i = 0; i < rowCount; i++) {
- Row row = table.addRow();
- for (String column : map.keySet()) {
- row.addContent(map.get(column).get(i));
- }
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
deleted file mode 100644
index 04baa70..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Row;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jdbc", name = "tables", description = "List the tables on a given JDBC datasource")
-@Service
-public class TablesCommand extends JdbcCommandSupport {
-
- @Argument(index = 0, name = "datasource", description = "The JDBC datasource to use", required = true, multiValued = false)
- @Completion(DataSourcesNameCompleter.class)
- String datasource;
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- Map<String, List<String>> map = this.getJdbcService().tables(datasource);
- int rowCount = 0;
- for (String column : map.keySet()) {
- table.column(column);
- rowCount = map.get(column).size();
- }
-
- for (int i = 0; i < rowCount; i++) {
- Row row = table.addRow();
- for (String column : map.keySet()) {
- row.addContent(map.get(column).get(i));
- }
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
deleted file mode 100644
index 8ba0fe9..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command.completers;
-
-import org.apache.karaf.jdbc.JdbcService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-import java.util.List;
-
-/**
- * Completer on the JDBC datasources file name.
- */
-@Service
-public class DataSourcesFileNameCompleter implements Completer {
-
- @Reference
- private JdbcService jdbcService;
-
- @Override
- public int complete(Session session, CommandLine commandLine, List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (String datasourceFileName : jdbcService.datasourceFileNames()) {
- delegate.getStrings().add(datasourceFileName.replace("datasource-", "").replace(".xml", ""));
- }
- } catch (Exception e) {
- // nothing to do
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
- public JdbcService getJdbcService() {
- return jdbcService;
- }
-
- public void setJdbcService(JdbcService jdbcService) {
- this.jdbcService = jdbcService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java b/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
deleted file mode 100644
index 238910f..0000000
--- a/jdbc/command/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.command.completers;
-
-import org.apache.karaf.jdbc.JdbcService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-import java.util.List;
-
-/**
- * Completer on the JDBC datasources name (JNDI or OSGi service property).
- */
-@Service
-public class DataSourcesNameCompleter implements Completer {
-
- @Reference
- private JdbcService jdbcService;
-
- @Override
- public int complete(Session session, CommandLine commandLine, List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (String datasource : jdbcService.datasources()) {
- delegate.getStrings().add(datasource);
- }
- } catch (Exception e) {
- // nothing to do
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
- public JdbcService getJdbcService() {
- return jdbcService;
- }
-
- public void setJdbcService(JdbcService jdbcService) {
- this.jdbcService = jdbcService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jdbc/command/src/main/resources/OSGI-INF/bundle.info b/jdbc/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index f4d4790..0000000
--- a/jdbc/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,26 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the shell commands to manipulate the JDBC service.
-
-The following commands are available:
-
-* jdbc:create
-* jdbc:delete
-* jdbc:datasources
-* jdbc:command
-* jdbc:query
-* jdbc:tables
-* jdbc:info
-
-h1. See also
-
-JDBC - section of the Karaf User Guide
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/NOTICE
----------------------------------------------------------------------
diff --git a/jdbc/core/NOTICE b/jdbc/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jdbc/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/pom.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/pom.xml b/jdbc/core/pom.xml
deleted file mode 100644
index 03fc7bd..0000000
--- a/jdbc/core/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.jdbc</groupId>
- <artifactId>jdbc</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.jdbc.core</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: JDBC :: Core</name>
- <description>This bundle provides core implementation of the JDBC service.</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf</groupId>
- <artifactId>org.apache.karaf.util</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>
- org.apache.karaf.jdbc
- </Export-Package>
- <Private-Package>
- org.apache.karaf.jdbc.internal,
- org.apache.karaf.util
- </Private-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java b/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
deleted file mode 100644
index 26165c8..0000000
--- a/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-import java.util.Map;
-
-/**
- * JDBC MBean
- */
-public interface JdbcMBean {
-
- /**
- * Get the list of JDBC datasources.
- *
- * @return a tabular data containing the list of JDBC datasources.
- * @throws MBeanException
- */
- TabularData getDatasources() throws MBeanException;
-
- /**
- * Create a JDBC datasource.
- *
- * @param name the JDBC datasource name.
- * @param type the JDBC datasource type (generic, MySQL, Oracle, Postgres, H2, HSQL, Derby, MSSQL).
- * @param driver the JDBC datasource driver class name (can be null).
- * @param version the target JDBC driver version (can be null).
- * @param url the JDBC URL.
- * @param user the database username.
- * @param password the database password.
- * @param installBundles true to install the bundles providing the JDBC driver, false to not install.
- * @throws MBeanException
- */
- void create(String name, String type, String driver, String version, String url, String user, String password, boolean installBundles) throws MBeanException;
-
- /**
- * Delete a JDBC datasource.
- *
- * @param name the JDBC datasource name (the one used at creation time).
- * @throws MBeanException
- */
- void delete(String name) throws MBeanException;
-
- /**
- * Get details about a JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @return a map (property/value) containing JDBC datasource details.
- * @throws MBeanException
- */
- Map<String, String> info(String datasource) throws MBeanException;
-
- /**
- * Get the tables available on a JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @return a tabular data containg datasource tables.
- * @throws MBeanException
- */
- TabularData tables(String datasource) throws MBeanException;
-
- /**
- * Execute a SQL command on a JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @param command the SQL command to execute.
- * @throws MBeanException
- */
- void execute(String datasource, String command) throws MBeanException;
-
- /**
- * Execute a SQL query on a JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @param query the SQL query to execute.
- * @return a tabular data with the result of execute (columns/values).
- * @throws MBeanException
- */
- TabularData query(String datasource, String query) throws MBeanException;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcService.java
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcService.java b/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcService.java
deleted file mode 100644
index d883a07..0000000
--- a/jdbc/core/src/main/java/org/apache/karaf/jdbc/JdbcService.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * JDBC Service.
- */
-public interface JdbcService {
-
- /**
- * Create a JDBC datasource (using a default template).
- *
- * @param name the JDBC datasource name.
- * @param type the backend database type (generic, Oracle, MySQL, ...)
- * @param driverClassName the JDBC driver classname.
- * @param version the JDBC driver version to use.
- * @param url the JDBC URL.
- * @param user the database user name.
- * @param password the database password.
- * @param tryToInstallBundles true to try to automatically install the required bundles (JDBC driver, etc) when possible, false else.
- */
- void create(String name, String type, String driverClassName, String version, String url, String user, String password, boolean tryToInstallBundles) throws Exception;
-
- /**
- * Delete a JDBC datasource identified by a name.
- *
- * @param name the JDBC datasource name.
- */
- void delete(String name) throws Exception;
-
- /**
- * List the JDBC datasources available.
- *
- * @return a list of datasources name.
- */
- List<String> datasources() throws Exception;
-
- /**
- * List the JDBC datasources configuration file names present in the deploy folder.
- *
- * @return a list of the JDBC datasources configuration file names.
- */
- List<String> datasourceFileNames() throws Exception;
-
- /**
- * Execute a SQL query on a given JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @param query the SQL query to execute.
- * @return the SQL query result (as a String).
- */
- Map<String, List<String>> query(String datasource, String query) throws Exception;
-
- /**
- * Execute a SQL command on a given JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @param command the SQL command to execute.
- */
- void execute(String datasource, String command) throws Exception;
-
- /**
- * List the tables available on a given JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @return the list of table names.
- */
- Map<String, List<String>> tables(String datasource) throws Exception;
-
- /**
- * Get detailed info about a JDBC datasource.
- *
- * @param datasource the JDBC datasource name.
- * @return a map of info (name/value).
- */
- Map<String, String> info(String datasource) throws Exception;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java b/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
deleted file mode 100644
index 11c7ca4..0000000
--- a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.internal;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.sql.*;
-import java.util.Deque;
-import java.util.LinkedList;
-
-import javax.sql.DataSource;
-import javax.sql.XAConnection;
-import javax.sql.XADataSource;
-
-import org.apache.karaf.util.StreamUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-public class JdbcConnector implements Closeable {
- private BundleContext bundleContext;
- private String datasourceName;
- private Connection connection;
- private Deque<Closeable> resources;
- private ServiceReference<?> reference;
-
- public JdbcConnector(BundleContext bundleContext, String datasourceName) {
- this.bundleContext = bundleContext;
- this.datasourceName = datasourceName;
- this.resources = new LinkedList<Closeable>();
- }
-
- public Connection connect() throws SQLException {
- reference = lookupDataSource(datasourceName);
- Object datasource = bundleContext.getService(reference);
- if (datasource instanceof DataSource) {
- connection = ((DataSource) datasource).getConnection();
- }
- if (datasource instanceof XADataSource) {
- connection = ((XADataSource) datasource).getXAConnection().getConnection();
- }
- return connection;
- }
-
- public Statement createStatement() throws SQLException {
- if (connection == null) {
- connect();
- }
- if (connection instanceof Connection) {
- return register(((Connection) connection).createStatement());
- }
- if (connection instanceof XAConnection) {
- return register(((XAConnection) connection).getConnection().createStatement());
- }
- return null;
- }
-
- public Connection register(final Connection connection) {
- resources.addFirst(new Closeable() {
-
- @Override
- public void close() throws IOException {
- try {
- connection.close();
- } catch (SQLException e) {
- // Ignore
- }
- }
- });
- return connection;
- }
-
- public Statement register(final Statement statement) {
- resources.addFirst(new Closeable() {
-
- @Override
- public void close() throws IOException {
- try {
- statement.close();
- } catch (SQLException e) {
- // Ignore
- }
- }
- });
- return statement;
- }
-
- public ResultSet register(final ResultSet resultSet) {
- resources.addFirst(new Closeable() {
-
- @Override
- public void close() throws IOException {
- try {
- resultSet.close();
- } catch (SQLException e) {
- // Ignore
- }
- }
- });
- return resultSet;
- }
-
-
- private ServiceReference<?> lookupDataSource(String name) {
- ServiceReference<?>[] references;
- try {
- references = bundleContext.getServiceReferences((String) null,
- "(&(|(" + Constants.OBJECTCLASS + "=" + DataSource.class.getName() + ")"
- + "(" + Constants.OBJECTCLASS + "=" + XADataSource.class.getName() + "))"
- + "(|(osgi.jndi.service.name=" + name + ")(datasource=" + name + ")(name=" + name + ")(service.id=" + name + ")))");
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Error finding datasource with name " + name, e);
- }
- if (references == null || references.length == 0) {
- throw new IllegalArgumentException("No JDBC datasource found for " + name);
- }
- if (references.length > 1) {
- throw new IllegalArgumentException("Multiple JDBC datasource found for " + name);
- }
- return references[0];
- }
-
- @Override
- public void close() {
- StreamUtils.close(resources.toArray(new Closeable[]{}));
- if (reference != null) {
- bundleContext.ungetService(reference);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java b/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
deleted file mode 100644
index 92bbba8..0000000
--- a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.internal;
-
-import org.apache.karaf.jdbc.JdbcMBean;
-import org.apache.karaf.jdbc.JdbcService;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.*;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Default implementation of the JDBC MBean.
- */
-public class JdbcMBeanImpl implements JdbcMBean {
-
- private JdbcService jdbcService;
-
- @Override
- public TabularData getDatasources() throws MBeanException {
- try {
- CompositeType type = new CompositeType("DataSource", "JDBC DataSource",
- new String[]{ "name", "product", "version", "url "},
- new String[]{ "Name", "Database product", "Database version", "JDBC URL" },
- new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING });
- TabularType tableType = new TabularType("JDBC DataSources", "Table of the JDBC DataSources",
- type, new String[]{ "name" });
- TabularData table = new TabularDataSupport(tableType);
-
- for (String datasource : jdbcService.datasources()) {
- Map<String, String> info = jdbcService.info(datasource);
- CompositeData data = new CompositeDataSupport(type,
- new String[]{ "name", "product", "version", "url" },
- new Object[]{ datasource, info.get("db.product"), info.get("db.version"), info.get("url") });
- table.put(data);
- }
-
- return table;
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public void create(String name, String type, String driver, String version, String url, String user, String password, boolean installBundles) throws MBeanException {
- try {
- jdbcService.create(name, type, driver, version, url, user, password, installBundles);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public void delete(String name) throws MBeanException {
- try {
- jdbcService.delete(name);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public Map<String, String> info(String datasource) throws MBeanException {
- try {
- return jdbcService.info(datasource);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public TabularData tables(String datasource) throws MBeanException {
- try {
- Map<String, List<String>> result = jdbcService.tables(datasource);
- OpenType[] stringTypes = new OpenType[result.keySet().size()];
- for (int i = 0; i < stringTypes.length; i++) {
- stringTypes[i] = SimpleType.STRING;
- }
- String[] columns = result.keySet().toArray(new String[result.keySet().size()]);
-
- CompositeType type = new CompositeType("Columns", "Columns",
- columns, columns, stringTypes);
- TabularType rows = new TabularType("Result", "Result Rows", type, columns);
- TabularData table = new TabularDataSupport(rows);
-
- int rowCount = result.get(result.keySet().iterator().next()).size();
-
- for (int i = 0; i < rowCount; i++) {
- Object[] row = new Object[columns.length];
- for (int j = 0; j < columns.length; j++) {
- row[j] = result.get(columns[j]).get(i);
- }
- CompositeData data = new CompositeDataSupport(type, columns, row);
- table.put(data);
- }
-
- return table;
- } catch (Exception e) {
- e.printStackTrace();
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public void execute(String datasource, String command) throws MBeanException {
- try {
- jdbcService.execute(datasource, command);
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- @Override
- public TabularData query(String datasource, String query) throws MBeanException {
- try {
- Map<String, List<String>> result = jdbcService.query(datasource, query);
- OpenType[] stringTypes = new OpenType[result.keySet().size()];
- for (int i = 0; i < stringTypes.length; i++) {
- stringTypes[i] = SimpleType.STRING;
- }
- String[] columns = result.keySet().toArray(new String[result.keySet().size()]);
-
- CompositeType type = new CompositeType("Columns", "Columns",
- columns, columns, stringTypes);
- TabularType rows = new TabularType("Result", "Result Rows", type, columns);
- TabularData table = new TabularDataSupport(rows);
-
- int rowCount = result.get(result.keySet().iterator().next()).size();
-
- for (int i = 0; i < rowCount; i++) {
- Object[] row = new Object[columns.length];
- for (int j = 0; j < columns.length; j++) {
- row[j] = result.get(columns[j]).get(i);
- }
- CompositeData data = new CompositeDataSupport(type, columns, row);
- table.put(data);
- }
-
- return table;
- } catch (Exception e) {
- throw new MBeanException(null, e.getMessage());
- }
- }
-
- public JdbcService getJdbcService() {
- return jdbcService;
- }
-
- public void setJdbcService(JdbcService jdbcService) {
- this.jdbcService = jdbcService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java b/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
deleted file mode 100644
index 50cf8ff..0000000
--- a/jdbc/core/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jdbc.internal;
-
-import org.apache.karaf.jdbc.JdbcService;
-import org.apache.karaf.util.TemplateUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-import javax.sql.DataSource;
-import javax.sql.XADataSource;
-
-import java.io.*;
-import java.sql.*;
-import java.util.*;
-
-/**
- * Default implementation of the JDBC Service.
- */
-public class JdbcServiceImpl implements JdbcService {
-
- public static enum TYPES {
- DB2("wrap:mvn:com.ibm.db2.jdbc/db2jcc/", "9.7", "datasource-db2.xml"),
- DERBY("mvn:org.apache.derby/derby/", "10.8.2.2", "datasource-derby.xml"),
- GENERIC(null, null, "datasource-generic.xml"),
- H2("mvn:com.h2database/h2/", "1.3.163", "datasource-h2.xml"),
- HSQL("mvn:org.hsqldb/hsqldb/", "2.3.2", "datasource-hsql.xml"),
- MYSQL("mvn:mysql/mysql-connector-java/", "5.1.18", "datasource-mysql.xml"),
- MSSQL("wrap:mvn:net.sourceforge.jtds/jtds/", "1.2.4", "datasource-mssql.xml"),
- ORACLE("wrap:mvn:ojdbc/ojdbc/", "11.2.0.2.0", "datasource-oracle.xml"),
- POSTGRES("wrap:mvn:postgresql/postgresql/", "9.1-901.jdbc4", "datasource-postgres.xml");
-
- private final String bundleUrl;
- private final String defaultVersion;
- private final String templateFile;
-
- TYPES(String bundleUrl, String defaultVersion, String templateFile) {
- this.bundleUrl = bundleUrl;
- this.defaultVersion = defaultVersion;
- this.templateFile = templateFile;
- }
-
- public void installBundle(BundleContext bundleContext, String version) throws Exception {
- String location = this.bundleUrl + getWithDefault(version, this.defaultVersion);
- bundleContext.installBundle(location, null).start();
- }
-
- private String getWithDefault(String st, String defaultSt) {
- return (st == null)? defaultSt : st;
- }
-
- public void copyDataSourceFile(File outFile, HashMap<String, String> properties) {
- InputStream is = this.getClass().getResourceAsStream(templateFile);
- if (is == null) {
- throw new IllegalArgumentException("Template resource " + templateFile + " doesn't exist");
- }
- TemplateUtils.createFromTemplate(outFile, is, properties);
- }
-
- }
-
- private BundleContext bundleContext;
-
- @Override
- public void create(String name, String type, String driverClassName, String version, String url, String user, String password, boolean tryToInstallBundles) throws Exception {
- if (type == null) {
- throw new IllegalStateException("No database type supplied");
- }
- TYPES dbType = TYPES.valueOf(type.toUpperCase());
-
- if (tryToInstallBundles) {
- dbType.installBundle(bundleContext, version);
- }
-
- File karafBase = new File(System.getProperty("karaf.base"));
- File deployFolder = new File(karafBase, "deploy");
- File outFile = new File(deployFolder, "datasource-" + name + ".xml");
-
- HashMap<String, String> properties = new HashMap<String, String>();
- properties.put("name", name);
- properties.put("driver", driverClassName);
- properties.put("url", url);
- properties.put("user", user);
- properties.put("password", password);
-
- dbType.copyDataSourceFile(outFile, properties);
- }
-
- @Override
- public void delete(String name) throws Exception {
- File karafBase = new File(System.getProperty("karaf.base"));
- File deployFolder = new File(karafBase, "deploy");
- File datasourceFile = new File(deployFolder, "datasource-" + name + ".xml");
- if (!datasourceFile.exists()) {
- throw new IllegalArgumentException("The JDBC datasource file "+ datasourceFile.getPath() + " doesn't exist");
- }
- datasourceFile.delete();
- }
-
- @Override
- public List<String> datasources() throws Exception {
- List<String> datasources = new ArrayList<String>();
-
- ServiceReference<?>[] references = bundleContext.getServiceReferences((String) null, "(|(" + Constants.OBJECTCLASS + "=" + DataSource.class.getName() + ")("
- + Constants.OBJECTCLASS + "=" + XADataSource.class.getName() + "))");
- if (references != null) {
- for (ServiceReference reference : references) {
- if (reference.getProperty("osgi.jndi.service.name") != null) {
- datasources.add((String) reference.getProperty("osgi.jndi.service.name"));
- } else if (reference.getProperty("datasource") != null) {
- datasources.add((String) reference.getProperty("datasource"));
- } else if (reference.getProperty("name") != null) {
- datasources.add((String) reference.getProperty("name"));
- } else {
- datasources.add(reference.getProperty(Constants.SERVICE_ID).toString());
- }
- }
- }
- return datasources;
- }
-
- @Override
- public List<String> datasourceFileNames() throws Exception {
- File karafBase = new File(System.getProperty("karaf.base"));
- File deployFolder = new File(karafBase, "deploy");
-
- String[] datasourceFileNames = deployFolder.list(new FilenameFilter() {
-
- @Override
- public boolean accept(File dir, String name) {
- return name.startsWith("datasource-") && name.endsWith(".xml");
- }
- });
-
- return Arrays.asList(datasourceFileNames);
- }
-
- @Override
- public Map<String, List<String>> query(String datasource, String query) throws Exception {
- JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
- try {
- Map<String, List<String>> map = new HashMap<String, List<String>>();
- Statement statement = jdbcConnector.createStatement();
- ResultSet resultSet = jdbcConnector.register(statement.executeQuery(query));
- ResultSetMetaData metaData = resultSet.getMetaData();
- for (int c = 1; c <= metaData.getColumnCount(); c++) {
- map.put(metaData.getColumnLabel(c), new ArrayList<String>());
- }
- while (resultSet.next()) {
- for (int c = 1; c <= metaData.getColumnCount(); c++) {
- map.get(metaData.getColumnLabel(c)).add(resultSet.getString(c));
- }
- }
- return map;
- } finally {
- jdbcConnector.close();
- }
- }
-
- @Override
- public void execute(String datasource, String command) throws Exception {
- JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
- try {
- jdbcConnector.createStatement().execute(command);
- } finally {
- jdbcConnector.close();
- }
- }
-
- @Override
- public Map<String, List<String>> tables(String datasource) throws Exception {
- JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
- try {
-
- DatabaseMetaData dbMetaData = jdbcConnector.connect().getMetaData();
- ResultSet resultSet = jdbcConnector.register(dbMetaData.getTables(null, null, null, null));
- ResultSetMetaData metaData = resultSet.getMetaData();
- Map<String, List<String>> map = new HashMap<String, List<String>>();
- for (int c = 1; c <= metaData.getColumnCount(); c++) {
- map.put(metaData.getColumnLabel(c), new ArrayList<String>());
- }
- while (resultSet.next()) {
- for (int c = 1; c <= metaData.getColumnCount(); c++) {
- map.get(metaData.getColumnLabel(c)).add(resultSet.getString(c));
- }
- }
- return map;
- } finally {
- jdbcConnector.close();
- }
- }
-
- @Override
- public Map<String, String> info(String datasource) throws Exception {
- JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
- try {
- DatabaseMetaData dbMetaData = jdbcConnector.connect().getMetaData();
- Map<String, String> map = new HashMap<String, String>();
- map.put("db.product", dbMetaData.getDatabaseProductName());
- map.put("db.version", dbMetaData.getDatabaseProductVersion());
- map.put("url", dbMetaData.getURL());
- map.put("username", dbMetaData.getUserName());
- map.put("driver.name", dbMetaData.getDriverName());
- map.put("driver.version", dbMetaData.getDriverVersion());
- return map;
- } finally {
- jdbcConnector.close();
- }
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml b/jdbc/core/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
deleted file mode 100644
index e961697..0000000
--- a/jdbc/core/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
- default-activation="lazy">
-
- <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
- <bean id="jdbcService" class="org.apache.karaf.jdbc.internal.JdbcServiceImpl">
- <property name="bundleContext" ref="blueprintBundleContext"/>
- </bean>
-
- <service ref="jdbcService" interface="org.apache.karaf.jdbc.JdbcService" />
-
- <!-- Management -->
- <bean id="jdbcMBeanImpl" class="org.apache.karaf.jdbc.internal.JdbcMBeanImpl">
- <property name="jdbcService" ref="jdbcService"/>
- </bean>
-
- <service ref="jdbcMBeanImpl" auto-export="interfaces">
- <service-properties>
- <entry key="jmx.objectname" value="org.apache.karaf:type=jdbc,name=$[karaf.name]"/>
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/OSGI-INF/bundle.info b/jdbc/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index bc7a1cd..0000000
--- a/jdbc/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,18 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the JDBC service support.
-
-The JDBC service allows you to create datasources, see the defined datasources, execute query on a datasource, etc.
-
-h1. See also
-
-JDBC - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
deleted file mode 100644
index da220a5..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="com.ibm.db2.jcc.DB2DataSource">
- <property name="url" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
deleted file mode 100644
index 440a439..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- default-activation="eager">
-
- <bean id="dataSource" class="org.apache.derby.jdbc.EmbeddedXADataSource">
- <property name="databaseName" value="${name}"/>
- <property name="createDatabase" value="create" />
- </bean>
-
- <service ref="dataSource" interface="javax.sql.DataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-
- <service ref="dataSource" interface="javax.sql.XADataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}xa"/>
- </service-properties>
- </service>
-
-</blueprint>
[14/33] git commit: Make sure aries-util is not referenced in the
framework car
Posted by gn...@apache.org.
Make sure aries-util is not referenced in the framework car
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/edd82fda
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/edd82fda
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/edd82fda
Branch: refs/heads/master
Commit: edd82fda337ed048b7c8fa24bb51c917d89bdaea
Parents: 0c8e8a8
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 19:16:08 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:04 2014 +0200
----------------------------------------------------------------------
assemblies/features/framework/pom.xml | 4 ----
shell/core/pom.xml | 10 ----------
2 files changed, 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/edd82fda/assemblies/features/framework/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/pom.xml b/assemblies/features/framework/pom.xml
index 4675b0a..fd73a47 100644
--- a/assemblies/features/framework/pom.xml
+++ b/assemblies/features/framework/pom.xml
@@ -173,10 +173,6 @@
</dependency>
<dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.core</artifactId>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.core</artifactId>
</dependency>
http://git-wip-us.apache.org/repos/asf/karaf/blob/edd82fda/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index 92c7555..572430c 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -68,16 +68,6 @@
</dependency>
<dependency>
- <groupId>org.apache.aries.blueprint</groupId>
- <artifactId>org.apache.aries.blueprint.api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.aries.blueprint</groupId>
- <artifactId>org.apache.aries.blueprint.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.gogo.runtime</artifactId>
<scope>provided</scope>
[16/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
deleted file mode 100644
index bed8104..0000000
--- a/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import org.apache.karaf.features.TestBase;
-
-public class BundleManagerTest extends TestBase {
-
- /*
- @Test
- public void testfindBundlestoRefreshWithHostToRefresh() throws Exception {
- Bundle hostBundle = createDummyBundle(12345l, "Host", headers());
- Bundle fragmentBundle = createDummyBundle(54321l, "fragment", headers(Constants.FRAGMENT_HOST, "Host"));
-
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- BundleManager bundleManager = new BundleManager(bundleContext);
-
- // Host was already installed, fragment is new
- Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(hostBundle, fragmentBundle));
- Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(fragmentBundle));
-
- replay(bundleContext);
- Set<Bundle> bundles = bundleManager.findBundlesWithFragmentsToRefresh(existing, installed);
- EasyMock.verify(bundleContext);
-
- Assert.assertEquals(1, bundles.size());
- Assert.assertEquals(hostBundle, bundles.iterator().next());
- }
-
- @Test
- public void testfindBundlestoRefreshWithOptionalPackages() throws Exception {
- Bundle exporterBundle = createDummyBundle(12345l, "exporter", headers(Constants.EXPORT_PACKAGE, "org.my.package"));
- Bundle importerBundle = createDummyBundle(54321l, "importer", headers(Constants.IMPORT_PACKAGE, "org.my.package;resolution:=optional"));
-
- BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
- BundleManager bundleManager = new BundleManager(bundleContext);
-
- // Importer was already installed, exporter is new
- Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(importerBundle, exporterBundle));
- Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(exporterBundle));
-
- replay(bundleContext);
- Set<Bundle> bundles = bundleManager.findBundlesWithOptionalPackagesToRefresh(existing, installed);
- EasyMock.verify(bundleContext);
-
- Assert.assertEquals(1, bundles.size());
- Assert.assertEquals(importerBundle, bundles.iterator().next());
- }
- */
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
deleted file mode 100644
index b8b5fc0..0000000
--- a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Map;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.TestBase;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test cases for {@link org.apache.karaf.features.internal.service.FeaturesServiceImpl}
- */
-public class FeaturesServiceImplTest extends TestBase {
-
- File dataFile;
-
- @Before
- public void setUp() throws IOException {
- dataFile = File.createTempFile("features", null, null);
- }
-
- @Test
- public void testGetFeature() throws Exception {
- Feature transactionFeature = feature("transaction", "1.0.0");
- final Map<String, Map<String, Feature>> features = features(transactionFeature);
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
- protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
- return features;
- }
- };
- assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
- assertSame(transactionFeature, impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
- }
-
- @Test
- public void testGetFeatureStripVersion() throws Exception {
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
- protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
- return features(feature("transaction", "1.0.0"));
- }
- };
- Feature feature = impl.getFeature("transaction", " 1.0.0 ");
- assertNotNull(feature);
- assertSame("transaction", feature.getName());
- }
-
- @Test
- public void testGetFeatureNotAvailable() throws Exception {
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
- protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
- return features(feature("transaction", "1.0.0"));
- }
- };
- assertNull(impl.getFeature("activemq", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
- }
-
- @Test
- public void testGetFeatureHighestAvailable() throws Exception {
- final Map<String, Map<String, Feature>> features = features(
- feature("transaction", "1.0.0"),
- feature("transaction", "2.0.0")
- );
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
- protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
- return features;
- }
- };
- assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
- assertSame("2.0.0", impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION).getVersion());
- }
-
- /**
- * This test ensures that every feature get installed only once, even if it appears multiple times in the list
- * of transitive feature dependencies (KARAF-1600)
- */
- /*
- @Test
- @SuppressWarnings("unchecked")
- public void testNoDuplicateFeaturesInstallation() throws Exception {
- final List<Feature> installed = new LinkedList<Feature>();
- BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
- expect(bundleManager.installBundleIfNeeded(EasyMock.anyObject(String.class), EasyMock.anyInt(), EasyMock.anyObject(String.class)))
- .andReturn(new BundleInstallerResult(createDummyBundle(1l, "", headers()), true)).anyTimes();
- bundleManager.refreshBundles(EasyMock.anyObject(Set.class), EasyMock.anyObject(Set.class), EasyMock.anyObject(EnumSet.class));
- EasyMock.expectLastCall();
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(bundleManager, null) {
- // override methods which refers to bundle context to avoid mocking everything
- @Override
- protected boolean loadState() {
- return true;
- }
-
- @Override
- protected void saveState() {
-
- }
-
- @Override
- protected void doInstallFeature(InstallationState state, Feature feature, boolean verbose) throws Exception {
- installed.add(feature);
-
- super.doInstallFeature(state, feature, verbose);
- }
-
- };
- replay(bundleManager);
- impl.addRepository(getClass().getResource("repo2.xml").toURI());
- impl.installFeature("all");
-
- // copying the features to a set to filter out the duplicates
- Set<Feature> noduplicates = new HashSet<Feature>();
- noduplicates.addAll(installed);
-
- assertEquals("Every feature should only have been installed once", installed.size(), noduplicates.size());
- }
-
- @Test
- public void testGetOptionalImportsOnly() {
- BundleManager bundleManager = new BundleManager(null, 0l);
-
- List<Clause> result = bundleManager.getOptionalImports("org.apache.karaf,org.apache.karaf.optional;resolution:=optional");
- assertEquals("One optional import expected", 1, result.size());
- assertEquals("org.apache.karaf.optional", result.get(0).getName());
-
- result = bundleManager.getOptionalImports(null);
- assertNotNull(result);
- assertEquals("No optional imports expected", 0, result.size());
- }
- */
-
- static class Storage extends StateStorage {
- @Override
- protected InputStream getInputStream() throws IOException {
- return null;
- }
- @Override
- protected OutputStream getOutputStream() throws IOException {
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
deleted file mode 100644
index 9e33ee3..0000000
--- a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.InputStream;
-import java.net.URL;
-
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.internal.model.Features;
-import org.apache.karaf.features.internal.model.JaxbUtil;
-import org.junit.Test;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-public class FeaturesValidationTest {
-
- @Test
- public void testNs10() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
- }
-
- @Test
- public void testNs10Unmarshall() throws Exception {
- URL url = getClass().getResource("f02.xml");
- Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
- assertNotNull(features);
- }
-
- @Test
- public void testNs10NoName() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f03.xml").toURI());
- }
-
- @Test
- public void testNs10NoNameUnmarshall() throws Exception {
- URL url = getClass().getResource("f03.xml");
- Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
- assertNotNull(features);
- }
-
- @Test
- public void testNs11() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f04.xml").toURI());
- }
-
- @Test
- public void testNs11Unmarshall() throws Exception {
- URL url = getClass().getResource("f04.xml");
- Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
- assertNotNull(features);
- }
-
- @Test
- public void testNs11NoName() throws Exception {
- try {
- FeatureValidationUtil.validate(getClass().getResource("f05.xml").toURI());
- fail("Validation should have failed");
- } catch (Exception e) {
- // ok
- }
- }
-
- @Test
- public void testNs12() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
- }
-
- @Test
- public void testNs12Unmarshall() throws Exception {
- URL url = getClass().getResource("f06.xml");
- Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
- assertNotNull(features);
- }
-
- @Test
- public void testNs13() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f07.xml").toURI());
- }
-
- @Test
- public void testNs13Unmarshall() throws Exception {
- URL url = getClass().getResource("f07.xml");
- Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
- assertNotNull(features);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
deleted file mode 100644
index d9093d5..0000000
--- a/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.internal.model.Bundle;
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.apache.karaf.features.internal.resolver.UriNamespace;
-import org.junit.Before;
-import org.junit.Test;
-import org.ops4j.pax.tinybundles.core.TinyBundles;
-import org.osgi.framework.BundleException;
-import org.osgi.resource.Resource;
-
-import static org.apache.karaf.features.internal.resolver.UriNamespace.getUri;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class OverridesTest {
-
- private String bsn = "bsn";
- private Resource b100;
- private Resource b101;
- private Resource b102;
- private Resource b110;
- private Resource c100;
- private Resource c101;
- private Resource c110;
-
- @Before
- public void setUp() throws BundleException {
- b100 = resource("karaf-100.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.0.0")
- .build();
-
- b101 = resource("karaf-101.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.0.1")
- .build();
-
- b102 = resource("karaf-102.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.0.2")
- .build();
-
- b110 = resource("karaf-110.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.1.0")
- .build();
-
- c100 = resource("karafc-100.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.0.0")
- .set("Bundle-Vendor", "Apache")
- .build();
-
- c101 = resource("karafc-101.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.0.1")
- .set("Bundle-Vendor", "NotApache")
- .build();
-
- c110 = resource("karafc-110.jar")
- .set("Bundle-SymbolicName", bsn)
- .set("Bundle-Version", "1.1.0")
- .set("Bundle-Vendor", "NotApache")
- .build();
- }
-
- @Test
- public void testDifferentVendors() throws IOException {
- Map<String, Resource> map = asResourceMap(c100, c101, c110);
- assertEquals(c100, map.get(getUri(c100)));
- Overrides.override(map, Arrays.asList(getUri(c101), getUri(c110)));
- assertEquals(c101, map.get(getUri(c100)));
- }
-
- @Test
- public void testMatching101() throws IOException {
- Map<String, Resource> map = asResourceMap(b100, b101, b110);
- assertEquals(b100, map.get(getUri(b100)));
- Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110)));
- assertEquals(b101, map.get(getUri(b100)));
- }
-
- @Test
- public void testMatching102() throws IOException {
- Map<String, Resource> map = asResourceMap(b100, b101, b102, b110);
- assertEquals(b100, map.get(getUri(b100)));
- Overrides.override(map, Arrays.asList(getUri(b101), getUri(b102), getUri(b110)));
- assertEquals(b102, map.get(getUri(b100)));
- }
-
- @Test
- public void testMatchingRange() throws IOException {
- Map<String, Resource> map = asResourceMap(b100, b101, b110);
- assertEquals(b100, map.get(getUri(b100)));
- Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110) + ";range=\"[1.0, 2.0)\""));
- assertEquals(b110, map.get(getUri(b100)));
- }
-
- @Test
- public void testNotMatching() throws IOException {
- Map<String, Resource> map = asResourceMap(b100, b110);
- assertEquals(b100, map.get(getUri(b100)));
- Overrides.override(map, Arrays.asList(getUri(b110)));
- assertEquals(b100, map.get(getUri(b100)));
- }
-
- @Test
- public void testLoadOverrides() {
- Set<String> overrides = Overrides.loadOverrides(getClass().getResource("overrides.properties").toExternalForm());
- assertEquals(2, overrides.size());
-
- Clause karafAdminCommand = null;
- Clause karafAdminCore = null;
- for (Clause clause : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
- if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X")) {
- karafAdminCommand = clause;
- }
- if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X")) {
- karafAdminCore = clause;
- }
- }
- assertNotNull("Missing admin.command bundle override", karafAdminCommand);
- assertNotNull("Missing admin.core bundle override", karafAdminCore);
- assertNotNull("Missing range on admin.core override", karafAdminCore.getAttribute(Overrides.OVERRIDE_RANGE));
- }
-
- /**
- * Copies the content of {@link java.io.InputStream} to {@link java.io.OutputStream}.
- *
- * @param input
- * @param output
- * @throws java.io.IOException
- */
- private void copy(final InputStream input, final OutputStream output) throws IOException {
- byte[] buffer = new byte[1024 * 16];
- int n;
- while (-1 != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- output.flush();
- }
- input.close();
- output.close();
- }
-
- static Builder resource(String uri) {
- return new Builder(uri);
- }
-
- static Map<String, Resource> asResourceMap(Resource... resources) {
- Map<String, Resource> map = new HashMap<String, Resource>();
- for (Resource resource : resources) {
- map.put(getUri(resource), resource);
- }
- return map;
- }
-
- static class Builder {
- String uri;
- Map<String,String> headers = new HashMap<String,String>();
- Builder(String uri) {
- this.uri = uri;
- this.headers.put("Bundle-ManifestVersion", "2");
- }
- Builder set(String key, String value) {
- this.headers.put(key, value);
- return this;
- }
- Resource build() throws BundleException {
- return ResourceBuilder.build(uri, headers);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
deleted file mode 100644
index 814c722..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="karaf-2.0.0">
- <feature name="spring" version="3.0.3.RELEASE">
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-asm/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-expression/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-beans/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-aop/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-context/3.0.3.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-context-support/3.0.3.RELEASE</bundle>
- </feature>
- <feature name="spring-dm" version="1.2.0">
- <feature version="3.0.3.RELEASE">spring</feature>
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.0</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.0</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.0</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.0</bundle>
- <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.0.0</bundle>
- </feature>
- <feature name="wrapper" version="2.0.0">
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.0.0</bundle>
- </feature>
- <feature name="obr" version="2.0.0">
- <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.0.0</bundle>
- <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.0.0</bundle>
- </feature>
- <feature name="http" version="2.0.0">
- <config name="org.ops4j.pax.web">
- org.osgi.service.http.port=8181
- </config>
- <bundle>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
- <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jetty-bundle/6.1.22_1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-api/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-spi/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/0.7.2</bundle>
- </feature>
- <feature name="war" version="2.0.0">
- <feature version="2.0.0">http</feature>
- <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/0.7.2</bundle>
- <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.1.3</bundle>
- <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.war/2.0.0</bundle>
- </feature>
- <feature name="webconsole" version="2.0.0">
- <feature version="2.0.0">http</feature>
- <config name="org.apache.karaf.webconsole">
- realm=karaf
- </config>
- <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.2</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.0.0</bundle>
- <bundle>mvn:org.apache.felix/org.apache.felix.webconsole/3.1.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.0.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.0.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.0.0</bundle>
- </feature>
- <feature name="ssh" version="2.0.0">
- <config name="org.apache.karaf.shell.ssh">
- sshPort=8101
- sshHost=0.0.0.0
- sshRealm=karaf
- </config>
- <bundle>mvn:org.apache.mina/mina-core/2.0.0-RC1</bundle>
- <bundle>mvn:org.apache.sshd/sshd-core/0.4.0</bundle>
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.0.0</bundle>
- </feature>
- <feature name="management" version="2.0.0">
- <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.0.0</bundle>
- <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.1-r964701</bundle>
- <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.1-r964701</bundle>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
deleted file mode 100644
index 1578faa..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="karaf-2.2.0" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- </feature>
- <feature name="spring-web" version="2.5.6.SEC02" resolver="(obr)">
- <feature version="2.5.6.SEC02">spring</feature>
- <feature version="2.2.0">http</feature>
- <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-webmvc/2.5.6.SEC02</bundle>
- </feature>
- <feature name="spring" version="3.0.5.RELEASE" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-asm/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-expression/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-beans/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-aop/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-context/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-context-support/3.0.5.RELEASE</bundle>
- </feature>
- <feature name="spring-web" version="3.0.5.RELEASE" resolver="(obr)">
- <feature version="3.0.5.RELEASE">spring</feature>
- <feature version="2.2.0">http</feature>
- <bundle>mvn:org.springframework/spring-web/3.0.5.RELEASE</bundle>
- <bundle>mvn:org.springframework/spring-webmvc/3.0.5.RELEASE</bundle>
- </feature>
- <feature name="spring-dm" version="1.2.1" resolver="(obr)">
- <feature version="[2.5.6,4)">spring</feature>
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.1</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.1</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.1</bundle>
- <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.1</bundle>
- <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.2.0</bundle>
- </feature>
- <feature name="spring-dm-web" version="1.2.1" resolver="(obr)">
- <feature version="1.2.1">spring-dm</feature>
- <feature version="[2.5.6,4)">spring-web</feature>
- <feature version="2.2.0">http</feature>
- <bundle>mvn:org.springframework.osgi/spring-osgi-web/1.2.1</bundle>
- </feature>
- <feature name="wrapper" version="2.2.0">
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.2.0</bundle>
- </feature>
- <feature name="obr" version="2.2.0">
- <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.2.0</bundle>
- <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.2.0</bundle>
- </feature>
- <feature name="config" version="2.2.0">
- <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.config/2.2.0</bundle>
- </feature>
- <feature name="jetty" version="7.2.2.v20101205" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.asm/3.3_1</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-util/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-io/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-http/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-continuation/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-server/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-security/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-servlet/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-xml/7.2.2.v20101205</bundle>
- </feature>
- <feature name="jetty-jaas" version="7.2.2.v20101205" resolver="(obr)">
- <feature version="[7.0,8.0)">jetty</feature>
- <bundle dependency='true'>mvn:javax.mail/mail/1.4.3</bundle>
- <bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-webapp/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-jndi/7.2.2.v20101205</bundle>
- <bundle>mvn:org.eclipse.jetty/jetty-plus/7.2.2.v20101205</bundle>
- </feature>
- <feature name="http" version="2.2.0" resolver="(obr)">
- <configfile finalname="/etc/jetty.xml">mvn:org.apache.karaf/apache-karaf/2.2.0/xml/jettyconfig</configfile>
- <config name="org.ops4j.pax.web">
- org.osgi.service.http.port=8181
- javax.servlet.context.tempdir=${karaf.data}/pax-web-jsp
- org.ops4j.pax.web.config.file=${karaf.etc}/jetty.xml
- </config>
- <feature version="[7.0,8.0)">jetty</feature>
- <bundle>mvn:org.ops4j.pax.web/pax-web-api/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-spi/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/1.0.1</bundle>
- </feature>
- <feature name="war" version="2.2.0" resolver="(obr)">
- <config name="org.ops4j.pax.url.war">
- org.ops4j.pax.url.war.importPaxLoggingPackages=true
- </config>
- <feature>http</feature>
- <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.web/2.2.0</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.web/pax-web-deployer/1.0.1</bundle>
- <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.2.5</bundle>
- </feature>
- <feature name="kar" version="2.2.0">
- <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/2.2.0</bundle>
- </feature>
- <feature name="webconsole-base" version="2.2.0">
- <config name="org.apache.karaf.webconsole">
- realm=karaf
- </config>
- <feature>http</feature>
- <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.4</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.2.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.console/2.2.0</bundle>
- </feature>
- <feature name="webconsole" version="2.2.0">
- <feature version="2.2.0">webconsole-base</feature>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.2.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.2.0</bundle>
- <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.2.0</bundle>
- <bundle>mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/1.0.2</bundle>
- </feature>
- <feature name="ssh" version="2.2.0">
- <config name="org.apache.karaf.shell">
- sshPort=8101
- sshHost=0.0.0.0
- sshRealm=karaf
- hostKey=${karaf.etc}/host.key
- </config>
- <bundle dependency='true'>mvn:org.apache.mina/mina-core/2.0.1</bundle>
- <bundle dependency='true'>mvn:org.apache.sshd/sshd-core/0.5.0</bundle>
- <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.2.0</bundle>
- </feature>
- <feature name="management" version="2.2.0">
- <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.2.0</bundle>
- <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.3</bundle>
- <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.3</bundle>
- </feature>
- <feature name="eventadmin" version="2.2.0">
- <bundle start-level='30'>mvn:org.apache.felix/org.apache.felix.eventadmin/1.2.8</bundle>
- </feature>
- <feature name="jasypt-encryption" version="2.2.0" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/1.3_3</bundle>
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/2.4_4</bundle>
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1</bundle>
- <bundle>mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.jasypt/2.2.0</bundle>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
deleted file mode 100644
index c058095..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
deleted file mode 100644
index 85f28ad..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- </feature>
-</features>
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
deleted file mode 100644
index 15d84e2..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- </feature>
-</features>
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
deleted file mode 100644
index 51e78f1..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- <conditional>
- <condition>http</condition>
- <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
- </conditional>
- <conditional>
- <condition>req:osgi.ee;filter:="(&(osgi.ee=JavaSE)(!(version>=1.7)))"</condition>
- <bundle start="true" start-level="30">mvn:org.apache.mina/mina-core/${mina.version}</bundle>
- </conditional>
- </feature>
-</features>
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
deleted file mode 100644
index 5b7dd90..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
- <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
- <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
- <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
- <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
- <conditional>
- <condition>http</condition>
- <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
- </conditional>
- <capability>
- service-reference;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
- </capability>
- </feature>
-</features>
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties b/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
deleted file mode 100644
index d34fa7e..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-
-################################################################################
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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.
-#
-################################################################################
-
-# Sample etc/overrides.properties file for testing purposes
-mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X
-mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X;range=[2.3.0,2.5)
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
deleted file mode 100644
index 5fd51d0..0000000
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="repo2">
- <feature name="common">
- <bundle>b1</bundle>
- </feature>
- <feature name="f1">
- <feature>common</feature>
- <bundle>b2</bundle>
- </feature>
- <feature name="f2">
- <feature>common</feature>
- <feature>f1</feature>
- <bundle>b3</bundle>
- </feature>
- <feature name="f3">
- <feature>f1</feature>
- <feature>f2</feature>
- <bundle>b4</bundle>
- </feature>
- <feature name="all">
- <feature>f1</feature>
- <feature>f2</feature>
- <feature>f3</feature>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/repo1.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo1.xml b/features/src/test/resources/org/apache/karaf/features/repo1.xml
deleted file mode 100644
index 641ef12..0000000
--- a/features/src/test/resources/org/apache/karaf/features/repo1.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
- <repository>urn:r1</repository>
- <feature name="f1" region="foo">
- <config name="c1">
- k=v
- </config>
- <bundle>b1</bundle>
- <bundle>b2</bundle>
- </feature>
- <feature name="f2">
- <feature>f1</feature>
- <bundle>b3</bundle>
- </feature>
- <feature name="f3">
- <configfile finalname="cf1" override="true">cfloc</configfile>
- <bundle>b4</bundle>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/repo2.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo2.xml b/features/src/test/resources/org/apache/karaf/features/repo2.xml
deleted file mode 100644
index f5e96ae..0000000
--- a/features/src/test/resources/org/apache/karaf/features/repo2.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
- <repository>
- urn:r1
- </repository>
- <feature name="f1" region="foo">
- <config name="c1">
- k=v
- </config>
- <bundle>b1</bundle>
- <bundle>b2</bundle>
- </feature>
- <feature name="f2">
- <feature>f1</feature>
- <bundle>b3</bundle>
- </feature>
- <feature name="f3">
- <configfile finalname="cf1" override="true">cfloc</configfile>
- <bundle>b4</bundle>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/test/resources/org/apache/karaf/features/repo3.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo3.xml b/features/src/test/resources/org/apache/karaf/features/repo3.xml
deleted file mode 100644
index ffe08ed..0000000
--- a/features/src/test/resources/org/apache/karaf/features/repo3.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
- <feature name="f1">
- <capability>
- cap
- </capability>
- <requirement>
- req
- </requirement>
- </feature>
-</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/instance/pom.xml
----------------------------------------------------------------------
diff --git a/instance/pom.xml b/instance/pom.xml
index baeb2f9..8d6ba13 100644
--- a/instance/pom.xml
+++ b/instance/pom.xml
@@ -70,7 +70,7 @@
<dependency>
<groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.core</artifactId>
+ <artifactId>org.apache.karaf.features.command</artifactId>
<optional>true</optional>
</dependency>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/kar/pom.xml
----------------------------------------------------------------------
diff --git a/kar/pom.xml b/kar/pom.xml
index 78629f6..8612252 100644
--- a/kar/pom.xml
+++ b/kar/pom.xml
@@ -65,7 +65,7 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.core</artifactId>
+ <artifactId>org.apache.karaf.features.command</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 48c5951..6a0dcb4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -509,6 +509,11 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
+ <artifactId>org.apache.karaf.features.command</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.obr</artifactId>
<version>${project.version}</version>
</dependency>
[18/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java b/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
deleted file mode 100644
index 233a8a2..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.felix.utils.version.VersionRange;
-import org.osgi.framework.Version;
-import org.osgi.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.felix.resolver.Util.getSymbolicName;
-import static org.apache.felix.resolver.Util.getVersion;
-
-/**
- * Helper class to deal with overriden bundles at feature installation time.
- */
-public class Overrides {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Overrides.class);
-
- protected static final String OVERRIDE_RANGE = "range";
-
- /**
- * Compute a list of bundles to install, taking into account overrides.
- *
- * The file containing the overrides will be loaded from the given url.
- * Blank lines and lines starting with a '#' will be ignored, all other lines
- * are considered as urls to override bundles.
- *
- * The list of resources to resolve will be scanned and for each bundle,
- * if a bundle override matches that resource, it will be used instead.
- *
- * Matching is done on bundle symbolic name (they have to be the same)
- * and version (the bundle override version needs to be greater than the
- * resource to be resolved, and less than the next minor version. A range
- * directive can be added to the override url in which case, the matching
- * will succeed if the resource to be resolved is within the given range.
- *
- * @param resources the list of resources to resolve
- * @param overrides list of bundle overrides
- */
- public static void override(Map<String, Resource> resources, Collection<String> overrides) {
- // Do override replacement
- for (Clause override : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
- String url = override.getName();
- String vr = override.getAttribute(OVERRIDE_RANGE);
- Resource over = resources.get(url);
- if (over == null) {
- // Ignore invalid overrides
- continue;
- }
- for (String uri : new ArrayList<String>(resources.keySet())) {
- Resource res = resources.get(uri);
- if (getSymbolicName(res).equals(getSymbolicName(over))) {
- VersionRange range;
- if (vr == null) {
- // default to micro version compatibility
- Version v1 = getVersion(res);
- Version v2 = new Version(v1.getMajor(), v1.getMinor() + 1, 0);
- range = new VersionRange(false, v1, v2, true);
- } else {
- range = VersionRange.parseVersionRange(vr);
- }
- // The resource matches, so replace it with the overridden resource
- // if the override is actually a newer version than what we currently have
- if (range.contains(getVersion(over)) && getVersion(res).compareTo(getVersion(over)) < 0) {
- resources.put(uri, over);
- }
- }
- }
- }
- }
-
- public static Set<String> loadOverrides(String overridesUrl) {
- Set<String> overrides = new HashSet<String>();
- try {
- if (overridesUrl != null) {
- InputStream is = new URL(overridesUrl).openStream();
- try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- String line;
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- if (!line.isEmpty() && !line.startsWith("#")) {
- overrides.add(line);
- }
- }
- } finally {
- is.close();
- }
- }
- } catch (Exception e) {
- LOGGER.debug("Unable to load overrides bundles list", e);
- }
- return overrides;
- }
-
- public static String extractUrl(String override) {
- Clause[] cs = Parser.parseClauses(new String[] { override });
- if (cs.length != 1) {
- throw new IllegalStateException("Override contains more than one clause: " + override);
- }
- return cs[0].getName();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
deleted file mode 100644
index 56e5102..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.net.URI;
-
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.internal.model.Features;
-import org.apache.karaf.features.internal.model.JaxbUtil;
-
-/**
- * The repository implementation.
- */
-public class RepositoryImpl implements Repository {
-
- private final URI uri;
- private Features features;
-
- public RepositoryImpl(URI uri) {
- this.uri = uri;
- }
-
- public URI getURI() {
- return uri;
- }
-
- public String getName() throws IOException {
- load();
- return features.getName();
- }
-
- public URI[] getRepositories() throws Exception {
- load();
- URI[] result = new URI[features.getRepository().size()];
- for (int i = 0; i < features.getRepository().size(); i++) {
- String uri = features.getRepository().get(i);
- uri = uri.trim();
- result[i] = URI.create(uri);
- }
- return result;
- }
-
- public org.apache.karaf.features.Feature[] getFeatures() throws Exception {
- load();
- return features.getFeature().toArray(new org.apache.karaf.features.Feature[features.getFeature().size()]);
- }
-
-
- public void load() throws IOException {
- load(false);
- }
-
- public void load(boolean validate) throws IOException {
- if (features == null) {
- try {
- InputStream inputStream = uri.toURL().openStream();
- inputStream = new FilterInputStream(inputStream) {
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (Thread.currentThread().isInterrupted()) {
- throw new InterruptedIOException();
- }
- return super.read(b, off, len);
- }
- };
- try {
- features = JaxbUtil.unmarshal(uri.toASCIIString(), inputStream, validate);
- } finally {
- inputStream.close();
- }
- } catch (IllegalArgumentException e) {
- throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
- } catch (Exception e) {
- throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
- }
- }
- }
-
- @Override
- public boolean isValid() {
- throw new UnsupportedOperationException();
- }
-}
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java b/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
deleted file mode 100644
index 96b99ee..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import org.apache.karaf.features.internal.resolver.CapabilitySet;
-import org.apache.karaf.features.internal.resolver.SimpleFilter;
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-public class RequirementSort<T extends Resource> {
-
- /**
- * Sorts {@link Resource} based on their {@link Requirement}s and {@link Capability}s.
- */
- public static <T extends Resource> Collection<T> sort(Collection<T> resources) {
- Set<String> namespaces = new HashSet<String>();
- for (Resource r : resources) {
- for (Capability cap : r.getCapabilities(null)) {
- namespaces.add(cap.getNamespace());
- }
- }
- CapabilitySet capSet = new CapabilitySet(new ArrayList<String>(namespaces));
- for (Resource r : resources) {
- for (Capability cap : r.getCapabilities(null)) {
- capSet.addCapability(cap);
- }
- }
- Set<T> sorted = new LinkedHashSet<T>();
- Set<T> visited = new LinkedHashSet<T>();
- for (T r : resources) {
- visit(r, visited, sorted, capSet);
- }
- return sorted;
- }
-
-
- private static <T extends Resource> void visit(T resource, Set<T> visited, Set<T> sorted, CapabilitySet capSet) {
- if (!visited.add(resource)) {
- return;
- }
- for (T r : collectDependencies(resource, capSet)) {
- visit(r, visited, sorted, capSet);
- }
- sorted.add(resource);
- }
-
- @SuppressWarnings("unchecked")
- private static <T extends Resource> Set<T> collectDependencies(T resource, CapabilitySet capSet) {
- Set<T> result = new LinkedHashSet<T>();
- for (Requirement requirement : resource.getRequirements(null)) {
- String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
- SimpleFilter sf = (filter != null)
- ? SimpleFilter.parse(filter)
- : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
- for (Capability cap : capSet.match(sf, true)) {
- result.add((T) cap.getResource());
- }
- }
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java b/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
deleted file mode 100644
index d1f16b9..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.karaf.features.internal.deployment.Downloader;
-import org.apache.karaf.features.internal.deployment.StreamProvider;
-import org.apache.karaf.features.internal.util.MultiException;
-
-public class SimpleDownloader implements Downloader {
-
- private final MultiException exception = new MultiException("Error");
-
- @Override
- public void await() throws InterruptedException, MultiException {
- exception.throwIfExceptions();
- }
-
- @Override
- public void download(final String location, final DownloadCallback downloadCallback) throws MalformedURLException {
- final URL url = new URL(location);
- try {
- downloadCallback.downloaded(new StreamProvider() {
- @Override
- public InputStream open() throws IOException {
- return url.openStream();
- }
- });
- } catch (Exception e) {
- exception.addException(e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/State.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/State.java b/features/src/main/java/org/apache/karaf/features/internal/service/State.java
deleted file mode 100644
index c84f4e0..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/State.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class State {
-
- public final AtomicBoolean bootDone = new AtomicBoolean();
- public final Set<String> repositories = new TreeSet<String>();
- public final Set<String> features = new TreeSet<String>();
- public final Set<String> installedFeatures = new TreeSet<String>();
- public final Set<Long> managedBundles = new TreeSet<Long>();
- public final Map<String, Long> bundleChecksums = new HashMap<String, Long>();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java b/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
deleted file mode 100644
index 574e52e..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.karaf.features.Feature;
-
-public abstract class StateStorage {
-
- public void load(State state) throws IOException {
- state.repositories.clear();
- state.features.clear();
- state.installedFeatures.clear();
- state.managedBundles.clear();
- InputStream is = getInputStream();
- if (is != null) {
- try {
- Properties props = new Properties();
- props.load(is);
- state.bootDone.set(loadBool(props, "bootDone"));
- state.repositories.addAll(loadSet(props, "repositories."));
- state.features.addAll(loadSet(props, "features."));
- state.installedFeatures.addAll(loadSet(props, "installed."));
- state.managedBundles.addAll(toLongSet(loadSet(props, "managed.")));
- state.bundleChecksums.putAll(toStringLongMap(loadMap(props, "checksums.")));
- } finally {
- close(is);
- }
- }
- }
-
- public void save(State state) throws IOException {
- OutputStream os = getOutputStream();
- if (os != null) {
- try {
- Properties props = new Properties();
- saveBool(props, "bootDone", state.bootDone.get());
- saveSet(props, "repositories.", state.repositories);
- saveSet(props, "features.", state.features);
- saveSet(props, "installed.", state.installedFeatures);
- saveSet(props, "managed.", toStringSet(state.managedBundles));
- saveMap(props, "checksums.", toStringStringMap(state.bundleChecksums));
- props.store(os, "FeaturesService State");
- } finally {
- close(os);
- }
- }
- }
-
- protected abstract InputStream getInputStream() throws IOException;
- protected abstract OutputStream getOutputStream() throws IOException;
-
- protected boolean loadBool(Properties props, String key) {
- return Boolean.parseBoolean(props.getProperty(key));
- }
-
- protected void saveBool(Properties props, String key, boolean val) {
- props.setProperty(key, Boolean.toString(val));
- }
-
- protected Set<String> toStringSet(Set<Long> set) {
- Set<String> ns = new TreeSet<String>();
- for (long l : set) {
- ns.add(Long.toString(l));
- }
- return ns;
- }
-
- protected Set<Long> toLongSet(Set<String> set) {
- Set<Long> ns = new TreeSet<Long>();
- for (String s : set) {
- ns.add(Long.parseLong(s));
- }
- return ns;
- }
-
- protected void saveSet(Properties props, String prefix, Set<String> set) {
- List<String> l = new ArrayList<String>(set);
- props.put(prefix + "count", Integer.toString(l.size()));
- for (int i = 0; i < l.size(); i++) {
- props.put(prefix + "item." + i, l.get(i));
- }
- }
-
- protected Set<String> loadSet(Properties props, String prefix) {
- Set<String> l = new HashSet<String>();
- String countStr = (String) props.get(prefix + "count");
- if (countStr != null) {
- int count = Integer.parseInt(countStr);
- for (int i = 0; i < count; i++) {
- l.add((String) props.get(prefix + "item." + i));
- }
- }
- return l;
- }
-
- protected Map<String, String> toStringStringMap(Map<String, Long> map) {
- Map<String, String> nm = new HashMap<String, String>();
- for (Map.Entry<String, Long> entry : map.entrySet()) {
- nm.put(entry.getKey(), Long.toString(entry.getValue()));
- }
- return nm;
- }
-
- protected Map<String, Long> toStringLongMap(Map<String, String> map) {
- Map<String, Long> nm = new HashMap<String, Long>();
- for (Map.Entry<String, String> entry : map.entrySet()) {
- nm.put(entry.getKey(), Long.parseLong(entry.getValue()));
- }
- return nm;
- }
-
-
- protected void saveMap(Properties props, String prefix, Map<String, String> map) {
- List<Map.Entry<String, String>> l = new ArrayList<Map.Entry<String, String>>(map.entrySet());
- props.put(prefix + "count", Integer.toString(l.size()));
- for (int i = 0; i < l.size(); i++) {
- props.put(prefix + "key." + i, l.get(i).getKey());
- props.put(prefix + "val." + i, l.get(i).getValue());
- }
- }
-
- protected Map<String, String> loadMap(Properties props, String prefix) {
- Map<String, String> l = new HashMap<String, String>();
- String countStr = (String) props.get(prefix + "count");
- if (countStr != null) {
- int count = Integer.parseInt(countStr);
- for (int i = 0; i < count; i++) {
- String key = (String) props.get(prefix + "key." + i);
- String val = (String) props.get(prefix + "val." + i);
- l.put(key, val);
- }
- }
- return l;
- }
-
-
- protected void close(Closeable closeable) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java b/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
deleted file mode 100644
index 19fc706..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.zip.CRC32;
-
-public class ChecksumUtils {
-
- private ChecksumUtils() {
- }
-
- /**
- * Compute a cheksum for the file or directory that consists of the name, length and the last modified date
- * for a file and its children in case of a directory
- *
- * @param is the input stream
- * @return a checksum identifying any change
- */
- public static long checksum(InputStream is) throws IOException
- {
- try {
- CRC32 crc = new CRC32();
- byte[] buffer = new byte[8192];
- int l;
- while ((l = is.read(buffer)) > 0) {
- crc.update(buffer, 0, l);
- }
- return crc.getValue();
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java b/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
deleted file mode 100644
index a53d8a5..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- */
-public class JsonReader {
-
- public static Object read(Reader reader) throws IOException {
- return new JsonReader(reader).parse();
- }
-
- public static Object read(InputStream is) throws IOException {
- return new JsonReader(new InputStreamReader(is)).parse();
- }
-
- //
- // Implementation
- //
-
- private final Reader reader;
- private final StringBuilder recorder;
- private int current;
- private int line = 1;
- private int column = 0;
-
- JsonReader(Reader reader) {
- this.reader = reader;
- recorder = new StringBuilder();
- }
-
- public Object parse() throws IOException {
- read();
- skipWhiteSpace();
- Object result = readValue();
- skipWhiteSpace();
- if (!endOfText()) {
- throw error("Unexpected character");
- }
- return result;
- }
-
- private Object readValue() throws IOException {
- switch (current) {
- case 'n':
- return readNull();
- case 't':
- return readTrue();
- case 'f':
- return readFalse();
- case '"':
- return readString();
- case '[':
- return readArray();
- case '{':
- return readObject();
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return readNumber();
- default:
- throw expected("value");
- }
- }
-
- private Collection<?> readArray() throws IOException {
- read();
- Collection<Object> array = new ArrayList<Object>();
- skipWhiteSpace();
- if (readChar(']')) {
- return array;
- }
- do {
- skipWhiteSpace();
- array.add(readValue());
- skipWhiteSpace();
- } while (readChar(','));
- if (!readChar(']')) {
- throw expected("',' or ']'");
- }
- return array;
- }
-
- private Map<String, Object> readObject() throws IOException {
- read();
- Map<String, Object> object = new HashMap<String, Object>();
- skipWhiteSpace();
- if (readChar('}')) {
- return object;
- }
- do {
- skipWhiteSpace();
- String name = readName();
- skipWhiteSpace();
- if (!readChar(':')) {
- throw expected("':'");
- }
- skipWhiteSpace();
- object.put(name, readValue());
- skipWhiteSpace();
- } while (readChar(','));
- if (!readChar('}')) {
- throw expected("',' or '}'");
- }
- return object;
- }
-
- private Object readNull() throws IOException {
- read();
- readRequiredChar('u');
- readRequiredChar('l');
- readRequiredChar('l');
- return null;
- }
-
- private Boolean readTrue() throws IOException {
- read();
- readRequiredChar('r');
- readRequiredChar('u');
- readRequiredChar('e');
- return Boolean.TRUE;
- }
-
- private Boolean readFalse() throws IOException {
- read();
- readRequiredChar('a');
- readRequiredChar('l');
- readRequiredChar('s');
- readRequiredChar('e');
- return Boolean.FALSE;
- }
-
- private void readRequiredChar(char ch) throws IOException {
- if (!readChar(ch)) {
- throw expected("'" + ch + "'");
- }
- }
-
- private String readString() throws IOException {
- read();
- recorder.setLength(0);
- while (current != '"') {
- if (current == '\\') {
- readEscape();
- } else if (current < 0x20) {
- throw expected("valid string character");
- } else {
- recorder.append((char) current);
- read();
- }
- }
- read();
- return recorder.toString();
- }
-
- private void readEscape() throws IOException {
- read();
- switch (current) {
- case '"':
- case '/':
- case '\\':
- recorder.append((char) current);
- break;
- case 'b':
- recorder.append('\b');
- break;
- case 'f':
- recorder.append('\f');
- break;
- case 'n':
- recorder.append('\n');
- break;
- case 'r':
- recorder.append('\r');
- break;
- case 't':
- recorder.append('\t');
- break;
- case 'u':
- char[] hexChars = new char[4];
- for (int i = 0; i < 4; i++) {
- read();
- if (!isHexDigit(current)) {
- throw expected("hexadecimal digit");
- }
- hexChars[i] = (char) current;
- }
- recorder.append((char) Integer.parseInt(String.valueOf(hexChars), 16));
- break;
- default:
- throw expected("valid escape sequence");
- }
- read();
- }
-
- private Number readNumber() throws IOException {
- recorder.setLength(0);
- readAndAppendChar('-');
- int firstDigit = current;
- if (!readAndAppendDigit()) {
- throw expected("digit");
- }
- if (firstDigit != '0') {
- while (readAndAppendDigit()) {
- }
- }
- readFraction();
- readExponent();
- return Double.parseDouble(recorder.toString());
- }
-
- private boolean readFraction() throws IOException {
- if (!readAndAppendChar('.')) {
- return false;
- }
- if (!readAndAppendDigit()) {
- throw expected("digit");
- }
- while (readAndAppendDigit()) {
- }
- return true;
- }
-
- private boolean readExponent() throws IOException {
- if (!readAndAppendChar('e') && !readAndAppendChar('E')) {
- return false;
- }
- if (!readAndAppendChar('+')) {
- readAndAppendChar('-');
- }
- if (!readAndAppendDigit()) {
- throw expected("digit");
- }
- while (readAndAppendDigit()) {
- }
- return true;
- }
-
- private String readName() throws IOException {
- if (current != '"') {
- throw expected("name");
- }
- readString();
- return recorder.toString();
- }
-
- private boolean readAndAppendChar(char ch) throws IOException {
- if (current != ch) {
- return false;
- }
- recorder.append(ch);
- read();
- return true;
- }
-
- private boolean readChar(char ch) throws IOException {
- if (current != ch) {
- return false;
- }
- read();
- return true;
- }
-
- private boolean readAndAppendDigit() throws IOException {
- if (!isDigit(current)) {
- return false;
- }
- recorder.append((char) current);
- read();
- return true;
- }
-
- private void skipWhiteSpace() throws IOException {
- while (isWhiteSpace(current) && !endOfText()) {
- read();
- }
- }
-
- private void read() throws IOException {
- if (endOfText()) {
- throw error("Unexpected end of input");
- }
- column++;
- if (current == '\n') {
- line++;
- column = 0;
- }
- current = reader.read();
- }
-
- private boolean endOfText() {
- return current == -1;
- }
-
- private IOException expected(String expected) {
- if (endOfText()) {
- return error("Unexpected end of input");
- }
- return error("Expected " + expected);
- }
-
- private IOException error(String message) {
- return new IOException(message + " at " + line + ":" + column);
- }
-
- private static boolean isWhiteSpace(int ch) {
- return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
- }
-
- private static boolean isDigit(int ch) {
- return ch >= '0' && ch <= '9';
- }
-
- private static boolean isHexDigit(int ch) {
- return ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F';
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java b/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
deleted file mode 100644
index cba27fb..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- */
-public class JsonWriter {
-
- public static void write(Writer writer, Object value) throws IOException {
- if (value instanceof Map) {
- writeObject(writer, (Map) value);
- } else if (value instanceof Collection) {
- writeArray(writer, (Collection) value);
- } else if (value instanceof Number) {
- writeNumber(writer, (Number) value);
- } else if (value instanceof String) {
- writeString(writer, (String) value);
- } else if (value instanceof Boolean) {
- writeBoolean(writer, (Boolean) value);
- } else if (value == null) {
- writeNull(writer);
- } else {
- throw new IllegalArgumentException("Unsupported value: " + value);
- }
- }
-
- private static void writeObject(Writer writer, Map<?, ?> value) throws IOException {
- writer.append('{');
- boolean first = true;
- for (Map.Entry entry : value.entrySet()) {
- if (!first) {
- writer.append(',');
- } else {
- first = false;
- }
- writeString(writer, (String) entry.getKey());
- writer.append(':');
- write(writer, entry.getValue());
- }
- writer.append('}');
- }
-
- private static void writeString(Writer writer, String value) throws IOException {
- writer.append('"');
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- switch (c) {
- case '\"':
- case '\\':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- writer.append('\\');
- writer.append(c);
- break;
- default:
- if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
- String s = Integer.toHexString(c);
- writer.append('\\');
- writer.append('u');
- for (int j = s.length(); j < 4; j++) {
- writer.append('0');
- }
- writer.append(s);
- } else {
- writer.append(c);
- }
- break;
- }
- }
- writer.append('"');
- }
-
- private static void writeNumber(Writer writer, Number value) throws IOException {
- writer.append(value.toString());
- }
-
- private static void writeBoolean(Writer writer, Boolean value) throws IOException {
- writer.append(Boolean.toString(value));
- }
-
- private static void writeArray(Writer writer, Collection<?> value) throws IOException {
- writer.append('[');
- boolean first = true;
- for (Object obj : value) {
- if (!first) {
- writer.append(',');
- } else {
- first = false;
- }
- write(writer, obj);
- }
- writer.append(']');
- }
-
- private static void writeNull(Writer writer) throws IOException {
- writer.append("null");
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java b/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
deleted file mode 100644
index d30b7b5..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.felix.utils.version.VersionTable;
-import org.osgi.framework.Version;
-
-public class Macro {
-
- public static String transform(String macro, String value) {
- if (macro.startsWith("${") && macro.endsWith("}")) {
- String[] args = macro.substring(2, macro.length() - 1).split(";");
- if ("version".equals(args[0])) {
- if (args.length != 2) {
- throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
- }
- return version(args[1], VersionTable.getVersion(value));
- } else if ("range".equals(args[0])) {
- if (args.length != 2) {
- throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
- }
- return range(args[1], VersionTable.getVersion(value));
- } else {
- throw new IllegalArgumentException("Unknown macro: " + macro);
- }
- }
- return value;
- }
-
- /**
- * Modify a version to set a version policy. Thed policy is a mask that is
- * mapped to a version.
- *
- * <pre>
- * + increment
- * - decrement
- * = maintain
- * ˜ discard
- *
- * ==+ = maintain major, minor, increment micro, discard qualifier
- * ˜˜˜= = just get the qualifier
- * version="[${version;==;${@}},${version;=+;${@}})"
- * </pre>
- *
- * @param args
- * @return
- */
- final static String MASK_STRING = "[\\-+=~0123456789]{0,3}[=~]?";
-
- static String version(String mask, Version version) {
- StringBuilder sb = new StringBuilder();
- String del = "";
-
- for (int i = 0; i < mask.length(); i++) {
- char c = mask.charAt(i);
- String result = null;
- if (c != '~') {
- if (i > 3) {
- throw new IllegalArgumentException("Version mask can only specify 3 digits");
- } else if (i == 3) {
- result = version.getQualifier();
- if (result.isEmpty()) {
- result = null;
- }
- } else if (Character.isDigit(c)) {
- // Handle masks like +00, =+0
- result = String.valueOf(c);
- } else {
- int x = 0;
- switch (i) {
- case 0: x = version.getMajor(); break;
- case 1: x = version.getMinor(); break;
- case 2: x = version.getMicro(); break;
- }
- switch (c) {
- case '+' :
- x++;
- break;
- case '-' :
- x--;
- break;
- case '=' :
- break;
- }
- result = Integer.toString(x);
- }
- if (result != null) {
- sb.append(del);
- del = ".";
- sb.append(result);
- }
- }
- }
- return sb.toString();
- }
-
- /**
- * Schortcut for version policy
- *
- * <pre>
- * -provide-policy : ${policy;[==,=+)}
- * -consume-policy : ${policy;[==,+)}
- * </pre>
- *
- * @param args
- * @return
- */
-
- static Pattern RANGE_MASK = Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
-
- static String range(String spec, Version version) {
- Matcher m = RANGE_MASK.matcher(spec);
- m.matches();
- String floor = m.group(1);
- String floorMask = m.group(2);
- String ceilingMask = m.group(3);
- String ceiling = m.group(4);
-
- String left = version(floorMask, version);
- String right = version(ceilingMask, version);
-
- return floor + left + "," + right + ceiling;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java b/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
deleted file mode 100644
index 36af452..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.util;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-@SuppressWarnings("serial")
-public class MultiException extends Exception {
-
- private List<Exception> exceptions = new ArrayList<Exception>();
-
- public MultiException(String message) {
- super(message);
- }
-
- public MultiException(String message, List<Exception> exceptions) {
- super(message);
- this.exceptions = exceptions;
- }
-
- public void addException(Exception e) {
- exceptions.add(e);
- }
-
- public void throwIfExceptions() throws MultiException {
- if (!exceptions.isEmpty()) {
- throw this;
- }
- }
-
- public Throwable[] getCauses() {
- return exceptions.toArray(new Throwable[exceptions.size()]);
- }
-
- @Override
- public void printStackTrace()
- {
- super.printStackTrace();
- for (Exception e : exceptions) {
- e.printStackTrace();
- }
- }
-
-
- /* ------------------------------------------------------------------------------- */
- /**
- * @see Throwable#printStackTrace(java.io.PrintStream)
- */
- @Override
- public void printStackTrace(PrintStream out)
- {
- super.printStackTrace(out);
- for (Exception e : exceptions) {
- e.printStackTrace(out);
- }
- }
-
- @Override
- public void printStackTrace(PrintWriter out)
- {
- super.printStackTrace(out);
- for (Exception e : exceptions) {
- e.printStackTrace(out);
- }
- }
-
- public static void throwIf(String message, List<Exception> exceptions) throws MultiException {
- if (exceptions != null && !exceptions.isEmpty()) {
- StringBuilder sb = new StringBuilder(message);
- sb.append(":");
- for (Exception e : exceptions) {
- sb.append("\n\t");
- sb.append(e.getMessage());
- }
- throw new MultiException(sb.toString(), exceptions);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java b/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
deleted file mode 100644
index 6afbbed..0000000
--- a/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.management;
-
-import javax.management.openmbean.TabularData;
-
-public interface FeaturesServiceMBean {
-
- TabularData getFeatures() throws Exception;
-
- TabularData getRepositories() throws Exception;
-
- void addRepository(String url) throws Exception;
-
- void addRepository(String url, boolean install) throws Exception;
-
- void removeRepository(String url) throws Exception;
-
- void removeRepository(String url, boolean uninstall) throws Exception;
-
- void installFeature(String name) throws Exception;
-
- void installFeature(String name, boolean noRefresh) throws Exception;
-
- void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception;
-
- void installFeature(String name, String version) throws Exception;
-
- void installFeature(String name, String version, boolean noRefresh) throws Exception;
-
- void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception;
-
- TabularData infoFeature(String name) throws Exception;
-
- TabularData infoFeature(String name, String version) throws Exception;
-
- void uninstallFeature(String name) throws Exception;
-
- void uninstallFeature(String name, boolean noRefresh) throws Exception;
-
- void uninstallFeature(String name, String version) throws Exception;
-
- void uninstallFeature(String name, String version, boolean noRefresh) throws Exception;
-
- String FEATURE_NAME = "Name";
-
- String FEATURE_VERSION = "Version";
-
- String FEATURE_DEPENDENCIES = "Dependencies";
-
- String FEATURE_BUNDLES = "Bundles";
-
- String FEATURE_CONFIGURATIONS = "Configurations";
-
- String FEATURE_CONFIGURATIONFILES = "Configuration Files";
-
- String FEATURE_INSTALLED = "Installed";
-
- String FEATURE_CONFIG_PID = "Pid";
- String FEATURE_CONFIG_ELEMENTS = "Elements";
- String FEATURE_CONFIG_ELEMENT_KEY = "Key";
- String FEATURE_CONFIG_ELEMENT_VALUE = "Value";
-
- String FEATURE_CONFIG_FILES_ELEMENTS = "Files";
-
- /**
- * The type of the event which is emitted for features events
- */
- String FEATURE_EVENT_TYPE = "org.apache.karaf.features.featureEvent";
-
- String FEATURE_EVENT_EVENT_TYPE = "Type";
-
- String FEATURE_EVENT_EVENT_TYPE_INSTALLED = "Installed";
-
- String FEATURE_EVENT_EVENT_TYPE_UNINSTALLED = "Uninstalled";
-
- /**
- * The item names in the CompositeData representing a feature
- */
- String[] FEATURE = { FEATURE_NAME, FEATURE_VERSION, FEATURE_DEPENDENCIES, FEATURE_BUNDLES,
- FEATURE_CONFIGURATIONS, FEATURE_CONFIGURATIONFILES, FEATURE_INSTALLED };
-
- String[] FEATURE_IDENTIFIER = { FEATURE_NAME, FEATURE_VERSION };
-
- String[] FEATURE_CONFIG = { FEATURE_CONFIG_PID, FEATURE_CONFIG_ELEMENTS };
-
- String[] FEATURE_CONFIG_FILES = { FEATURE_CONFIG_FILES_ELEMENTS };
-
- String[] FEATURE_CONFIG_ELEMENT = { FEATURE_CONFIG_ELEMENT_KEY, FEATURE_CONFIG_ELEMENT_VALUE };
-
- /**
- * The item names in the CompositeData representing the event raised for
- * feature events within the OSGi container by this bean
- */
- String[] FEATURE_EVENT = { FEATURE_NAME, FEATURE_VERSION, FEATURE_EVENT_EVENT_TYPE };
-
-
- String REPOSITORY_NAME = "Name";
-
- String REPOSITORY_URI = "Uri";
-
- String REPOSITORY_REPOSITORIES = "Repositories";
-
- String REPOSITORY_FEATURES = "Features";
-
- /**
- * The type of the event which is emitted for repositories events
- */
- String REPOSITORY_EVENT_TYPE = "org.apache.karaf.features.repositoryEvent";
-
- String REPOSITORY_EVENT_EVENT_TYPE = "Type";
-
- String REPOSITORY_EVENT_EVENT_TYPE_ADDED = "Added";
-
- String REPOSITORY_EVENT_EVENT_TYPE_REMOVED = "Removed";
-
- /**
- * The item names in the CompositeData representing a feature
- */
- String[] REPOSITORY = { REPOSITORY_NAME, REPOSITORY_URI, REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
-
- /**
- * The item names in the CompositeData representing the event raised for
- * feature events within the OSGi container by this bean
- */
- String[] REPOSITORY_EVENT = { REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
deleted file mode 100644
index 54fa3c0..0000000
--- a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.management.codec;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxFeature {
-
- /**
- * The CompositeType which represents a single feature
- */
- public final static CompositeType FEATURE;
-
- /**
- * The TabularType which represents a list of features
- */
- public final static TabularType FEATURE_TABLE;
-
- public final static CompositeType FEATURE_IDENTIFIER;
-
- public final static TabularType FEATURE_IDENTIFIER_TABLE;
-
- public final static CompositeType FEATURE_CONFIG_ELEMENT;
-
- public final static TabularType FEATURE_CONFIG_ELEMENT_TABLE;
-
- public final static CompositeType FEATURE_CONFIG;
-
- public final static TabularType FEATURE_CONFIG_TABLE;
-
- public final static CompositeType FEATURE_CONFIG_FILES;
-
- public final static TabularType FEATURE_CONFIG_FILES_TABLE;
-
- private final CompositeData data;
-
- public JmxFeature(Feature feature, boolean installed) {
- try {
- String[] itemNames = FeaturesServiceMBean.FEATURE;
- Object[] itemValues = new Object[itemNames.length];
- itemValues[0] = feature.getName();
- itemValues[1] = feature.getVersion();
- itemValues[2] = getDependencyIdentifierTable(feature.getDependencies());
- itemValues[3] = getBundleUris(feature.getBundles());
- itemValues[4] = getConfigTable(feature.getConfigurations());
- itemValues[5] = getConfigFileList(feature.getConfigurationFiles());
- itemValues[6] = installed;
- data = new CompositeDataSupport(FEATURE, itemNames, itemValues);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Cannot form feature open data", e);
- }
- }
-
- public CompositeData asCompositeData() {
- return data;
- }
-
- public static TabularData tableFrom(Collection<JmxFeature> features) {
- TabularDataSupport table = new TabularDataSupport(FEATURE_TABLE);
- for (JmxFeature feature : features) {
- table.put(feature.asCompositeData());
- }
- return table;
- }
-
- private static TabularData getDependencyIdentifierTable(List<Dependency> features) throws OpenDataException {
- TabularDataSupport table = new TabularDataSupport(FEATURE_IDENTIFIER_TABLE);
- Set<String> featureSet = new HashSet<String>();
- for (Dependency feature : features) {
- if (featureSet.contains(feature.getName() + feature.getVersion())) {
- continue;
- } else {
- featureSet.add(feature.getName() + feature.getVersion());
- }
- String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
- Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
- CompositeData ident = new CompositeDataSupport(FEATURE_IDENTIFIER, itemNames, itemValues);
- table.put(ident);
- }
- return table;
- }
-
- static String[] getBundleUris(List<BundleInfo> infos) {
- String[] array = new String[infos.size()];
- for (int i = 0; i < array.length; i++) {
- array[i] = infos.get(i).getLocation();
- }
- return array;
- }
-
- static TabularData getConfigTable(Map<String, Map<String, String>> configs) throws OpenDataException {
- TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_TABLE);
- for (Map.Entry<String, Map<String, String>> entry : configs.entrySet()) {
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
- Object[] itemValues = new Object[2];
- itemValues[0] = entry.getKey();
- itemValues[1] = getConfigElementTable(entry.getValue());
- CompositeData config = new CompositeDataSupport(FEATURE_CONFIG, itemNames, itemValues);
- table.put(config);
- }
- return table;
- }
-
- static TabularData getConfigFileList(List<ConfigFileInfo> configFiles) throws OpenDataException {
- TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_FILES_TABLE);
- for (ConfigFileInfo configFile : configFiles) {
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
- Object[] itemValues = { configFile.getFinalname() };
- CompositeData config = new CompositeDataSupport(FEATURE_CONFIG_FILES, itemNames, itemValues);
- table.put(config);
- }
- return table;
- }
-
- static TabularData getConfigElementTable(Map<String, String> config) throws OpenDataException {
- TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_ELEMENT_TABLE);
- for (Map.Entry<String, String> entry : config.entrySet()) {
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
- Object[] itemValues = { entry.getKey(), entry.getValue() };
- CompositeData element = new CompositeDataSupport(FEATURE_CONFIG_ELEMENT, itemNames, itemValues);
- table.put(element);
- }
- return table;
- }
-
-
- static {
- FEATURE_IDENTIFIER = createFeatureIdentifierType();
- FEATURE_IDENTIFIER_TABLE = createFeatureIdentifierTableType();
- FEATURE_CONFIG_ELEMENT = createFeatureConfigElementType();
- FEATURE_CONFIG_ELEMENT_TABLE = createFeatureConfigElementTableType();
- FEATURE_CONFIG = createFeatureConfigType();
- FEATURE_CONFIG_TABLE = createFeatureConfigTableType();
- FEATURE_CONFIG_FILES = createFeatureConfigFilesType();
- FEATURE_CONFIG_FILES_TABLE = createFeatureConfigFilesTableType();
- FEATURE = createFeatureType();
- FEATURE_TABLE = createFeatureTableType();
- }
-
- private static CompositeType createFeatureIdentifierType() {
- try {
- String description = "This type identify a Karaf features";
- String[] itemNames = FeaturesServiceMBean.FEATURE_IDENTIFIER;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
-
- itemDescriptions[0] = "The id of the feature";
- itemDescriptions[1] = "The version of the feature";
-
- return new CompositeType("FeatureIdentifier", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build featureIdentifier type", e);
- }
- }
-
- private static TabularType createFeatureIdentifierTableType() {
- try {
- return new TabularType("Features", "The table of featureIdentifiers",
- FEATURE_IDENTIFIER, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build featureIdentifier table type", e);
- }
- }
-
- private static CompositeType createFeatureConfigElementType() {
- try {
- String description = "This type encapsulates Karaf feature config element";
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
-
- itemDescriptions[0] = "The key";
- itemDescriptions[1] = "The value";
-
- return new CompositeType("ConfigElement", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build configElement type", e);
- }
- }
-
- private static TabularType createFeatureConfigElementTableType() {
- try {
- return new TabularType("ConfigElement", "The table of configurations elements",
- FEATURE_CONFIG_ELEMENT, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT_KEY});
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build feature table type", e);
- }
- }
-
- private static CompositeType createFeatureConfigType() {
- try {
- String description = "This type encapsulates Karaf feature config";
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = FEATURE_CONFIG_ELEMENT_TABLE;
-
- itemDescriptions[0] = "The PID of the config";
- itemDescriptions[1] = "The configuration elements";
-
- return new CompositeType("Config", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build configElement type", e);
- }
- }
-
- private static CompositeType createFeatureConfigFilesType() {
- try {
- String description = "This type encapsulates Karaf feature config files";
- String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
-
- itemDescriptions[0] = "The configuration file";
-
- return new CompositeType("Config", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build configElement type", e);
- }
- }
-
- private static TabularType createFeatureConfigTableType() {
- try {
- return new TabularType("Features", "The table of configurations",
- FEATURE_CONFIG, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_PID});
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build feature table type", e);
- }
- }
-
- private static TabularType createFeatureConfigFilesTableType() {
- try {
- return new TabularType("Features", "The table of configuration files",
- FEATURE_CONFIG_FILES, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_FILES_ELEMENTS });
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build feature table type", e);
- }
- }
-
- private static CompositeType createFeatureType() {
- try {
- String description = "This type encapsulates Karaf features";
- String[] itemNames = FeaturesServiceMBean.FEATURE;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
- itemTypes[2] = FEATURE_IDENTIFIER_TABLE;
- itemTypes[3] = new ArrayType(1, SimpleType.STRING);
- itemTypes[4] = FEATURE_CONFIG_TABLE;
- itemTypes[5] = FEATURE_CONFIG_FILES_TABLE;
- itemTypes[6] = SimpleType.BOOLEAN;
-
- itemDescriptions[0] = "The name of the feature";
- itemDescriptions[1] = "The version of the feature";
- itemDescriptions[2] = "The feature dependencies";
- itemDescriptions[3] = "The feature bundles";
- itemDescriptions[4] = "The feature configurations";
- itemDescriptions[5] = "The feature configuration files";
- itemDescriptions[6] = "Whether the feature is installed";
-
- return new CompositeType("Feature", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build feature type", e);
- }
- }
-
- private static TabularType createFeatureTableType() {
- try {
- return new TabularType("Features", "The table of all features",
- FEATURE, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build feature table type", e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
deleted file mode 100644
index 81f446b..0000000
--- a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.management.codec;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxFeatureEvent {
-
- public static final CompositeType FEATURE_EVENT;
-
- private final CompositeData data;
-
- public JmxFeatureEvent(FeatureEvent event) {
- try {
- String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
- Object[] itemValues = new Object[itemNames.length];
- itemValues[0] = event.getFeature().getName();
- itemValues[1] = event.getFeature().getVersion();
- switch (event.getType()) {
- case FeatureInstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_INSTALLED; break;
- case FeatureUninstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_UNINSTALLED; break;
- default: throw new IllegalStateException("Unsupported event type: " + event.getType());
- }
- data = new CompositeDataSupport(FEATURE_EVENT, itemNames, itemValues);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Cannot form feature event open data", e);
- }
- }
-
- public CompositeData asCompositeData() {
- return data;
- }
-
- static {
- FEATURE_EVENT = createFeatureEventType();
- }
-
- private static CompositeType createFeatureEventType() {
- try {
- String description = "This type identify a Karaf feature event";
- String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
- itemTypes[2] = SimpleType.STRING;
-
- itemDescriptions[0] = "The id of the feature";
- itemDescriptions[1] = "The version of the feature";
- itemDescriptions[2] = "The type of the event";
-
- return new CompositeType("FeatureEvent", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build featureEvent type", e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
deleted file mode 100644
index fee1ab2..0000000
--- a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.management.codec;
-
-import java.util.Collection;
-import java.util.Arrays;
-import java.net.URI;
-import java.util.List;
-
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.TabularType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.CompositeDataSupport;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxRepository {
-
- public final static CompositeType REPOSITORY;
-
- public final static TabularType REPOSITORY_TABLE;
-
- private final CompositeData data;
-
- public JmxRepository(Repository repository) {
- try {
- String[] itemNames = FeaturesServiceMBean.REPOSITORY;
- Object[] itemValues = new Object[itemNames.length];
- itemValues[0] = repository.getName();
- itemValues[1] = repository.getURI().toString();
- itemValues[2] = toStringArray(repository.getRepositories());
- itemValues[3] = getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
- data = new CompositeDataSupport(REPOSITORY, itemNames, itemValues);
- } catch (Exception e) {
- throw new IllegalStateException("Cannot form repository open data", e);
- }
- }
-
- public CompositeData asCompositeData() {
- return data;
- }
-
- public static TabularData tableFrom(Collection<JmxRepository> repositories) {
- TabularDataSupport table = new TabularDataSupport(REPOSITORY_TABLE);
- for (JmxRepository repository : repositories) {
- table.put(repository.asCompositeData());
- }
- return table;
- }
-
- private static String[] toStringArray(URI[] uris) {
- if (uris == null) {
- return null;
- }
- String[] res = new String[uris.length];
- for (int i = 0; i < res.length; i++) {
- res[i] = uris[i].toString();
- }
- return res;
- }
-
- static TabularData getFeatureIdentifierTable(List<Feature> features) throws OpenDataException {
- TabularDataSupport table = new TabularDataSupport(JmxFeature.FEATURE_IDENTIFIER_TABLE);
- for (Feature feature : features) {
- String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
- Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
- CompositeData ident = new CompositeDataSupport(JmxFeature.FEATURE_IDENTIFIER, itemNames, itemValues);
- table.put(ident);
- }
- return table;
- }
-
- static {
- REPOSITORY = createRepositoryType();
- REPOSITORY_TABLE = createRepositoryTableType();
- }
-
- private static CompositeType createRepositoryType() {
- try {
- String description = "This type identify a Karaf repository";
- String[] itemNames = FeaturesServiceMBean.REPOSITORY;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
- itemTypes[2] = new ArrayType(1, SimpleType.STRING);
- itemTypes[3] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
-
- itemDescriptions[0] = "The name of the repository";
- itemDescriptions[1] = "The uri of the repository";
- itemDescriptions[2] = "The dependent repositories";
- itemDescriptions[3] = "The list of included features";
-
- return new CompositeType("Repository", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build repository type", e);
- }
- }
-
- private static TabularType createRepositoryTableType() {
- try {
- return new TabularType("Features", "The table of repositories",
- REPOSITORY, new String[] { FeaturesServiceMBean.REPOSITORY_URI });
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build repository table type", e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
deleted file mode 100644
index e00e85d..0000000
--- a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.management.codec;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.karaf.features.RepositoryEvent;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxRepositoryEvent {
-
- public static final CompositeType REPOSITORY_EVENT;
-
- private final CompositeData data;
-
- public JmxRepositoryEvent(RepositoryEvent event) {
- try {
- String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
- Object[] itemValues = new Object[itemNames.length];
- itemValues[0] = event.getRepository().getURI().toString();
- switch (event.getType()) {
- case RepositoryAdded: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_ADDED; break;
- case RepositoryRemoved: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_REMOVED; break;
- default: throw new IllegalStateException("Unsupported event type: " + event.getType());
- }
- data = new CompositeDataSupport(REPOSITORY_EVENT, itemNames, itemValues);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Cannot form repository event open data", e);
- }
- }
-
- public CompositeData asCompositeData() {
- return data;
- }
-
- static {
- REPOSITORY_EVENT = createRepositoryEventType();
- }
-
- private static CompositeType createRepositoryEventType() {
- try {
- String description = "This type identify a Karaf repository event";
- String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
- OpenType[] itemTypes = new OpenType[itemNames.length];
- String[] itemDescriptions = new String[itemNames.length];
- itemTypes[0] = SimpleType.STRING;
- itemTypes[1] = SimpleType.STRING;
-
- itemDescriptions[0] = "The uri of the repository";
- itemDescriptions[1] = "The type of event";
-
- return new CompositeType("RepositoryEvent", description, itemNames,
- itemDescriptions, itemTypes);
- } catch (OpenDataException e) {
- throw new IllegalStateException("Unable to build repositoryEvent type", e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/src/main/resources/OSGI-INF/bundle.info b/features/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index d5b4180..0000000
--- a/features/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,20 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the Karaf features support.
-
-Karaf provides a simple, yet flexible, way to provision applications or "features". Such a mechanism is mainly
-provided by a set of commands available in the features shell. The provisioning system uses xml "repositories"
-that define a set of features.
-
-h1. See also
-
-Provisioning - section of the Karaf User Guide
[29/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
new file mode 100644
index 0000000..ad4cc85
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.Comparator;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.resource.Capability;
+
+public class CandidateComparator implements Comparator<Capability>
+{
+ public int compare(Capability cap1, Capability cap2)
+ {
+ int c = 0;
+ // Always prefer system bundle
+ if (cap1 instanceof BundleCapability && !(cap2 instanceof BundleCapability)) {
+ c = -1;
+ } else if (!(cap1 instanceof BundleCapability) && cap2 instanceof BundleCapability) {
+ c = 1;
+ }
+ // Compare revision capabilities.
+ if ((c == 0) && cap1.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
+ {
+ c = ((Comparable) cap1.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE))
+ .compareTo(cap2.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE));
+ if (c == 0)
+ {
+ Version v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ Version v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ // Compare these in reverse order, since we want
+ // highest version to have priority.
+ c = compareVersions(v2, v1);
+ }
+ }
+ // Compare package capabilities.
+ else if ((c == 0) && cap1.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+ {
+ c = ((Comparable) cap1.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))
+ .compareTo(cap2.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
+ if (c == 0)
+ {
+ Version v1 = (!cap1.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap1.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ Version v2 = (!cap2.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap2.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ // Compare these in reverse order, since we want
+ // highest version to have priority.
+ c = compareVersions(v2, v1);
+ // if same version, rather compare on the bundle version
+ if (c == 0)
+ {
+ v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+ // Compare these in reverse order, since we want
+ // highest version to have priority.
+ c = compareVersions(v2, v1);
+ }
+ }
+ }
+ // Compare feature capabilities
+ else if ((c == 0) && cap1.getNamespace().equals(FeatureNamespace.FEATURE_NAMESPACE))
+ {
+ c = ((Comparable) cap1.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE))
+ .compareTo(cap2.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE));
+ if (c == 0)
+ {
+ Version v1 = (!cap1.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap1.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ Version v2 = (!cap2.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap2.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ // Compare these in reverse order, since we want
+ // highest version to have priority.
+ c = compareVersions(v2, v1);
+ }
+ }
+ return c;
+ }
+
+ private int compareVersions(Version v1, Version v2) {
+ int c = v1.getMajor() - v2.getMajor();
+ if (c != 0) {
+ return c;
+ }
+ c = v1.getMinor() - v2.getMinor();
+ if (c != 0) {
+ return c;
+ }
+ c = v1.getMicro() - v2.getMicro();
+ if (c != 0) {
+ return c;
+ }
+ String q1 = cleanQualifierForComparison(v1.getQualifier());
+ String q2 = cleanQualifierForComparison(v2.getQualifier());
+ return q1.compareTo(q2);
+ }
+
+ private String cleanQualifierForComparison(String qualifier) {
+ return qualifier.replaceAll("(redhat-[0-9]{3})([0-9]{3})", "$1-$2");
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
new file mode 100644
index 0000000..bfe9b40
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+public class CapabilityImpl extends BaseClause implements Capability {
+
+ private final Resource m_resource;
+ private final String m_namespace;
+ private final Map<String, String> m_dirs;
+ private final Map<String, Object> m_attrs;
+ private final List<String> m_uses;
+ private final List<List<String>> m_includeFilter;
+ private final List<List<String>> m_excludeFilter;
+ private final Set<String> m_mandatory;
+
+ public CapabilityImpl(Capability capability) {
+ this(null, capability.getNamespace(), capability.getDirectives(), capability.getAttributes());
+ }
+
+ public CapabilityImpl(Resource resource, String namespace,
+ Map<String, String> dirs, Map<String, Object> attrs) {
+ m_namespace = namespace;
+ m_resource = resource;
+ m_dirs = dirs;
+ m_attrs = attrs;
+
+ // Find all export directives: uses, mandatory, include, and exclude.
+
+ List<String> uses = Collections.emptyList();
+ String value = m_dirs.get(Constants.USES_DIRECTIVE);
+ if (value != null) {
+ // Parse these uses directive.
+ StringTokenizer tok = new StringTokenizer(value, ",");
+ uses = new ArrayList<String>(tok.countTokens());
+ while (tok.hasMoreTokens()) {
+ uses.add(tok.nextToken().trim());
+ }
+ }
+ m_uses = uses;
+
+ value = m_dirs.get(Constants.INCLUDE_DIRECTIVE);
+ if (value != null) {
+ List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
+ m_includeFilter = new ArrayList<List<String>>(filters.size());
+ for (String filter : filters) {
+ List<String> substrings = SimpleFilter.parseSubstring(filter);
+ m_includeFilter.add(substrings);
+ }
+ } else {
+ m_includeFilter = null;
+ }
+
+ value = m_dirs.get(Constants.EXCLUDE_DIRECTIVE);
+ if (value != null) {
+ List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
+ m_excludeFilter = new ArrayList<List<String>>(filters.size());
+ for (String filter : filters) {
+ List<String> substrings = SimpleFilter.parseSubstring(filter);
+ m_excludeFilter.add(substrings);
+ }
+ } else {
+ m_excludeFilter = null;
+ }
+
+ Set<String> mandatory = Collections.emptySet();
+ value = m_dirs.get(Constants.MANDATORY_DIRECTIVE);
+ if (value != null) {
+ List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
+ mandatory = new HashSet<String>(names.size());
+ for (String name : names) {
+ // If attribute exists, then record it as mandatory.
+ if (m_attrs.containsKey(name)) {
+ mandatory.add(name);
+ }
+ // Otherwise, report an error.
+ else {
+ throw new IllegalArgumentException("Mandatory attribute '" + name + "' does not exist.");
+ }
+ }
+ }
+ m_mandatory = mandatory;
+ }
+
+ public Resource getResource() {
+ return m_resource;
+ }
+
+ public String getNamespace() {
+ return m_namespace;
+ }
+
+ public Map<String, String> getDirectives() {
+ return m_dirs;
+ }
+
+ public Map<String, Object> getAttributes() {
+ return m_attrs;
+ }
+
+ public boolean isAttributeMandatory(String name) {
+ return !m_mandatory.isEmpty() && m_mandatory.contains(name);
+ }
+
+ public List<String> getUses() {
+ return m_uses;
+ }
+
+ public boolean isIncluded(String name) {
+ if ((m_includeFilter == null) && (m_excludeFilter == null)) {
+ return true;
+ }
+
+ // Get the class name portion of the target class.
+ String className = getClassName(name);
+
+ // If there are no include filters then all classes are included
+ // by default, otherwise try to find one match.
+ boolean included = (m_includeFilter == null);
+ for (int i = 0; !included && m_includeFilter != null && i < m_includeFilter.size(); i++) {
+ included = SimpleFilter.compareSubstring(m_includeFilter.get(i), className);
+ }
+
+ // If there are no exclude filters then no classes are excluded
+ // by default, otherwise try to find one match.
+ boolean excluded = false;
+ for (int i = 0; (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size()); i++) {
+ excluded = SimpleFilter.compareSubstring(m_excludeFilter.get(i), className);
+ }
+ return included && !excluded;
+ }
+
+ private static String getClassName(String className) {
+ if (className == null) {
+ className = "";
+ }
+ return (className.lastIndexOf('.') < 0) ? "" : className.substring(className.lastIndexOf('.') + 1);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
new file mode 100644
index 0000000..4c5656d
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
@@ -0,0 +1,612 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+
+public class CapabilitySet
+{
+ private final Map<String, Map<Object, Set<Capability>>> m_indices;
+ private final Set<Capability> m_capSet = new HashSet<Capability>();
+
+public void dump()
+{
+ for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+ {
+ boolean header1 = false;
+ for (Entry<Object, Set<Capability>> entry2 : entry.getValue().entrySet())
+ {
+ boolean header2 = false;
+ for (Capability cap : entry2.getValue())
+ {
+ if (!header1)
+ {
+ System.out.println(entry.getKey() + ":");
+ header1 = true;
+ }
+ if (!header2)
+ {
+ System.out.println(" " + entry2.getKey());
+ header2 = true;
+ }
+ System.out.println(" " + cap);
+ }
+ }
+ }
+}
+
+ public CapabilitySet(List<String> indexProps)
+ {
+ m_indices = new TreeMap<String, Map<Object, Set<Capability>>>();
+ for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++)
+ {
+ m_indices.put(
+ indexProps.get(i), new HashMap<Object, Set<Capability>>());
+ }
+ }
+
+ public void addCapability(Capability cap)
+ {
+ m_capSet.add(cap);
+
+ // Index capability.
+ for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+ {
+ Object value = cap.getAttributes().get(entry.getKey());
+ if (value != null)
+ {
+ if (value.getClass().isArray())
+ {
+ value = convertArrayToList(value);
+ }
+
+ Map<Object, Set<Capability>> index = entry.getValue();
+
+ if (value instanceof Collection)
+ {
+ Collection c = (Collection) value;
+ for (Object o : c)
+ {
+ indexCapability(index, cap, o);
+ }
+ }
+ else
+ {
+ indexCapability(index, cap, value);
+ }
+ }
+ }
+ }
+
+ private void indexCapability(
+ Map<Object, Set<Capability>> index, Capability cap, Object capValue)
+ {
+ Set<Capability> caps = index.get(capValue);
+ if (caps == null)
+ {
+ caps = new HashSet<Capability>();
+ index.put(capValue, caps);
+ }
+ caps.add(cap);
+ }
+
+ public void removeCapability(Capability cap)
+ {
+ if (m_capSet.remove(cap))
+ {
+ for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+ {
+ Object value = cap.getAttributes().get(entry.getKey());
+ if (value != null)
+ {
+ if (value.getClass().isArray())
+ {
+ value = convertArrayToList(value);
+ }
+
+ Map<Object, Set<Capability>> index = entry.getValue();
+
+ if (value instanceof Collection)
+ {
+ Collection c = (Collection) value;
+ for (Object o : c)
+ {
+ deindexCapability(index, cap, o);
+ }
+ }
+ else
+ {
+ deindexCapability(index, cap, value);
+ }
+ }
+ }
+ }
+ }
+
+ private void deindexCapability(
+ Map<Object, Set<Capability>> index, Capability cap, Object value)
+ {
+ Set<Capability> caps = index.get(value);
+ if (caps != null)
+ {
+ caps.remove(cap);
+ if (caps.isEmpty())
+ {
+ index.remove(value);
+ }
+ }
+ }
+
+ public Set<Capability> match(SimpleFilter sf, boolean obeyMandatory)
+ {
+ Set<Capability> matches = match(m_capSet, sf);
+ return (obeyMandatory)
+ ? matchMandatory(matches, sf)
+ : matches;
+ }
+
+ private Set<Capability> match(Set<Capability> caps, SimpleFilter sf)
+ {
+ Set<Capability> matches = new HashSet<Capability>();
+
+ if (sf.getOperation() == SimpleFilter.MATCH_ALL)
+ {
+ matches.addAll(caps);
+ }
+ else if (sf.getOperation() == SimpleFilter.AND)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For AND we calculate the intersection of each subfilter.
+ // We can short-circuit the AND operation if there are no
+ // remaining capabilities.
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; (caps.size() > 0) && (i < sfs.size()); i++)
+ {
+ matches = match(caps, sfs.get(i));
+ caps = matches;
+ }
+ }
+ else if (sf.getOperation() == SimpleFilter.OR)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For OR we calculate the union of each subfilter.
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; i < sfs.size(); i++)
+ {
+ matches.addAll(match(caps, sfs.get(i)));
+ }
+ }
+ else if (sf.getOperation() == SimpleFilter.NOT)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For OR we calculate the union of each subfilter.
+ matches.addAll(caps);
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; i < sfs.size(); i++)
+ {
+ matches.removeAll(match(caps, sfs.get(i)));
+ }
+ }
+ else
+ {
+ Map<Object, Set<Capability>> index = m_indices.get(sf.getName());
+ if ((sf.getOperation() == SimpleFilter.EQ) && (index != null))
+ {
+ Set<Capability> existingCaps = index.get(sf.getValue());
+ if (existingCaps != null)
+ {
+ matches.addAll(existingCaps);
+ matches.retainAll(caps);
+ }
+ }
+ else
+ {
+ for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
+ {
+ Capability cap = it.next();
+ Object lhs = cap.getAttributes().get(sf.getName());
+ if (lhs != null)
+ {
+ if (compare(lhs, sf.getValue(), sf.getOperation()))
+ {
+ matches.add(cap);
+ }
+ }
+ }
+ }
+ }
+
+ return matches;
+ }
+
+ public static boolean matches(Capability cap, SimpleFilter sf)
+ {
+ return matchesInternal(cap, sf) && matchMandatory(cap, sf);
+ }
+
+ private static boolean matchesInternal(Capability cap, SimpleFilter sf)
+ {
+ boolean matched = true;
+
+ if (sf.getOperation() == SimpleFilter.MATCH_ALL)
+ {
+ matched = true;
+ }
+ else if (sf.getOperation() == SimpleFilter.AND)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For AND we calculate the intersection of each subfilter.
+ // We can short-circuit the AND operation if there are no
+ // remaining capabilities.
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; matched && (i < sfs.size()); i++)
+ {
+ matched = matchesInternal(cap, sfs.get(i));
+ }
+ }
+ else if (sf.getOperation() == SimpleFilter.OR)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For OR we calculate the union of each subfilter.
+ matched = false;
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; !matched && (i < sfs.size()); i++)
+ {
+ matched = matchesInternal(cap, sfs.get(i));
+ }
+ }
+ else if (sf.getOperation() == SimpleFilter.NOT)
+ {
+ // Evaluate each subfilter against the remaining capabilities.
+ // For OR we calculate the union of each subfilter.
+ List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+ for (int i = 0; i < sfs.size(); i++)
+ {
+ matched = !(matchesInternal(cap, sfs.get(i)));
+ }
+ }
+ else
+ {
+ matched = false;
+ Object lhs = cap.getAttributes().get(sf.getName());
+ if (lhs != null)
+ {
+ matched = compare(lhs, sf.getValue(), sf.getOperation());
+ }
+ }
+
+ return matched;
+ }
+
+ private static Set<Capability> matchMandatory(
+ Set<Capability> caps, SimpleFilter sf)
+ {
+ for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
+ {
+ Capability cap = it.next();
+ if (!matchMandatory(cap, sf))
+ {
+ it.remove();
+ }
+ }
+ return caps;
+ }
+
+ private static boolean matchMandatory(Capability cap, SimpleFilter sf)
+ {
+ if (cap instanceof CapabilityImpl) {
+ for (Entry<String, Object> entry : cap.getAttributes().entrySet())
+ {
+ if (((CapabilityImpl) cap).isAttributeMandatory(entry.getKey())
+ && !matchMandatoryAttribute(entry.getKey(), sf))
+ {
+ return false;
+ }
+ }
+ } else {
+ String value = cap.getDirectives().get(Constants.MANDATORY_DIRECTIVE);
+ if (value != null) {
+ List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
+ for (Entry<String, Object> entry : cap.getAttributes().entrySet())
+ {
+ if (names.contains(entry.getKey())
+ && !matchMandatoryAttribute(entry.getKey(), sf))
+ {
+ return false;
+ }
+ }
+ }
+
+ }
+ return true;
+ }
+
+ private static boolean matchMandatoryAttribute(String attrName, SimpleFilter sf)
+ {
+ if ((sf.getName() != null) && sf.getName().equals(attrName))
+ {
+ return true;
+ }
+ else if (sf.getOperation() == SimpleFilter.AND)
+ {
+ List list = (List) sf.getValue();
+ for (int i = 0; i < list.size(); i++)
+ {
+ SimpleFilter sf2 = (SimpleFilter) list.get(i);
+ if ((sf2.getName() != null)
+ && sf2.getName().equals(attrName))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static final Class<?>[] STRING_CLASS = new Class[] { String.class };
+
+ private static boolean compare(Object lhs, Object rhsUnknown, int op)
+ {
+ if (lhs == null)
+ {
+ return false;
+ }
+
+ // If this is a PRESENT operation, then just return true immediately
+ // since we wouldn't be here if the attribute wasn't present.
+ if (op == SimpleFilter.PRESENT)
+ {
+ return true;
+ }
+
+ // If the type is comparable, then we can just return the
+ // result immediately.
+ if (lhs instanceof Comparable)
+ {
+ // Spec says SUBSTRING is false for all types other than string.
+ if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+ {
+ return false;
+ }
+
+ Object rhs;
+ if (op == SimpleFilter.SUBSTRING)
+ {
+ rhs = rhsUnknown;
+ }
+ else
+ {
+ try
+ {
+ rhs = coerceType(lhs, (String) rhsUnknown);
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ switch (op)
+ {
+ case SimpleFilter.EQ :
+ try
+ {
+ return (((Comparable) lhs).compareTo(rhs) == 0);
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ case SimpleFilter.GTE :
+ try
+ {
+ return (((Comparable) lhs).compareTo(rhs) >= 0);
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ case SimpleFilter.LTE :
+ try
+ {
+ return (((Comparable) lhs).compareTo(rhs) <= 0);
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ case SimpleFilter.APPROX :
+ return compareApproximate(((Comparable) lhs), rhs);
+ case SimpleFilter.SUBSTRING :
+ return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
+ default:
+ throw new RuntimeException(
+ "Unknown comparison operator: " + op);
+ }
+ }
+ // Booleans do not implement comparable, so special case them.
+ else if (lhs instanceof Boolean)
+ {
+ Object rhs;
+ try
+ {
+ rhs = coerceType(lhs, (String) rhsUnknown);
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+
+ switch (op)
+ {
+ case SimpleFilter.EQ :
+ case SimpleFilter.GTE :
+ case SimpleFilter.LTE :
+ case SimpleFilter.APPROX :
+ return (lhs.equals(rhs));
+ default:
+ throw new RuntimeException(
+ "Unknown comparison operator: " + op);
+ }
+ }
+
+ // If the LHS is not a comparable or boolean, check if it is an
+ // array. If so, convert it to a list so we can treat it as a
+ // collection.
+ if (lhs.getClass().isArray())
+ {
+ lhs = convertArrayToList(lhs);
+ }
+
+ // If LHS is a collection, then call compare() on each element
+ // of the collection until a match is found.
+ if (lhs instanceof Collection)
+ {
+ for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext(); )
+ {
+ if (compare(iter.next(), rhsUnknown, op))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Spec says SUBSTRING is false for all types other than string.
+ if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+ {
+ return false;
+ }
+
+ // Since we cannot identify the LHS type, then we can only perform
+ // equality comparison.
+ try
+ {
+ return lhs.equals(coerceType(lhs, (String) rhsUnknown));
+ }
+ catch (Exception ex)
+ {
+ return false;
+ }
+ }
+
+ private static boolean compareApproximate(Object lhs, Object rhs)
+ {
+ if (rhs instanceof String)
+ {
+ return removeWhitespace((String) lhs)
+ .equalsIgnoreCase(removeWhitespace((String) rhs));
+ }
+ else if (rhs instanceof Character)
+ {
+ return Character.toLowerCase(((Character) lhs))
+ == Character.toLowerCase(((Character) rhs));
+ }
+ return lhs.equals(rhs);
+ }
+
+ private static String removeWhitespace(String s)
+ {
+ StringBuffer sb = new StringBuffer(s.length());
+ for (int i = 0; i < s.length(); i++)
+ {
+ if (!Character.isWhitespace(s.charAt(i)))
+ {
+ sb.append(s.charAt(i));
+ }
+ }
+ return sb.toString();
+ }
+
+ private static Object coerceType(Object lhs, String rhsString) throws Exception
+ {
+ // If the LHS expects a string, then we can just return
+ // the RHS since it is a string.
+ if (lhs.getClass() == rhsString.getClass())
+ {
+ return rhsString;
+ }
+
+ // Try to convert the RHS type to the LHS type by using
+ // the string constructor of the LHS class, if it has one.
+ Object rhs = null;
+ try
+ {
+ // The Character class is a special case, since its constructor
+ // does not take a string, so handle it separately.
+ if (lhs instanceof Character)
+ {
+ rhs = new Character(rhsString.charAt(0));
+ }
+ else
+ {
+ // Spec says we should trim number types.
+ if ((lhs instanceof Number) || (lhs instanceof Boolean))
+ {
+ rhsString = rhsString.trim();
+ }
+ Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
+ ctor.setAccessible(true);
+ rhs = ctor.newInstance(new Object[] { rhsString });
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(
+ "Could not instantiate class "
+ + lhs.getClass().getName()
+ + " from string constructor with argument '"
+ + rhsString + "' because " + ex);
+ }
+
+ return rhs;
+ }
+
+ /**
+ * This is an ugly utility method to convert an array of primitives
+ * to an array of primitive wrapper objects. This method simplifies
+ * processing LDAP filters since the special case of primitive arrays
+ * can be ignored.
+ * @param array An array of primitive types.
+ * @return An corresponding array using pritive wrapper objects.
+ **/
+ private static List convertArrayToList(Object array)
+ {
+ int len = Array.getLength(array);
+ List list = new ArrayList(len);
+ for (int i = 0; i < len; i++)
+ {
+ list.add(Array.get(array, i));
+ }
+ return list;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
new file mode 100644
index 0000000..e211618
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public final class FeatureNamespace extends Namespace {
+
+ public static final String FEATURE_NAMESPACE = "karaf.feature";
+
+ public static final String CAPABILITY_VERSION_ATTRIBUTE = "version";
+
+ /**
+ * The attribute value identifying the resource
+ * {@link org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE type} as an OSGi bundle.
+ *
+ * @see org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
+ */
+ public static final String TYPE_FEATURE = "karaf.feature";
+
+ public static String getName(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(FEATURE_NAMESPACE))
+ {
+ return cap.getAttributes().get(FEATURE_NAMESPACE).toString();
+ }
+ }
+ return null;
+ }
+
+ public static Version getVersion(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(FEATURE_NAMESPACE))
+ {
+ return (Version)
+ cap.getAttributes().get(CAPABILITY_VERSION_ATTRIBUTE);
+ }
+ }
+ return null;
+ }
+
+
+ private FeatureNamespace() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
new file mode 100644
index 0000000..e3b0101
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.internal.util.Macro;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/**
+*/
+public class FeatureResource extends ResourceImpl {
+
+ private final Feature feature;
+
+ public static Resource build(Feature feature, Conditional conditional, String featureRange, Map<String, Resource> locToRes) throws BundleException {
+ Feature fcond = conditional.asFeature(feature.getName(), feature.getVersion());
+ FeatureResource resource = (FeatureResource) build(fcond, featureRange, locToRes);
+ for (String cond : conditional.getCondition()) {
+ if (cond.startsWith("req:")) {
+ cond = cond.substring("req:".length());
+ List<Requirement> reqs = ResourceBuilder.parseRequirement(resource, cond);
+ resource.addRequirements(reqs);
+ } else {
+ org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
+ String[] p = cond.split("/");
+ dep.setName(p[0]);
+ if (p.length > 1) {
+ dep.setVersion(p[1]);
+ }
+ addDependency(resource, dep, featureRange);
+ }
+ }
+ org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
+ dep.setName(feature.getName());
+ dep.setVersion(feature.getVersion());
+ addDependency(resource, dep, featureRange);
+ return resource;
+ }
+
+ public static Resource build(Feature feature, String featureRange, Map<String, Resource> locToRes) throws BundleException {
+ FeatureResource resource = new FeatureResource(feature);
+ Map<String, String> dirs = new HashMap<String, String>();
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(FeatureNamespace.FEATURE_NAMESPACE, feature.getName());
+ attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, VersionTable.getVersion(feature.getVersion()));
+ resource.addCapability(new CapabilityImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
+ for (BundleInfo info : feature.getBundles()) {
+ if (!info.isDependency()) {
+ Resource res = locToRes.get(info.getLocation());
+ if (res == null) {
+ throw new IllegalStateException("Resource not found for url " + info.getLocation());
+ }
+ List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ if (caps.size() != 1) {
+ throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
+ }
+ dirs = new HashMap<String, String>();
+ attrs = new HashMap<String, Object>();
+ attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, caps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
+ resource.addRequirement(new RequirementImpl(resource, IdentityNamespace.IDENTITY_NAMESPACE, dirs, attrs));
+ }
+ }
+ for (Dependency dep : feature.getDependencies()) {
+ addDependency(resource, dep, featureRange);
+ }
+ for (org.apache.karaf.features.Capability cap : feature.getCapabilities()) {
+ resource.addCapabilities(ResourceBuilder.parseCapability(resource, cap.getValue()));
+ }
+ for (org.apache.karaf.features.Requirement req : feature.getRequirements()) {
+ resource.addRequirements(ResourceBuilder.parseRequirement(resource, req.getValue()));
+ }
+ return resource;
+ }
+
+ protected static void addDependency(FeatureResource resource, Dependency dep, String featureRange) {
+ Map<String, String> dirs;
+ Map<String, Object> attrs;
+ String name = dep.getName();
+ String version = dep.getVersion();
+ if (version.equals("0.0.0")) {
+ version = null;
+ } else if (!version.startsWith("[") && !version.startsWith("(")) {
+ version = Macro.transform(featureRange, version);
+ }
+ dirs = new HashMap<String, String>();
+ attrs = new HashMap<String, Object>();
+ attrs.put(FeatureNamespace.FEATURE_NAMESPACE, name);
+ if (version != null) {
+ attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(version));
+ }
+ resource.addRequirement(new RequirementImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
+ }
+
+ public FeatureResource(Feature feature) {
+ super(feature.getName(), FeatureNamespace.TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
+ this.feature = feature;
+ }
+
+ public Feature getFeature() {
+ return feature;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
new file mode 100644
index 0000000..cdc00d1
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+class IdentityCapability extends BaseClause implements Capability
+{
+ private final Resource m_resource;
+ private final Map<String, String> m_dirs;
+ private final Map<String, Object> m_attrs;
+
+ public IdentityCapability(Resource resource, String name, String type, Version version)
+ {
+ m_resource = resource;
+ m_dirs = new HashMap<String, String>();
+ m_attrs = new HashMap<String, Object>();
+ m_attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
+ m_attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, type);
+ m_attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+ }
+
+ public String getNamespace()
+ {
+ return IdentityNamespace.IDENTITY_NAMESPACE;
+ }
+
+ public Map<String, String> getDirectives()
+ {
+ return m_dirs;
+ }
+
+ public Map<String, Object> getAttributes()
+ {
+ return m_attrs;
+ }
+
+ public Resource getResource()
+ {
+ return m_resource;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
new file mode 100644
index 0000000..a4ef775
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class RequirementImpl extends BaseClause implements Requirement {
+ private final Resource m_resource;
+ private final String m_namespace;
+ private final SimpleFilter m_filter;
+ private final boolean m_optional;
+ private final Map<String, String> m_dirs;
+ private final Map<String, Object> m_attrs;
+
+ public RequirementImpl(
+ Resource resource, String namespace,
+ Map<String, String> dirs, Map<String, Object> attrs, SimpleFilter filter) {
+ m_resource = resource;
+ m_namespace = namespace;
+ m_dirs = dirs;
+ m_attrs = attrs;
+ m_filter = filter;
+ // Find resolution import directives.
+ m_optional = Constants.RESOLUTION_OPTIONAL.equals(m_dirs.get(Constants.RESOLUTION_DIRECTIVE));
+ }
+
+ public RequirementImpl(
+ Resource resource, String namespace,
+ Map<String, String> dirs, Map<String, Object> attrs) {
+ this(resource, namespace, dirs, attrs, SimpleFilter.convert(attrs));
+ }
+
+ public String getNamespace() {
+ return m_namespace;
+ }
+
+ public Map<String, String> getDirectives() {
+ return m_dirs;
+ }
+
+ public Map<String, Object> getAttributes() {
+ return m_attrs;
+ }
+
+ public Resource getResource() {
+ return m_resource;
+ }
+
+ public boolean matches(Capability cap) {
+ return CapabilitySet.matches(cap, getFilter());
+ }
+
+ public boolean isOptional() {
+ return m_optional;
+ }
+
+ public SimpleFilter getFilter() {
+ return m_filter;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
new file mode 100644
index 0000000..e2ff793
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wiring;
+import org.osgi.service.repository.Repository;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolveContext;
+
+/**
+*/
+public class ResolveContextImpl extends ResolveContext {
+
+ private final Set<Resource> mandatory;
+ private final Set<Resource> optional;
+ private final Repository repository;
+ private final Map<Resource, Wiring> wirings;
+ private final boolean resolveOptional;
+
+ private final CandidateComparator candidateComparator = new CandidateComparator();
+
+ public ResolveContextImpl(Set<Resource> mandatory,
+ Set<Resource> optional,
+ Repository repository,
+ boolean resolveOptional) {
+ this.mandatory = mandatory;
+ this.optional = optional;
+ this.repository = repository;
+ this.wirings = new HashMap<Resource, Wiring>();
+ this.resolveOptional = resolveOptional;
+ }
+
+ @Override
+ public Collection<Resource> getMandatoryResources() {
+ return mandatory;
+ }
+
+ @Override
+ public Collection<Resource> getOptionalResources() {
+ return optional;
+ }
+
+ @Override
+ public List<Capability> findProviders(Requirement requirement) {
+ List<Capability> caps = new ArrayList<Capability>();
+ Map<Requirement, Collection<Capability>> resMap =
+ repository.findProviders(Collections.singleton(requirement));
+ Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
+ if (res != null) {
+ caps.addAll(res);
+ }
+ Collections.sort(caps, candidateComparator);
+ return caps;
+ }
+ @Override
+ public int insertHostedCapability(List capabilities, HostedCapability hostedCapability) {
+ for (int i=0; i < capabilities.size(); i++) {
+ Capability cap = (Capability) capabilities.get(i);
+ if (candidateComparator.compare(hostedCapability, cap) <= 0) {
+ capabilities.add(i, hostedCapability);
+ return i;
+ }
+ }
+ capabilities.add(hostedCapability);
+ return capabilities.size() - 1;
+ }
+ @Override
+ public boolean isEffective(Requirement requirement) {
+ return resolveOptional ||
+ !Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
+ }
+ @Override
+ public Map<Resource, Wiring> getWirings() {
+ return wirings;
+ }
+}
[33/33] git commit: [KARAF-2902] Separate section for Karaf-xxx
headers and sort headers
Posted by gn...@apache.org.
[KARAF-2902] Separate section for Karaf-xxx headers and sort headers
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/fd4b3f67
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/fd4b3f67
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/fd4b3f67
Branch: refs/heads/master
Commit: fd4b3f67799c1d37f6756e1a9d2fe4c3c780f4e9
Parents: 6727c1b
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 19:19:13 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:04 2014 +0200
----------------------------------------------------------------------
.../apache/karaf/bundle/command/Headers.java | 27 ++++++++++++++++----
1 file changed, 22 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/fd4b3f67/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
index 16083ff..5cf92c3 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.TreeMap;
import org.apache.felix.utils.manifest.Attribute;
import org.apache.felix.utils.manifest.Clause;
@@ -48,6 +49,7 @@ import org.osgi.framework.wiring.BundleWiring;
@Service
public class Headers extends BundlesCommand {
+ protected final static String KARAF_PREFIX = "Karaf-";
protected final static String BUNDLE_PREFIX = "Bundle-";
protected final static String PACKAGE_SUFFFIX = "-Package";
protected final static String SERVICE_SUFFIX = "-Service";
@@ -90,10 +92,11 @@ public class Headers extends BundlesCommand {
protected String generateFormattedOutput(Bundle bundle) {
StringBuilder output = new StringBuilder();
- Map<String, Object> otherAttribs = new HashMap<String, Object>();
- Map<String, Object> bundleAttribs = new HashMap<String, Object>();
- Map<String, Object> serviceAttribs = new HashMap<String, Object>();
- Map<String, Object> packagesAttribs = new HashMap<String, Object>();
+ Map<String, Object> otherAttribs = new TreeMap<String, Object>();
+ Map<String, Object> karafAttribs = new TreeMap<String, Object>();
+ Map<String, Object> bundleAttribs = new TreeMap<String, Object>();
+ Map<String, Object> serviceAttribs = new TreeMap<String, Object>();
+ Map<String, Object> packagesAttribs = new TreeMap<String, Object>();
Dictionary<String, String> dict = bundle.getHeaders();
Enumeration<String> keys = dict.keys();
@@ -101,7 +104,10 @@ public class Headers extends BundlesCommand {
while (keys.hasMoreElements()) {
String k = (String) keys.nextElement();
Object v = dict.get(k);
- if (k.startsWith(BUNDLE_PREFIX)) {
+ if (k.startsWith(KARAF_PREFIX)) {
+ // starts with Karaf-xxx
+ karafAttribs.put(k, v);
+ } else if (k.startsWith(BUNDLE_PREFIX)) {
// starts with Bundle-xxx
bundleAttribs.put(k, v);
} else if (k.endsWith(SERVICE_SUFFIX) || k.endsWith(CAPABILITY_SUFFIX)) {
@@ -124,6 +130,8 @@ public class Headers extends BundlesCommand {
// -----------------------
// all other attributes
//
+ // all Karaf attributes
+ //
// all Bundle attributes
//
// all Service attributes
@@ -138,6 +146,15 @@ public class Headers extends BundlesCommand {
output.append('\n');
}
+ it = karafAttribs.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, Object> e = it.next();
+ output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
+ }
+ if (karafAttribs.size() > 0) {
+ output.append('\n');
+ }
+
it = bundleAttribs.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Object> e = it.next();
[19/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java b/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
deleted file mode 100644
index 44e9a7c..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.net.URI;
-
-/**
- * Simple abstraction of a maven artifact to avoid external deps
- */
-public class Artifact {
- String groupId;
- String artifactId;
- String version;
- String extension;
- String classifier;
-
- public Artifact(String coords) {
- String[] coordsAr = coords.split(":");
- if (coordsAr.length != 5) {
- throw new IllegalArgumentException("Maven URL " + coords + " is malformed or not complete");
- }
- this.groupId = coordsAr[0];
- this.artifactId = coordsAr[1];
- this.version = coordsAr[4];
- this.extension = coordsAr[2];
- this.classifier = coordsAr[3];
- }
-
- public Artifact(String coords, String version) {
- this(coords);
- this.version = version;
- }
-
- public URI getMavenUrl(String version) {
- String uriSt = "mvn:" + this.groupId + "/" + this.artifactId + "/" + version + "/" + this.extension + "/" + this.classifier;
- try {
- return new URI(uriSt);
- } catch (Exception e) {
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
deleted file mode 100644
index 5b362b8..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.features.BootFinished;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BootFeaturesInstaller {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(BootFeaturesInstaller.class);
-
- public static String VERSION_PREFIX = "version=";
-
- private final FeaturesServiceImpl featuresService;
- private final BundleContext bundleContext;
- private final String repositories;
- private final String features;
- private final boolean asynchronous;
-
- /**
- *
- * @param features list of boot features separated by comma. Optionally contains ;version=x.x.x to specify a specific feature version
- */
- public BootFeaturesInstaller(BundleContext bundleContext,
- FeaturesServiceImpl featuresService,
- String repositories,
- String features,
- boolean asynchronous) {
- this.bundleContext = bundleContext;
- this.featuresService = featuresService;
- this.repositories = repositories;
- this.features = features;
- this.asynchronous = asynchronous;
- }
-
- /**
- * Install boot features
- */
- public void start() {
- if (featuresService.isBootDone()) {
- publishBootFinished();
- return;
- }
- if (asynchronous) {
- new Thread("Initial Features Provisioning") {
- public void run() {
- installBootFeatures();
- }
- }.start();
- } else {
- installBootFeatures();
- }
- }
-
- protected void installBootFeatures() {
- try {
- for (String repo : repositories.split(",")) {
- repo = repo.trim();
- if (!repo.isEmpty()) {
- try {
- featuresService.addRepository(URI.create(repo));
- } catch (Exception e) {
- LOGGER.error("Error installing boot feature repository " + repo, e);
- }
- }
- }
-
- List<Set<String>> stagedFeatures = parseBootFeatures(features);
- for (Set<String> features : stagedFeatures) {
- featuresService.installFeatures(features, EnumSet.of(FeaturesService.Option.NoFailOnFeatureNotFound));
- }
- featuresService.bootDone();
- publishBootFinished();
- } catch (Exception e) {
- // Special handling in case the bundle has been refreshed.
- // In such a case, simply exits without logging any exception
- // as the restart should cause the feature service to finish
- // the work.
- if (e instanceof IllegalStateException) {
- try {
- bundleContext.getBundle();
- } catch (IllegalStateException ies) {
- return;
- }
- }
- LOGGER.error("Error installing boot features", e);
- }
- }
-
- /**
- *
- * @param featureSt either feature name or <featurename>;version=<version>
- * @return feature matching the feature string
- * @throws Exception
- */
- private Feature getFeature(String featureSt) throws Exception {
- String[] parts = featureSt.trim().split(";");
- String featureName = parts[0];
- String featureVersion = null;
- for (String part : parts) {
- // if the part starts with "version=" it contains the version info
- if (part.startsWith(VERSION_PREFIX)) {
- featureVersion = part.substring(VERSION_PREFIX.length());
- }
- }
- if (featureVersion == null) {
- // no version specified - use default version
- featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
- }
- return featuresService.getFeature(featureName, featureVersion);
- }
-
- protected List<Set<String>> parseBootFeatures(String bootFeatures) {
- Pattern pattern = Pattern.compile("(\\((.+))\\),|.+");
- Matcher matcher = pattern.matcher(bootFeatures);
- List<Set<String>> result = new ArrayList<Set<String>>();
- while (matcher.find()) {
- String group = matcher.group(2) != null ? matcher.group(2) : matcher.group();
- result.add(parseFeatureList(group));
- }
- return result;
- }
-
- protected Set<String> parseFeatureList(String group) {
- HashSet<String> features = new HashSet<String>();
- for (String feature : Arrays.asList(group.trim().split("\\s*,\\s*"))) {
- if (feature.length() > 0) {
- features.add(feature);
- }
- }
- return features;
- }
-
- private void publishBootFinished() {
- if (bundleContext != null) {
- BootFinished bootFinished = new BootFinished() {};
- bundleContext.registerService(BootFinished.class, bootFinished, new Hashtable<String, String>());
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java b/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
deleted file mode 100644
index b6eaae5..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.features.EventConstants;
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.RepositoryEvent;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * A listener to publish events to EventAdmin
- */
-public class EventAdminListener implements FeaturesListener {
-
- private final ServiceTracker<EventAdmin, EventAdmin> tracker;
-
- public EventAdminListener(BundleContext context) {
- tracker = new ServiceTracker<EventAdmin, EventAdmin>(context, EventAdmin.class.getName(), null);
- tracker.open();
- }
-
- public void featureEvent(FeatureEvent event) {
- EventAdmin eventAdmin = tracker.getService();
- if (eventAdmin == null) {
- return;
- }
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(EventConstants.TYPE, event.getType());
- props.put(EventConstants.EVENT, event);
- props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
- props.put(EventConstants.FEATURE_NAME, event.getFeature().getName());
- props.put(EventConstants.FEATURE_VERSION, event.getFeature().getVersion());
- String topic;
- switch (event.getType()) {
- case FeatureInstalled:
- topic = EventConstants.TOPIC_FEATURES_INSTALLED;
- break;
- case FeatureUninstalled:
- topic = EventConstants.TOPIC_FEATURES_UNINSTALLED;
- break;
- default:
- throw new IllegalStateException("Unknown features event type: " + event.getType());
- }
- eventAdmin.postEvent(new Event(topic, props));
- }
-
- public void repositoryEvent(RepositoryEvent event) {
- EventAdmin eventAdmin = tracker.getService();
- if (eventAdmin == null) {
- return;
- }
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(EventConstants.TYPE, event.getType());
- props.put(EventConstants.EVENT, event);
- props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
- props.put(EventConstants.REPOSITORY_URI, event.getRepository().getURI().toString());
- String topic;
- switch (event.getType()) {
- case RepositoryAdded:
- topic = EventConstants.TOPIC_REPOSITORY_ADDED;
- break;
- case RepositoryRemoved:
- topic = EventConstants.TOPIC_REPOSITORY_REMOVED;
- break;
- default:
- throw new IllegalStateException("Unknown repository event type: " + event.getType());
- }
- eventAdmin.postEvent(new Event(topic, props));
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
deleted file mode 100644
index 0e9038d..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Feature;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FeatureConfigInstaller {
- private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
- private static final String CONFIG_KEY = "org.apache.karaf.features.configKey";
-
- private final ConfigurationAdmin configAdmin;
-
- public FeatureConfigInstaller(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- private String[] parsePid(String pid) {
- int n = pid.indexOf('-');
- if (n > 0) {
- String factoryPid = pid.substring(n + 1);
- pid = pid.substring(0, n);
- return new String[]{pid, factoryPid};
- } else {
- return new String[]{pid, null};
- }
- }
-
- private Configuration createConfiguration(ConfigurationAdmin configurationAdmin,
- String pid, String factoryPid) throws IOException, InvalidSyntaxException {
- if (factoryPid != null) {
- return configurationAdmin.createFactoryConfiguration(factoryPid, null);
- } else {
- return configurationAdmin.getConfiguration(pid, null);
- }
- }
-
- private Configuration findExistingConfiguration(ConfigurationAdmin configurationAdmin,
- String pid, String factoryPid) throws IOException, InvalidSyntaxException {
- String filter;
- if (factoryPid == null) {
- filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
- } else {
- String key = createConfigurationKey(pid, factoryPid);
- filter = "(" + CONFIG_KEY + "=" + key + ")";
- }
- Configuration[] configurations = configurationAdmin.listConfigurations(filter);
- if (configurations != null && configurations.length > 0) {
- return configurations[0];
- }
- return null;
- }
-
- void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
- for (String config : feature.getConfigurations().keySet()) {
- Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config));
- String[] pid = parsePid(config);
- Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
- if (cfg == null) {
- cfg = createConfiguration(configAdmin, pid[0], pid[1]);
- String key = createConfigurationKey(pid[0], pid[1]);
- props.put(CONFIG_KEY, key);
- if (cfg.getBundleLocation() != null) {
- cfg.setBundleLocation(null);
- }
- cfg.update(props);
- }
- }
- for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
- installConfigurationFile(configFile.getLocation(), configFile.getFinalname(), configFile.isOverride());
- }
- }
-
- private String createConfigurationKey(String pid, String factoryPid) {
- return factoryPid == null ? pid : pid + "-" + factoryPid;
- }
-
- private void installConfigurationFile(String fileLocation, String finalname, boolean override) throws IOException {
- String basePath = System.getProperty("karaf.base");
-
- if (finalname.contains("${")) {
- //remove any placeholder or variable part, this is not valid.
- int marker = finalname.indexOf("}");
- finalname = finalname.substring(marker+1);
- }
-
- finalname = basePath + File.separator + finalname;
-
- File file = new File(finalname);
- if (file.exists()) {
- if (!override) {
- LOGGER.debug("Configuration file {} already exist, don't override it", finalname);
- return;
- } else {
- LOGGER.info("Configuration file {} already exist, overriding it", finalname);
- }
- } else {
- LOGGER.info("Creating configuration file {}", finalname);
- }
-
- InputStream is = null;
- FileOutputStream fop = null;
- try {
- is = new BufferedInputStream(new URL(fileLocation).openStream());
-
- if (!file.exists()) {
- File parentFile = file.getParentFile();
- if (parentFile != null)
- parentFile.mkdirs();
- file.createNewFile();
- }
-
- fop = new FileOutputStream(file);
-
- int bytesRead;
- byte[] buffer = new byte[1024];
-
- while ((bytesRead = is.read(buffer)) != -1) {
- fop.write(buffer, 0, bytesRead);
- }
- } catch (RuntimeException e) {
- LOGGER.error(e.getMessage());
- throw e;
- } catch (MalformedURLException e) {
- LOGGER.error(e.getMessage());
- throw e;
- } finally {
- if (is != null)
- is.close();
- if (fop != null) {
- fop.flush();
- fop.close();
- }
- }
-
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
deleted file mode 100644
index d6defe0..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.net.URI;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-
-public class FeatureFinder implements ManagedService {
-
- final Map<String, String> nameToArtifactMap = new HashMap<String, String>();
-
- public String[] getNames() {
- synchronized (nameToArtifactMap) {
- Set<String> strings = nameToArtifactMap.keySet();
- return strings.toArray(new String[strings.size()]);
- }
- }
-
- public URI getUriFor(String name, String version) {
- String coords;
- synchronized (nameToArtifactMap) {
- coords = nameToArtifactMap.get(name);
- }
- if (coords == null) {
- return null;
- }
- Artifact artifact = new Artifact(coords);
- return artifact.getMavenUrl(version);
- }
-
- @SuppressWarnings("rawtypes")
- public void updated(Dictionary properties) throws ConfigurationException {
- synchronized (nameToArtifactMap) {
- if (properties != null) {
- nameToArtifactMap.clear();
- Enumeration keys = properties.keys();
- while (keys.hasMoreElements()) {
- String key = (String) keys.nextElement();
- if (!"felix.fileinstall.filename".equals(key) && !"service.pid".equals(key)) {
- nameToArtifactMap.put(key, (String) properties.get(key));
- }
- }
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
deleted file mode 100644
index 6903dc0..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.net.URI;
-
-import org.apache.karaf.features.internal.model.JaxbUtil;
-
-/**
- * Utility class which fires XML Schema validation.
- */
-public class FeatureValidationUtil {
-
- /**
- * Runs schema validation.
- *
- * @param uri Uri to validate.
- * @throws Exception When validation fails.
- */
- public static void validate(URI uri) throws Exception {
- JaxbUtil.unmarshal(uri.toASCIIString(), true);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
deleted file mode 100644
index 0243dc0..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ /dev/null
@@ -1,1416 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.RepositoryEvent;
-import org.apache.karaf.features.internal.deployment.DeploymentBuilder;
-import org.apache.karaf.features.internal.deployment.StreamProvider;
-import org.apache.karaf.features.internal.resolver.FeatureNamespace;
-import org.apache.karaf.features.internal.resolver.UriNamespace;
-import org.apache.karaf.features.internal.util.ChecksumUtils;
-import org.apache.karaf.features.internal.util.Macro;
-import org.apache.karaf.features.internal.util.MultiException;
-import org.apache.karaf.util.collections.CopyOnWriteArrayIdentityList;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wire;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.felix.resolver.Util.getSymbolicName;
-import static org.apache.felix.resolver.Util.getVersion;
-
-/**
- *
- */
-public class FeaturesServiceImpl implements FeaturesService {
-
- public static final String UPDATE_SNAPSHOTS_NONE = "none";
- public static final String UPDATE_SNAPSHOTS_CRC = "crc";
- public static final String UPDATE_SNAPSHOTS_ALWAYS = "always";
- public static final String DEFAULT_UPDATE_SNAPSHOTS = UPDATE_SNAPSHOTS_CRC;
-
- public static final String DEFAULT_FEATURE_RESOLUTION_RANGE = "${range;[====,====]}";
- public static final String DEFAULT_BUNDLE_UPDATE_RANGE = "${range;[==,=+)}";
-
- private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
- private static final String SNAPSHOT = "SNAPSHOT";
- private static final String MAVEN = "mvn:";
-
- /**
- * Our bundle.
- * We use it to check bundle operations affecting our own bundle.
- */
- private final Bundle bundle;
-
- /**
- * The system bundle context.
- * For all bundles related operations, we use the system bundle context
- * to allow this bundle to be stopped and still allow the deployment to
- * take place.
- */
- private final BundleContext systemBundleContext;
- /**
- * Used to load and save the {@link State} of this service.
- */
- private final StateStorage storage;
- private final FeatureFinder featureFinder;
- private final EventAdminListener eventAdminListener;
- private final FeatureConfigInstaller configInstaller;
- private final String overrides;
- /**
- * Range to use when a version is specified on a feature dependency.
- * The default is {@link FeaturesServiceImpl#DEFAULT_FEATURE_RESOLUTION_RANGE}
- */
- private final String featureResolutionRange;
- /**
- * Range to use when verifying if a bundle should be updated or
- * new bundle installed.
- * The default is {@link FeaturesServiceImpl#DEFAULT_BUNDLE_UPDATE_RANGE}
- */
- private final String bundleUpdateRange;
- /**
- * Use CRC to check snapshot bundles and update them if changed.
- * Either:
- * - none : never update snapshots
- * - always : always update snapshots
- * - crc : use CRC to detect changes
- */
- private final String updateSnaphots;
-
- private final List<FeaturesListener> listeners = new CopyOnWriteArrayIdentityList<FeaturesListener>();
-
- // Synchronized on lock
- private final Object lock = new Object();
- private final State state = new State();
- private final Map<String, Repository> repositoryCache = new HashMap<String, Repository>();
- private Map<String, Map<String, Feature>> featureCache;
-
-
- public FeaturesServiceImpl(Bundle bundle,
- BundleContext systemBundleContext,
- StateStorage storage,
- FeatureFinder featureFinder,
- EventAdminListener eventAdminListener,
- FeatureConfigInstaller configInstaller,
- String overrides,
- String featureResolutionRange,
- String bundleUpdateRange,
- String updateSnaphots) {
- this.bundle = bundle;
- this.systemBundleContext = systemBundleContext;
- this.storage = storage;
- this.featureFinder = featureFinder;
- this.eventAdminListener = eventAdminListener;
- this.configInstaller = configInstaller;
- this.overrides = overrides;
- this.featureResolutionRange = featureResolutionRange;
- this.bundleUpdateRange = bundleUpdateRange;
- this.updateSnaphots = updateSnaphots;
- loadState();
- }
-
- //
- // State support
- //
-
- protected void loadState() {
- try {
- synchronized (lock) {
- storage.load(state);
- }
- } catch (IOException e) {
- LOGGER.warn("Error loading FeaturesService state", e);
- }
- }
-
- protected void saveState() {
- try {
- synchronized (lock) {
- // Make sure we don't store bundle checksums if
- // it has been disabled through configadmin
- // so that we don't keep out-of-date checksums.
- if (!UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
- state.bundleChecksums.clear();
- }
- storage.save(state);
- }
- } catch (IOException e) {
- LOGGER.warn("Error saving FeaturesService state", e);
- }
- }
-
- boolean isBootDone() {
- synchronized (lock) {
- return state.bootDone.get();
- }
- }
-
- void bootDone() {
- synchronized (lock) {
- state.bootDone.set(true);
- saveState();
- }
- }
-
- //
- // Listeners support
- //
-
- public void registerListener(FeaturesListener listener) {
- listeners.add(listener);
- try {
- Set<String> repositories = new TreeSet<String>();
- Set<String> installedFeatures = new TreeSet<String>();
- synchronized (lock) {
- repositories.addAll(state.repositories);
- installedFeatures.addAll(state.installedFeatures);
- }
- for (String uri : repositories) {
- Repository repository = new RepositoryImpl(URI.create(uri));
- listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
- }
- for (String id : installedFeatures) {
- Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf(id);
- listener.featureEvent(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, true));
- }
- } catch (Exception e) {
- LOGGER.error("Error notifying listener about the current state", e);
- }
- }
-
- public void unregisterListener(FeaturesListener listener) {
- listeners.remove(listener);
- }
-
- protected void callListeners(FeatureEvent event) {
- if (eventAdminListener != null) {
- eventAdminListener.featureEvent(event);
- }
- for (FeaturesListener listener : listeners) {
- listener.featureEvent(event);
- }
- }
-
- protected void callListeners(RepositoryEvent event) {
- if (eventAdminListener != null) {
- eventAdminListener.repositoryEvent(event);
- }
- for (FeaturesListener listener : listeners) {
- listener.repositoryEvent(event);
- }
- }
-
- //
- // Feature Finder support
- //
-
- @Override
- public URI getRepositoryUriFor(String name, String version) {
- return featureFinder.getUriFor(name, version);
- }
-
- @Override
- public String[] getRepositoryNames() {
- return featureFinder.getNames();
- }
-
-
- //
- // Repositories support
- //
-
- public Repository loadRepository(URI uri) throws Exception {
- RepositoryImpl repo = new RepositoryImpl(uri);
- repo.load(true);
- return repo;
- }
-
- @Override
- public void validateRepository(URI uri) throws Exception {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void addRepository(URI uri) throws Exception {
- addRepository(uri, false);
- }
-
- @Override
- public void addRepository(URI uri, boolean install) throws Exception {
- if (install) {
- // TODO: implement
- throw new UnsupportedOperationException();
- }
- Repository repository = loadRepository(uri);
- synchronized (lock) {
- // Clean cache
- repositoryCache.put(uri.toString(), repository);
- featureCache = null;
- // Add repo
- if (!state.repositories.add(uri.toString())) {
- return;
- }
- saveState();
- }
- callListeners(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, false));
- }
-
- @Override
- public void removeRepository(URI uri) throws Exception {
- removeRepository(uri, true);
- }
-
- @Override
- public void removeRepository(URI uri, boolean uninstall) throws Exception {
- // TODO: check we don't have any feature installed from this repository
- Repository repo;
- synchronized (lock) {
- // Remove repo
- if (!state.repositories.remove(uri.toString())) {
- return;
- }
- // Clean cache
- featureCache = null;
- repo = repositoryCache.get(uri.toString());
- List<String> toRemove = new ArrayList<String>();
- toRemove.add(uri.toString());
- while (!toRemove.isEmpty()) {
- Repository rep = repositoryCache.remove(toRemove.remove(0));
- if (rep != null) {
- for (URI u : rep.getRepositories()) {
- toRemove.add(u.toString());
- }
- }
- }
- saveState();
- }
- if (repo == null) {
- repo = new RepositoryImpl(uri);
- }
- callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryRemoved, false));
- }
-
- @Override
- public void restoreRepository(URI uri) throws Exception {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void refreshRepository(URI uri) throws Exception {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Repository[] listRepositories() throws Exception {
- // Make sure the cache is loaded
- getFeatures();
- synchronized (lock) {
- return repositoryCache.values().toArray(new Repository[repositoryCache.size()]);
- }
- }
-
- @Override
- public Repository[] listRequiredRepositories() throws Exception {
- // Make sure the cache is loaded
- getFeatures();
- synchronized (lock) {
- List<Repository> repos = new ArrayList<Repository>();
- for (Map.Entry<String, Repository> entry : repositoryCache.entrySet()) {
- if (state.repositories.contains(entry.getKey())) {
- repos.add(entry.getValue());
- }
- }
- return repos.toArray(new Repository[repos.size()]);
- }
- }
-
- @Override
- public Repository getRepository(String name) throws Exception {
- // Make sure the cache is loaded
- getFeatures();
- synchronized (lock) {
- for (Repository repo : this.repositoryCache.values()) {
- if (name.equals(repo.getName())) {
- return repo;
- }
- }
- return null;
- }
- }
-
- //
- // Features support
- //
-
- public Feature getFeature(String name) throws Exception {
- return getFeature(name, null);
- }
-
- public Feature getFeature(String name, String version) throws Exception {
- Map<String, Feature> versions = getFeatures().get(name);
- return getFeatureMatching(versions, version);
- }
-
- protected Feature getFeatureMatching(Map<String, Feature> versions, String version) {
- if (version != null) {
- version = version.trim();
- if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
- version = "";
- }
- } else {
- version = "";
- }
- if (versions == null || versions.isEmpty()) {
- return null;
- } else {
- Feature feature = version.isEmpty() ? null : versions.get(version);
- if (feature == null) {
- // Compute version range. If an version has been given, assume exact range
- VersionRange versionRange = version.isEmpty() ?
- new VersionRange(Version.emptyVersion) :
- new VersionRange(version, true, true);
- Version latest = Version.emptyVersion;
- for (String available : versions.keySet()) {
- Version availableVersion = VersionTable.getVersion(available);
- if (availableVersion.compareTo(latest) >= 0 && versionRange.contains(availableVersion)) {
- feature = versions.get(available);
- latest = availableVersion;
- }
- }
- }
- return feature;
- }
- }
-
- public Feature[] listFeatures() throws Exception {
- Set<Feature> features = new HashSet<Feature>();
- for (Map<String, Feature> featureWithDifferentVersion : getFeatures().values()) {
- for (Feature f : featureWithDifferentVersion.values()) {
- features.add(f);
- }
- }
- return features.toArray(new Feature[features.size()]);
- }
-
- protected Map<String, Map<String, Feature>> getFeatures() throws Exception {
- List<String> uris;
- synchronized (lock) {
- if (featureCache != null) {
- return featureCache;
- }
- uris = new ArrayList<String>(state.repositories);
- }
- //the outer map's key is feature name, the inner map's key is feature version
- Map<String, Map<String, Feature>> map = new HashMap<String, Map<String, Feature>>();
- // Two phase load:
- // * first load dependent repositories
- List<String> toLoad = new ArrayList<String>(uris);
- while (!toLoad.isEmpty()) {
- String uri = toLoad.remove(0);
- Repository repo;
- synchronized (lock) {
- repo = repositoryCache.get(uri);
- }
- if (repo == null) {
- RepositoryImpl rep = new RepositoryImpl(URI.create(uri));
- rep.load();
- repo = rep;
- synchronized (lock) {
- repositoryCache.put(uri, repo);
- }
- }
- for (URI u : repo.getRepositories()) {
- toLoad.add(u.toString());
- }
- }
- List<Repository> repos;
- synchronized (lock) {
- repos = new ArrayList<Repository>(repositoryCache.values());
- }
- // * then load all features
- for (Repository repo : repos) {
- for (Feature f : repo.getFeatures()) {
- if (map.get(f.getName()) == null) {
- Map<String, Feature> versionMap = new HashMap<String, Feature>();
- versionMap.put(f.getVersion(), f);
- map.put(f.getName(), versionMap);
- } else {
- map.get(f.getName()).put(f.getVersion(), f);
- }
- }
- }
- synchronized (lock) {
- if (uris.size() == state.repositories.size() &&
- state.repositories.containsAll(uris)) {
- featureCache = map;
- }
- }
- return map;
- }
-
- //
- // Installed features
- //
-
- @Override
- public Feature[] listInstalledFeatures() throws Exception {
- Set<Feature> features = new HashSet<Feature>();
- Map<String, Map<String, Feature>> allFeatures = getFeatures();
- synchronized (lock) {
- for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
- for (Feature f : featureWithDifferentVersion.values()) {
- if (isInstalled(f)) {
- features.add(f);
- }
- }
- }
- }
- return features.toArray(new Feature[features.size()]);
- }
-
- @Override
- public Feature[] listRequiredFeatures() throws Exception {
- Set<Feature> features = new HashSet<Feature>();
- Map<String, Map<String, Feature>> allFeatures = getFeatures();
- synchronized (lock) {
- for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
- for (Feature f : featureWithDifferentVersion.values()) {
- if (isRequired(f)) {
- features.add(f);
- }
- }
- }
- }
- return features.toArray(new Feature[features.size()]);
- }
-
-
- @Override
- public boolean isInstalled(Feature f) {
- String id = normalize(f.getId());
- synchronized (lock) {
- return state.installedFeatures.contains(id);
- }
- }
-
- @Override
- public boolean isRequired(Feature f) {
- String id = normalize(f.getId());
- synchronized (lock) {
- return state.features.contains(id);
- }
- }
-
- //
- // Installation and uninstallation of features
- //
-
- public void installFeature(String name) throws Exception {
- installFeature(name, EnumSet.noneOf(Option.class));
- }
-
- public void installFeature(String name, String version) throws Exception {
- installFeature(version != null ? name + "/" + version : name, EnumSet.noneOf(Option.class));
- }
-
- public void installFeature(String name, EnumSet<Option> options) throws Exception {
- installFeatures(Collections.singleton(name), options);
- }
-
- public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
- installFeature(version != null ? name + "/" + version : name, options);
- }
-
- public void installFeature(Feature feature, EnumSet<Option> options) throws Exception {
- installFeature(feature.getId());
- }
-
- @Override
- public void uninstallFeature(String name, String version) throws Exception {
- uninstallFeature(version != null ? name + "/" + version : name);
- }
-
- @Override
- public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
- uninstallFeature(version != null ? name + "/" + version : name, options);
- }
-
- @Override
- public void uninstallFeature(String name) throws Exception {
- uninstallFeature(name, EnumSet.noneOf(Option.class));
- }
-
- @Override
- public void uninstallFeature(String name, EnumSet<Option> options) throws Exception {
- uninstallFeatures(Collections.singleton(name), options);
- }
-
-
- //
- //
- //
- // RESOLUTION
- //
- //
- //
-
-
-
-
-
-
- public void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
- Set<String> required;
- Set<String> installed;
- Set<Long> managed;
- synchronized (lock) {
- required = new HashSet<String>(state.features);
- installed = new HashSet<String>(state.installedFeatures);
- managed = new HashSet<Long>(state.managedBundles);
- }
- List<String> featuresToAdd = new ArrayList<String>();
- Map<String, Map<String, Feature>> featuresMap = getFeatures();
- for (String feature : features) {
- feature = normalize(feature);
- String name = feature.substring(0, feature.indexOf("/"));
- String version = feature.substring(feature.indexOf("/") + 1);
- Feature f = getFeatureMatching(featuresMap.get(name), version);
- if (f == null) {
- if (!options.contains(Option.NoFailOnFeatureNotFound)) {
- throw new IllegalArgumentException("No matching features for " + feature);
- }
- } else {
- featuresToAdd.add(normalize(f.getId()));
- }
- }
- featuresToAdd = new ArrayList<String>(new LinkedHashSet<String>(featuresToAdd));
- StringBuilder sb = new StringBuilder();
- sb.append("Adding features: ");
- for (int i = 0; i < featuresToAdd.size(); i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(featuresToAdd.get(i));
- }
- print(sb.toString(), options.contains(Option.Verbose));
- required.addAll(featuresToAdd);
- doInstallFeaturesInThread(required, installed, managed, options);
- }
-
- public void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
- Set<String> required;
- Set<String> installed;
- Set<Long> managed;
- synchronized (lock) {
- required = new HashSet<String>(state.features);
- installed = new HashSet<String>(state.installedFeatures);
- managed = new HashSet<Long>(state.managedBundles);
- }
- List<String> featuresToRemove = new ArrayList<String>();
- for (String feature : new HashSet<String>(features)) {
- List<String> toRemove = new ArrayList<String>();
- feature = normalize(feature);
- if (feature.endsWith("/0.0.0")) {
- String nameSep = feature.substring(0, feature.indexOf("/") + 1);
- for (String f : required) {
- if (normalize(f).startsWith(nameSep)) {
- toRemove.add(f);
- }
- }
- } else {
- toRemove.add(feature);
- }
- toRemove.retainAll(required);
- if (toRemove.isEmpty()) {
- throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
- } else if (toRemove.size() > 1) {
- String name = feature.substring(0, feature.indexOf("/"));
- StringBuilder sb = new StringBuilder();
- sb.append("Feature named '").append(name).append("' has multiple versions installed (");
- for (int i = 0; i < toRemove.size(); i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(toRemove.get(i));
- }
- sb.append("). Please specify the version to uninstall.");
- throw new IllegalArgumentException(sb.toString());
- }
- featuresToRemove.addAll(toRemove);
- }
- featuresToRemove = new ArrayList<String>(new LinkedHashSet<String>(featuresToRemove));
- StringBuilder sb = new StringBuilder();
- sb.append("Removing features: ");
- for (int i = 0; i < featuresToRemove.size(); i++) {
- if (i > 0) {
- sb.append(", ");
- }
- sb.append(featuresToRemove.get(i));
- }
- print(sb.toString(), options.contains(Option.Verbose));
- required.removeAll(featuresToRemove);
- doInstallFeaturesInThread(required, installed, managed, options);
- }
-
- protected String normalize(String feature) {
- if (!feature.contains("/")) {
- feature += "/0.0.0";
- }
- int idx = feature.indexOf("/");
- String name = feature.substring(0, idx);
- String version = feature.substring(idx + 1);
- return name + "/" + VersionTable.getVersion(version).toString();
- }
-
- /**
- * Actual deployment needs to be done in a separate thread.
- * The reason is that if the console is refreshed, the current thread which is running
- * the command may be interrupted while waiting for the refresh to be done, leading
- * to bundles not being started after the refresh.
- */
- public void doInstallFeaturesInThread(final Set<String> features,
- final Set<String> installed,
- final Set<Long> managed,
- final EnumSet<Option> options) throws Exception {
- ExecutorService executor = Executors.newCachedThreadPool();
- try {
- executor.submit(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- doInstallFeatures(features, installed, managed, options);
- return null;
- }
- }).get();
- } catch (ExecutionException e) {
- Throwable t = e.getCause();
- if (t instanceof RuntimeException) {
- throw ((RuntimeException) t);
- } else if (t instanceof Error) {
- throw ((Error) t);
- } else if (t instanceof Exception) {
- throw (Exception) t;
- } else {
- throw e;
- }
- } finally {
- executor.shutdown();
- }
- }
-
- public void doInstallFeatures(Set<String> features, // all request features
- Set<String> installed, // installed features
- Set<Long> managed, // currently managed bundles
- EnumSet<Option> options // installation options
- ) throws Exception {
-
- boolean noRefreshUnmanaged = options.contains(Option.NoAutoRefreshUnmanagedBundles);
- boolean noRefreshManaged = options.contains(Option.NoAutoRefreshManagedBundles);
- boolean noRefresh = options.contains(Option.NoAutoRefreshBundles);
- boolean noStart = options.contains(Option.NoAutoStartBundles);
- boolean verbose = options.contains(Option.Verbose);
- boolean simulate = options.contains(Option.Simulate);
-
- // Get a list of resolved and unmanaged bundles to use as capabilities during resolution
- List<Resource> systemBundles = new ArrayList<Resource>();
- Bundle[] bundles = systemBundleContext.getBundles();
- for (Bundle bundle : bundles) {
- if (bundle.getState() >= Bundle.RESOLVED && !managed.contains(bundle.getBundleId())) {
- Resource res = bundle.adapt(BundleRevision.class);
- systemBundles.add(res);
- }
- }
- // Resolve
- // TODO: requirements
- // TODO: bundles
- // TODO: regions: on isolated regions, we may need different resolution for each region
- Set<String> overrides = Overrides.loadOverrides(this.overrides);
- Repository[] repositories = listRepositories();
- DeploymentBuilder builder = createDeploymentBuilder(repositories);
- builder.setFeatureRange(featureResolutionRange);
- builder.download(features,
- Collections.<String>emptySet(),
- Collections.<String>emptySet(),
- overrides,
- Collections.<String>emptySet());
- Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles);
- Collection<Resource> allResources = resolution.keySet();
- Map<String, StreamProvider> providers = builder.getProviders();
-
- // Install conditionals
- List<String> installedFeatureIds = getFeatureIds(allResources);
- List<String> newFeatures = new ArrayList<String>(installedFeatureIds);
- newFeatures.removeAll(installed);
- List<String> delFeatures = new ArrayList<String>(installed);
- delFeatures.removeAll(installedFeatureIds);
-
- //
- // Compute list of installable resources (those with uris)
- //
- List<Resource> resources = getBundles(allResources);
-
- // Compute information for each bundle
- Map<String, BundleInfo> bundleInfos = new HashMap<String, BundleInfo>();
- for (Feature feature : getFeatures(repositories, getFeatureIds(allResources))) {
- for (BundleInfo bi : feature.getBundles()) {
- BundleInfo oldBi = bundleInfos.get(bi.getLocation());
- if (oldBi != null) {
- bi = mergeBundleInfo(bi, oldBi);
- }
- bundleInfos.put(bi.getLocation(), bi);
- }
- }
-
- // TODO: handle bundleInfo.isStart()
-
- // Get all resources that will be used to satisfy the old features set
- Set<Resource> resourceLinkedToOldFeatures = new HashSet<Resource>();
- if (noStart) {
- for (Resource resource : resolution.keySet()) {
- String name = FeatureNamespace.getName(resource);
- if (name != null) {
- Version version = FeatureNamespace.getVersion(resource);
- String id = version != null ? name + "/" + version : name;
- if (installed.contains(id)) {
- addTransitive(resource, resourceLinkedToOldFeatures, resolution);
- }
- }
- }
- }
-
- //
- // Compute deployment
- //
- Map<String, Long> bundleChecksums = new HashMap<String, Long>();
- synchronized (lock) {
- bundleChecksums.putAll(state.bundleChecksums);
- }
- Deployment deployment = computeDeployment(managed, bundles, providers, resources, bundleChecksums);
-
- if (deployment.toDelete.isEmpty() &&
- deployment.toUpdate.isEmpty() &&
- deployment.toInstall.isEmpty()) {
- print("No deployment change.", verbose);
- return;
- }
- //
- // Log deployment
- //
- logDeployment(deployment, verbose);
-
- //
- // Compute the set of bundles to refresh
- //
- Set<Bundle> toRefresh = new HashSet<Bundle>();
- toRefresh.addAll(deployment.toDelete);
- toRefresh.addAll(deployment.toUpdate.keySet());
-
- if (!noRefreshManaged) {
- int size;
- do {
- size = toRefresh.size();
- for (Bundle bundle : bundles) {
- // Continue if we already know about this bundle
- if (toRefresh.contains(bundle)) {
- continue;
- }
- // Ignore non resolved bundle
- BundleWiring wiring = bundle.adapt(BundleWiring.class);
- if (wiring == null) {
- continue;
- }
- // Get through the old resolution and flag this bundle
- // if it was wired to a bundle to be refreshed
- for (BundleWire wire : wiring.getRequiredWires(null)) {
- if (toRefresh.contains(wire.getProvider().getBundle())) {
- toRefresh.add(bundle);
- break;
- }
- }
- // Get through the new resolution and flag this bundle
- // if it's wired to any new bundle
- List<Wire> newWires = resolution.get(wiring.getRevision());
- if (newWires != null) {
- for (Wire wire : newWires) {
- Bundle b = null;
- if (wire.getProvider() instanceof BundleRevision) {
- b = ((BundleRevision) wire.getProvider()).getBundle();
- } else {
- b = deployment.resToBnd.get(wire.getProvider());
- }
- if (b == null || toRefresh.contains(b)) {
- toRefresh.add(bundle);
- break;
- }
- }
- }
- }
- } while (toRefresh.size() > size);
- }
- if (noRefreshUnmanaged) {
- Set<Bundle> newSet = new HashSet<Bundle>();
- for (Bundle bundle : toRefresh) {
- if (managed.contains(bundle.getBundleId())) {
- newSet.add(bundle);
- }
- }
- toRefresh = newSet;
- }
-
-
- if (simulate) {
- if (!toRefresh.isEmpty()) {
- print(" Bundles to refresh:", verbose);
- for (Bundle bundle : toRefresh) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- }
- }
- return;
- }
-
- Set<Bundle> toStart = new HashSet<Bundle>();
-
- //
- // Execute deployment
- //
-
- // TODO: handle update on the features service itself
- if (deployment.toUpdate.containsKey(bundle) ||
- deployment.toDelete.contains(bundle)) {
-
- LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
- deployment.toUpdate.remove(bundle);
- deployment.toDelete.remove(bundle);
-
- }
-
- //
- // Perform bundle operations
- //
-
- // Stop bundles by chunks
- Set<Bundle> toStop = new HashSet<Bundle>();
- toStop.addAll(deployment.toUpdate.keySet());
- toStop.addAll(deployment.toDelete);
- removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
- if (!toStop.isEmpty()) {
- print("Stopping bundles:", verbose);
- while (!toStop.isEmpty()) {
- List<Bundle> bs = getBundlesToStop(toStop);
- for (Bundle bundle : bs) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- bundle.stop(Bundle.STOP_TRANSIENT);
- toStop.remove(bundle);
- }
- }
- }
- if (!deployment.toDelete.isEmpty()) {
- print("Uninstalling bundles:", verbose);
- for (Bundle bundle : deployment.toDelete) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- bundle.uninstall();
- managed.remove(bundle.getBundleId());
- }
- }
- if (!deployment.toUpdate.isEmpty()) {
- print("Updating bundles:", verbose);
- for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
- Bundle bundle = entry.getKey();
- Resource resource = entry.getValue();
- String uri = UriNamespace.getUri(resource);
- print(" " + uri, verbose);
- InputStream is = getBundleInputStream(resource, providers);
- bundle.update(is);
- toStart.add(bundle);
- BundleInfo bi = bundleInfos.get(uri);
- if (bi != null && bi.getStartLevel() > 0) {
- bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
- }
- // TODO: handle region
- }
- }
- if (!deployment.toInstall.isEmpty()) {
- print("Installing bundles:", verbose);
- for (Resource resource : deployment.toInstall) {
- String uri = UriNamespace.getUri(resource);
- print(" " + uri, verbose);
- InputStream is = getBundleInputStream(resource, providers);
- Bundle bundle = systemBundleContext.installBundle(uri, is);
- managed.add(bundle.getBundleId());
- if (!noStart || resourceLinkedToOldFeatures.contains(resource)) {
- toStart.add(bundle);
- }
- deployment.resToBnd.put(resource, bundle);
- // save a checksum of installed snapshot bundle
- if (UPDATE_SNAPSHOTS_CRC.equals(updateSnaphots)
- && isUpdateable(resource) && !deployment.newCheckums.containsKey(bundle.getLocation())) {
- deployment.newCheckums.put(bundle.getLocation(), ChecksumUtils.checksum(getBundleInputStream(resource, providers)));
- }
- BundleInfo bi = bundleInfos.get(uri);
- if (bi != null && bi.getStartLevel() > 0) {
- bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
- }
- // TODO: handle region
- }
- }
-
- //
- // Update and save state
- //
- synchronized (lock) {
- state.bundleChecksums.putAll(deployment.newCheckums);
- state.features.clear();
- state.features.addAll(features);
- state.installedFeatures.clear();
- state.installedFeatures.addAll(installedFeatureIds);
- state.managedBundles.clear();
- state.managedBundles.addAll(managed);
- saveState();
- }
-
- //
- // Install configurations
- //
- if (configInstaller != null && !newFeatures.isEmpty()) {
- for (Repository repository : repositories) {
- for (Feature feature : repository.getFeatures()) {
- if (newFeatures.contains(feature.getId())) {
- configInstaller.installFeatureConfigs(feature);
- }
- }
- }
- }
-
- // TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
- new CopyOnWriteArrayIdentityList().iterator();
- RequirementSort.sort(Collections.<Resource>emptyList());
-
- if (!noRefresh) {
- toStop = new HashSet<Bundle>();
- toStop.addAll(toRefresh);
- removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
- if (!toStop.isEmpty()) {
- print("Stopping bundles:", verbose);
- while (!toStop.isEmpty()) {
- List<Bundle> bs = getBundlesToStop(toStop);
- for (Bundle bundle : bs) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- bundle.stop(Bundle.STOP_TRANSIENT);
- toStop.remove(bundle);
- toStart.add(bundle);
- }
- }
- }
-
- if (!toRefresh.isEmpty()) {
- print("Refreshing bundles:", verbose);
- for (Bundle bundle : toRefresh) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- }
- if (!toRefresh.isEmpty()) {
- refreshPackages(toRefresh);
- }
- }
- }
-
- // Compute bundles to start
- removeFragmentsAndBundlesInState(toStart, Bundle.UNINSTALLED | Bundle.ACTIVE | Bundle.STARTING);
- if (!toStart.isEmpty()) {
- // Compute correct start order
- List<Exception> exceptions = new ArrayList<Exception>();
- print("Starting bundles:", verbose);
- while (!toStart.isEmpty()) {
- List<Bundle> bs = getBundlesToStart(toStart);
- for (Bundle bundle : bs) {
- LOGGER.info(" " + bundle.getSymbolicName() + " / " + bundle.getVersion());
- try {
- bundle.start();
- } catch (BundleException e) {
- exceptions.add(e);
- }
- toStart.remove(bundle);
- }
- }
- if (!exceptions.isEmpty()) {
- throw new MultiException("Error restarting bundles", exceptions);
- }
- }
-
- // Call listeners
- for (Feature feature : getFeatures(repositories, delFeatures)) {
- callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureUninstalled, false));
- }
- for (Feature feature : getFeatures(repositories, newFeatures)) {
- callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, false));
- }
-
- print("Done.", verbose);
- }
-
- private void addTransitive(Resource resource, Set<Resource> resources, Map<Resource, List<Wire>> resolution) {
- if (resources.add(resource)) {
- for (Wire wire : resolution.get(resource)) {
- addTransitive(wire.getProvider(), resources, resolution);
- }
- }
- }
-
- protected BundleInfo mergeBundleInfo(BundleInfo bi, BundleInfo oldBi) {
- // TODO: we need a proper merge strategy when a bundle
- // TODO: comes from different features
- return bi;
- }
-
- private void print(String message, boolean verbose) {
- LOGGER.info(message);
- if (verbose) {
- System.out.println(message);
- }
- }
-
- private void removeFragmentsAndBundlesInState(Collection<Bundle> bundles, int state) {
- for (Bundle bundle : new ArrayList<Bundle>(bundles)) {
- if ((bundle.getState() & state) != 0
- || bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) {
- bundles.remove(bundle);
- }
- }
- }
-
- protected void logDeployment(Deployment deployment, boolean verbose) {
- print("Changes to perform:", verbose);
- if (!deployment.toDelete.isEmpty()) {
- print(" Bundles to uninstall:", verbose);
- for (Bundle bundle : deployment.toDelete) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- }
- }
- if (!deployment.toUpdate.isEmpty()) {
- print(" Bundles to update:", verbose);
- for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
- print(" " + entry.getKey().getSymbolicName() + " / " + entry.getKey().getVersion() + " with " + UriNamespace.getUri(entry.getValue()), verbose);
- }
- }
- if (!deployment.toInstall.isEmpty()) {
- print(" Bundles to install:", verbose);
- for (Resource resource : deployment.toInstall) {
- print(" " + UriNamespace.getUri(resource), verbose);
- }
- }
- }
-
- protected Deployment computeDeployment(
- Set<Long> managed,
- Bundle[] bundles,
- Map<String, StreamProvider> providers,
- List<Resource> resources,
- Map<String, Long> bundleChecksums) throws IOException {
- Deployment deployment = new Deployment();
-
- // TODO: regions
- List<Resource> toDeploy = new ArrayList<Resource>(resources);
-
- // First pass: go through all installed bundles and mark them
- // as either to ignore or delete
- for (Bundle bundle : bundles) {
- if (bundle.getSymbolicName() != null && bundle.getBundleId() != 0) {
- Resource resource = null;
- for (Resource res : toDeploy) {
- if (bundle.getSymbolicName().equals(getSymbolicName(res))) {
- if (bundle.getVersion().equals(getVersion(res))) {
- resource = res;
- break;
- }
- }
- }
- // We found a matching bundle
- if (resource != null) {
- // In case of snapshots, check if the snapshot is out of date
- // and flag it as to update
- if (managed.contains(bundle.getBundleId()) && isUpdateable(resource)) {
- // Always update snapshots
- if (UPDATE_SNAPSHOTS_ALWAYS.equalsIgnoreCase(updateSnaphots)) {
- LOGGER.debug("Update snapshot for " + bundle.getLocation());
- deployment.toUpdate.put(bundle, resource);
- }
- else if (UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
- // if the checksum are different
- InputStream is = null;
- try {
- is = getBundleInputStream(resource, providers);
- long newCrc = ChecksumUtils.checksum(is);
- long oldCrc = bundleChecksums.containsKey(bundle.getLocation()) ? bundleChecksums.get(bundle.getLocation()) : 0l;
- if (newCrc != oldCrc) {
- LOGGER.debug("New snapshot available for " + bundle.getLocation());
- deployment.toUpdate.put(bundle, resource);
- deployment.newCheckums.put(bundle.getLocation(), newCrc);
- }
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
- }
- // We're done for this resource
- toDeploy.remove(resource);
- deployment.resToBnd.put(resource, bundle);
- // There's no matching resource
- // If the bundle is managed, we need to delete it
- } else if (managed.contains(bundle.getBundleId())) {
- deployment.toDelete.add(bundle);
- }
- }
- }
-
- // Second pass on remaining resources
- for (Resource resource : toDeploy) {
- TreeMap<Version, Bundle> matching = new TreeMap<Version, Bundle>();
- VersionRange range = new VersionRange(Macro.transform(bundleUpdateRange, getVersion(resource).toString()));
- for (Bundle bundle : deployment.toDelete) {
- if (bundle.getSymbolicName().equals(getSymbolicName(resource)) && range.contains(bundle.getVersion())) {
- matching.put(bundle.getVersion(), bundle);
- }
- }
- if (!matching.isEmpty()) {
- Bundle bundle = matching.lastEntry().getValue();
- deployment.toUpdate.put(bundle, resource);
- deployment.toDelete.remove(bundle);
- deployment.resToBnd.put(resource, bundle);
- } else {
- deployment.toInstall.add(resource);
- }
- }
- return deployment;
- }
-
- protected List<Resource> getBundles(Collection<Resource> allResources) {
- Map<String, Resource> deploy = new TreeMap<String, Resource>();
- for (Resource res : allResources) {
- String uri = UriNamespace.getUri(res);
- if (uri != null) {
- deploy.put(uri, res);
- }
- }
- return new ArrayList<Resource>(deploy.values());
- }
-
- protected List<Feature> getFeatures(Repository[] repositories, List<String> featureIds) throws Exception {
- List<Feature> installedFeatures = new ArrayList<Feature>();
- for (Repository repository : repositories) {
- for (Feature feature : repository.getFeatures()) {
- String id = feature.getName() + "/" + VersionTable.getVersion(feature.getVersion());
- if (featureIds.contains(id)) {
- installedFeatures.add(feature);
- }
- }
- }
- return installedFeatures;
- }
-
- protected List<String> getFeatureIds(Collection<Resource> allResources) {
- List<String> installedFeatureIds = new ArrayList<String>();
- for (Resource resource : allResources) {
- String name = FeatureNamespace.getName(resource);
- if (name != null) {
- Version version = FeatureNamespace.getVersion(resource);
- String id = version != null ? name + "/" + version : name;
- installedFeatureIds.add(id);
- }
- }
- return installedFeatureIds;
- }
-
- protected DeploymentBuilder createDeploymentBuilder(Repository[] repositories) {
- return new DeploymentBuilder(new SimpleDownloader(), Arrays.asList(repositories));
- }
-
-
- protected boolean isUpdateable(Resource resource) {
- return (getVersion(resource).getQualifier().endsWith(SNAPSHOT) ||
- UriNamespace.getUri(resource).contains(SNAPSHOT) ||
- !UriNamespace.getUri(resource).contains(MAVEN));
- }
-
- protected List<Bundle> getBundlesToStart(Collection<Bundle> bundles) {
- // TODO: make this pluggable ?
- // TODO: honor respectStartLvlDuringFeatureStartup
-
- // We hit FELIX-2949 if we don't use the correct order as Felix resolver isn't greedy.
- // In order to minimize that, we make sure we resolve the bundles in the order they
- // are given back by the resolution, meaning that all root bundles (i.e. those that were
- // not flagged as dependencies in features) are started before the others. This should
- // make sure those important bundles are started first and minimize the problem.
-
- // Restart the features service last, regardless of any other consideration
- // so that we don't end up with the service trying to do stuff before we're done
- boolean restart = bundles.remove(bundle);
-
- List<BundleRevision> revs = new ArrayList<BundleRevision>();
- for (Bundle bundle : bundles) {
- revs.add(bundle.adapt(BundleRevision.class));
- }
- List<Bundle> sorted = new ArrayList<Bundle>();
- for (BundleRevision rev : RequirementSort.sort(revs)) {
- sorted.add(rev.getBundle());
- }
- if (restart) {
- sorted.add(bundle);
- }
- return sorted;
- }
-
- protected List<Bundle> getBundlesToStop(Collection<Bundle> bundles) {
- // TODO: make this pluggable ?
- // TODO: honor respectStartLvlDuringFeatureUninstall
-
- List<Bundle> bundlesToDestroy = new ArrayList<Bundle>();
- for (Bundle bundle : bundles) {
- ServiceReference[] references = bundle.getRegisteredServices();
- int usage = 0;
- if (references != null) {
- for (ServiceReference reference : references) {
- usage += getServiceUsage(reference, bundles);
- }
- }
- LOGGER.debug("Usage for bundle {} is {}", bundle, usage);
- if (usage == 0) {
- bundlesToDestroy.add(bundle);
- }
- }
- if (!bundlesToDestroy.isEmpty()) {
- Collections.sort(bundlesToDestroy, new Comparator<Bundle>() {
- public int compare(Bundle b1, Bundle b2) {
- return (int) (b2.getLastModified() - b1.getLastModified());
- }
- });
- LOGGER.debug("Selected bundles {} for destroy (no services in use)", bundlesToDestroy);
- } else {
- ServiceReference ref = null;
- for (Bundle bundle : bundles) {
- ServiceReference[] references = bundle.getRegisteredServices();
- for (ServiceReference reference : references) {
- if (getServiceUsage(reference, bundles) == 0) {
- continue;
- }
- if (ref == null || reference.compareTo(ref) < 0) {
- LOGGER.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
- ref = reference;
- }
- }
- }
- if (ref != null) {
- bundlesToDestroy.add(ref.getBundle());
- }
- LOGGER.debug("Selected bundle {} for destroy (lowest ranking service)", bundlesToDestroy);
- }
- return bundlesToDestroy;
- }
-
- private static int getServiceUsage(ServiceReference ref, Collection<Bundle> bundles) {
- Bundle[] usingBundles = ref.getUsingBundles();
- int nb = 0;
- if (usingBundles != null) {
- for (Bundle bundle : usingBundles) {
- if (bundles.contains(bundle)) {
- nb++;
- }
- }
- }
- return nb;
- }
-
- protected InputStream getBundleInputStream(Resource resource, Map<String, StreamProvider> providers) throws IOException {
- String uri = UriNamespace.getUri(resource);
- if (uri == null) {
- throw new IllegalStateException("Resource has no uri");
- }
- StreamProvider provider = providers.get(uri);
- if (provider == null) {
- throw new IllegalStateException("Resource " + uri + " has no StreamProvider");
- }
- return provider.open();
- }
-
- protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
- final CountDownLatch latch = new CountDownLatch(1);
- FrameworkWiring fw = systemBundleContext.getBundle().adapt(FrameworkWiring.class);
- fw.refreshBundles(bundles, new FrameworkListener() {
- @Override
- public void frameworkEvent(FrameworkEvent event) {
- if (event.getType() == FrameworkEvent.ERROR) {
- LOGGER.error("Framework error", event.getThrowable());
- }
- latch.countDown();
- }
- });
- latch.await();
- }
-
-
- static class Deployment {
- Map<String, Long> newCheckums = new HashMap<String, Long>();
- Map<Resource, Bundle> resToBnd = new HashMap<Resource, Bundle>();
- List<Resource> toInstall = new ArrayList<Resource>();
- List<Bundle> toDelete = new ArrayList<Bundle>();
- Map<Bundle, Resource> toUpdate = new HashMap<Bundle, Resource>();
- }
-
-}
[02/33] [KARAF-2852] Merge jdbc/core and jdbc/command
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
deleted file mode 100644
index 090daee..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-generic.xml
+++ /dev/null
@@ -1,141 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName" value="${driver}"/>
- <property name="url" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- <property name="maxIdle" value="1"/>
- </bean>
-
- <bean id="connectionFactory" class="org.apache.commons.dbcp.DataSourceConnectionFactory">
- <argument ref="dataSource" />
- </bean>
-
- <bean id="connectionPool" class="org.apache.commons.pool.impl.GenericObjectPool" >
- <!-- No default factory -->
- <argument><null/></argument> <!-- factory -->
- <!--
- controls the maximum number of objects that can be allocated by the pool (checked out to clients, or
- idle awaiting checkout) at a given time. When non-positive, there is no limit to the number of objects that can
- be managed by the pool at one time. When maxActive is reached, the pool is said to be exhausted.
- The default setting for this parameter is 8.
- -->
- <argument value="8" /> <!-- maxActive -->
- <!--
- specifies the behavior of the borrowObject() method when the pool is exhausted:
-
- When whenExhaustedAction is WHEN_EXHAUSTED_FAIL, borrowObject() will throw a NoSuchElementException
- When whenExhaustedAction is WHEN_EXHAUSTED_GROW, borrowObject() will create a new object and return it
- (essentially making maxActive meaningless.)
- When whenExhaustedAction is WHEN_EXHAUSTED_BLOCK, borrowObject() will block (invoke Object.wait()) until
- a new or idle object is available. If a positive maxWait value is supplied, then borrowObject() will block for at most that many milliseconds, after which a NoSuchElementException will be thrown. If maxWait is non-positive, the borrowObject() method will block indefinitely.
-
- The default whenExhaustedAction setting is WHEN_EXHAUSTED_BLOCK and the default maxWait setting is -1.
- By default, therefore, borrowObject will block indefinitely until an idle instance becomes available.
- -->
- <argument value="WHEN_EXHAUSTED_BLOCK" /> <!-- whenExhaustedAction -->
- <!--
- the maximum amount of time to wait for an idle object when the pool is exhausted and whenExhaustedAction
- is WHEN_EXHAUSTED_BLOCK (otherwise ignored)
- -->
- <argument value="-1" /> <!-- maxWait -->
- <!--
- controls the maximum number of objects that can sit idle in the pool at any time.
- When negative, there is no limit to the number of objects that may be idle at one time.
- The default setting for this parameter is 8.
- -->
- <argument value="8" /> <!-- maxIdle -->
- <!--
- sets the minimum number of objects allowed in the pool before the evictor thread (if active) spawns
- new objects.
- -->
- <argument value="0" /> <!-- minIdle -->
- <!--
- when true, objects will be validated before being returned by the borrowObject() method.
- -->
- <argument value="false" /> <!-- testOnBorrow -->
- <!--
- when true, objects will be validated before being returned to the pool within the returnObject(T).
- -->
- <argument value="false" /> <!-- testOnReturn -->
- <!--
- sets the number of milliseconds to sleep between runs of the idle object evictor thread.
- -->
- <argument value="-1" /> <!-- timeBetweenEvictionRunsMillis -->
- <!--
- the number of idle objects to examine per run within the idle object eviction thread (if any)
- -->
- <argument value="3" /> <!-- numTestsPerEvictionRun -->
- <!--
- sets the minimum amount of time an object may sit idle in the pool before it is eligible for eviction by
- the idle object evictor (if any). When non-positive, no objects will be evicted from the pool due to idle
- time alone.
- -->
- <argument value="1800000" /> <!-- minEvictableIdleTimeMillis -->
- <!--
- when true, objects will be validated by the idle object evictor (if any). If an object fails to validate,
- it will be dropped from the pool.
- -->
- <argument value="false" /> <!-- testWhileIdle -->
- <!--
- softMinEvictableIdleTimeMillis specifies the minimum amount of time an object may sit idle in the pool before
- it is eligible for eviction by the idle object evictor (if any), with the extra condition that at least "minIdle"
- object instances remain in the pool. When non-positive, no objects will be evicted from the pool due to idle time alone.
- This setting has no effect unless timeBetweenEvictionRunsMillis > 0. and it is superceded by
- minEvictableIdleTimeMillis (that is, if minEvictableIdleTimeMillis is positive, then
- softMinEvictableIdleTimeMillis is ignored). The default setting for this parameter is -1 (disabled).
- -->
- <argument value="-1" /> <!-- softMinEvictableIdleTimeMillis -->
- <!--
- lifo determines whether or not the pool returns idle objects in last-in-first-out order. The default setting for this parameter is true.
- -->
- <argument value="true" /> <!-- lifo -->
- </bean>
-
- <bean id="pooledConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory" >
- <argument ref="connectionFactory" />
- <argument ref="connectionPool" />
- <argument><null/></argument>
- <!--
- a query to use to validate Connections. Should return at least one row. Using null turns off validation.
- -->
- <argument><null/></argument> <!-- validationQuery -->
- <!--
- the default "read only" setting for borrowed connections
- -->
- <argument value="false" /> <!-- defaultReadOnly -->
- <!--
- the default "auto commit" setting for returned connections
- -->
- <argument value="true" /> <!-- defaultAutoCommit -->
- </bean>
-
- <bean id="pooledDataSource" class="org.apache.commons.dbcp.PoolingDataSource" depends-on="pooledConnectionFactory">
- <argument ref="connectionPool" />
- </bean>
-
- <service ref="pooledDataSource" interface="javax.sql.DataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
deleted file mode 100644
index 19805f4..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-h2.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="org.h2.jdbcx.JdbcDataSource">
- <property name="URL" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
deleted file mode 100644
index 3ea9ba8..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-hsql.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="org.hsqldb.jdbc.JDBCDataSource">
- <property name="url" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
deleted file mode 100644
index 35e6ed9..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mssql.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="net.sourceforge.jtds.jdbcx.JtdsDataSource">
- <property name="serverName" value="${url}"/>
- <property name="databaseName" value="${name}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
deleted file mode 100644
index 012ecaf..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-mysql.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
- <property name="url" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
deleted file mode 100644
index 8168b16..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-oracle.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
- <property name="URL" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
----------------------------------------------------------------------
diff --git a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml b/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
deleted file mode 100644
index 1845c48..0000000
--- a/jdbc/core/src/main/resources/org/apache/karaf/jdbc/internal/datasource-postgres.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="dataSource" class="org.postgresql.ds.PGPoolingDataSource" destroy-method="close">
- <property name="serverName" value="${url}"/>
- <property name="user" value="${user}"/>
- <property name="password" value="${password}"/>
- <property name="dataSourceName" value="${name}"/>
- <property name="initialConnections" value="2"/>
- <property name="maxConnections" value="4" />
- </bean>
-
- <service interface="javax.sql.DataSource" ref="dataSource">
- <service-properties>
- <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
- </service-properties>
- </service>
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/pom.xml
----------------------------------------------------------------------
diff --git a/jdbc/pom.xml b/jdbc/pom.xml
index 631dc54..a6dce66 100644
--- a/jdbc/pom.xml
+++ b/jdbc/pom.xml
@@ -29,13 +29,68 @@
</parent>
<groupId>org.apache.karaf.jdbc</groupId>
- <artifactId>jdbc</artifactId>
- <packaging>pom</packaging>
- <name>Apache Karaf :: JDBC</name>
-
- <modules>
- <module>core</module>
- <module>command</module>
- </modules>
+ <artifactId>org.apache.karaf.jdbc.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: JDBC :: Core</name>
+ <description>This bundle provides core implementation of the JDBC service.</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.karaf.jdbc
+ </Export-Package>
+ <Private-Package>
+ org.apache.karaf.jdbc.command,
+ org.apache.karaf.jdbc.command.completers,
+ org.apache.karaf.jdbc.internal,
+ org.apache.karaf.util
+ </Private-Package>
+ <Karaf-Commands>*</Karaf-Commands>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java b/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
new file mode 100644
index 0000000..26165c8
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcMBean.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+import java.util.Map;
+
+/**
+ * JDBC MBean
+ */
+public interface JdbcMBean {
+
+ /**
+ * Get the list of JDBC datasources.
+ *
+ * @return a tabular data containing the list of JDBC datasources.
+ * @throws MBeanException
+ */
+ TabularData getDatasources() throws MBeanException;
+
+ /**
+ * Create a JDBC datasource.
+ *
+ * @param name the JDBC datasource name.
+ * @param type the JDBC datasource type (generic, MySQL, Oracle, Postgres, H2, HSQL, Derby, MSSQL).
+ * @param driver the JDBC datasource driver class name (can be null).
+ * @param version the target JDBC driver version (can be null).
+ * @param url the JDBC URL.
+ * @param user the database username.
+ * @param password the database password.
+ * @param installBundles true to install the bundles providing the JDBC driver, false to not install.
+ * @throws MBeanException
+ */
+ void create(String name, String type, String driver, String version, String url, String user, String password, boolean installBundles) throws MBeanException;
+
+ /**
+ * Delete a JDBC datasource.
+ *
+ * @param name the JDBC datasource name (the one used at creation time).
+ * @throws MBeanException
+ */
+ void delete(String name) throws MBeanException;
+
+ /**
+ * Get details about a JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @return a map (property/value) containing JDBC datasource details.
+ * @throws MBeanException
+ */
+ Map<String, String> info(String datasource) throws MBeanException;
+
+ /**
+ * Get the tables available on a JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @return a tabular data containg datasource tables.
+ * @throws MBeanException
+ */
+ TabularData tables(String datasource) throws MBeanException;
+
+ /**
+ * Execute a SQL command on a JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @param command the SQL command to execute.
+ * @throws MBeanException
+ */
+ void execute(String datasource, String command) throws MBeanException;
+
+ /**
+ * Execute a SQL query on a JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @param query the SQL query to execute.
+ * @return a tabular data with the result of execute (columns/values).
+ * @throws MBeanException
+ */
+ TabularData query(String datasource, String query) throws MBeanException;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcService.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcService.java b/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcService.java
new file mode 100644
index 0000000..d883a07
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/JdbcService.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JDBC Service.
+ */
+public interface JdbcService {
+
+ /**
+ * Create a JDBC datasource (using a default template).
+ *
+ * @param name the JDBC datasource name.
+ * @param type the backend database type (generic, Oracle, MySQL, ...)
+ * @param driverClassName the JDBC driver classname.
+ * @param version the JDBC driver version to use.
+ * @param url the JDBC URL.
+ * @param user the database user name.
+ * @param password the database password.
+ * @param tryToInstallBundles true to try to automatically install the required bundles (JDBC driver, etc) when possible, false else.
+ */
+ void create(String name, String type, String driverClassName, String version, String url, String user, String password, boolean tryToInstallBundles) throws Exception;
+
+ /**
+ * Delete a JDBC datasource identified by a name.
+ *
+ * @param name the JDBC datasource name.
+ */
+ void delete(String name) throws Exception;
+
+ /**
+ * List the JDBC datasources available.
+ *
+ * @return a list of datasources name.
+ */
+ List<String> datasources() throws Exception;
+
+ /**
+ * List the JDBC datasources configuration file names present in the deploy folder.
+ *
+ * @return a list of the JDBC datasources configuration file names.
+ */
+ List<String> datasourceFileNames() throws Exception;
+
+ /**
+ * Execute a SQL query on a given JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @param query the SQL query to execute.
+ * @return the SQL query result (as a String).
+ */
+ Map<String, List<String>> query(String datasource, String query) throws Exception;
+
+ /**
+ * Execute a SQL command on a given JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @param command the SQL command to execute.
+ */
+ void execute(String datasource, String command) throws Exception;
+
+ /**
+ * List the tables available on a given JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @return the list of table names.
+ */
+ Map<String, List<String>> tables(String datasource) throws Exception;
+
+ /**
+ * Get detailed info about a JDBC datasource.
+ *
+ * @param datasource the JDBC datasource name.
+ * @return a map of info (name/value).
+ */
+ Map<String, String> info(String datasource) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
new file mode 100644
index 0000000..89ed49c
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/CreateCommand.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+@Command(scope = "jdbc", name = "create", description = "Create a JDBC datasource")
+@Service
+public class CreateCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "The JDBC datasource name", required = true, multiValued = false)
+ String name;
+
+ @Option(name = "-t", aliases = { "--type" }, description = "The JDBC datasource type (generic, MySQL, Oracle, Postgres, H2, HSQL, Derby, MSSQL)", required = false, multiValued = false)
+ @Completion(value = StringsCompleter.class, values = { "db2", "derby", "generic", "h2", "hsql", "mysql", "oracle", "postgres", "mssql" })
+ String type;
+
+ @Option(name = "-d", aliases = { "--driver" }, description = "The classname of the JDBC driver to use. NB: this option is used only the type generic", required = false, multiValued = false)
+ String driver;
+
+ @Option(name = "-v", aliases = { "--version" }, description = "The version of the driver to use", required = false, multiValued = false)
+ String version;
+
+ @Option(name = "-url", description = "The JDBC URL to use", required = false, multiValued = false)
+ String url;
+
+ @Option(name = "-u", aliases = { "--username" }, description = "The database username", required = false, multiValued = false)
+ String username;
+
+ @Option(name = "-p", aliases = { "--password" }, description = "The database password", required = false, multiValued = false)
+ String password;
+
+ @Option(name = "-i", aliases = { "--install-bundles" }, description = "Try to install the bundles providing the JDBC driver", required = false, multiValued = false)
+ boolean installBundles = false;
+
+ @Override
+ public Object execute() throws Exception {
+ this.getJdbcService().create(name, type, driver, version, url, username, password, installBundles);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
new file mode 100644
index 0000000..cb3edad
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/DataSourcesCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jdbc", name = "datasources", description = "List the JDBC datasources")
+@Service
+public class DataSourcesCommand extends JdbcCommandSupport {
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ table.column("Name");
+ table.column("Product");
+ table.column("Version");
+ table.column("URL");
+
+ List<String> datasources = this.getJdbcService().datasources();
+ for (String datasource : datasources) {
+ Map<String, String> info = this.getJdbcService().info(datasource);
+ table.addRow().addContent(datasource, info.get("db.product"), info.get("db.version"), info.get("url"));
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
new file mode 100644
index 0000000..6bf7236
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/DeleteCommand.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import org.apache.karaf.jdbc.command.completers.DataSourcesFileNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jdbc", name = "delete", description = "Delete a JDBC datasource")
+@Service
+public class DeleteCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "The JDBC datasource name (the one used at creation time)", required = true, multiValued = false)
+ @Completion(DataSourcesFileNameCompleter.class)
+ String name;
+
+ @Override
+ public Object execute() throws Exception {
+ this.getJdbcService().delete(name);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
new file mode 100644
index 0000000..480ab51
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/ExecuteCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jdbc", name = "execute", description = "Execute a SQL command on a given JDBC datasource")
+@Service
+public class ExecuteCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "datasource", description = "The JDBC datasource", required = true, multiValued = false)
+ @Completion(DataSourcesNameCompleter.class)
+ String datasource;
+
+ @Argument(index = 1, name = "command", description = "The SQL command to execute", required = true, multiValued = false)
+ String command;
+
+ @Override
+ public Object execute() throws Exception {
+ this.getJdbcService().execute(datasource, command);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
new file mode 100644
index 0000000..e53bbab
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/InfoCommand.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+import java.util.Map;
+
+@Command(scope = "jdbc", name = "info", description = "Display details about a JDBC datasource")
+@Service
+public class InfoCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "datasource", description = "The JDBC datasource name", required = true, multiValued = false)
+ @Completion(DataSourcesNameCompleter.class)
+ String datasource;
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ table.column("Property");
+ table.column("Value");
+
+ Map<String, String> info = this.getJdbcService().info(datasource);
+ for (String property : info.keySet()) {
+ table.addRow().addContent(property, info.get(property));
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
new file mode 100644
index 0000000..cf1eb58
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/JdbcCommandSupport.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import org.apache.karaf.jdbc.JdbcService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+
+public abstract class JdbcCommandSupport implements Action {
+
+ @Reference
+ private JdbcService jdbcService;
+
+ public JdbcService getJdbcService() {
+ return jdbcService;
+ }
+
+ public void setJdbcService(JdbcService jdbcService) {
+ this.jdbcService = jdbcService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
new file mode 100644
index 0000000..297288b
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/QueryCommand.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jdbc", name = "query", description = "Execute a SQL query on a JDBC datasource")
+@Service
+public class QueryCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "datasource", description = "The JDBC datasource to use", required = true, multiValued = false)
+ @Completion(DataSourcesNameCompleter.class)
+ String datasource;
+
+ @Argument(index = 1, name = "query", description = "The SQL query to execute", required = true, multiValued = false)
+ String query;
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ Map<String, List<String>> map = this.getJdbcService().query(datasource, query);
+ int rowCount = 0;
+ for (String column : map.keySet()) {
+ table.column(column);
+ rowCount = map.get(column).size();
+ }
+
+ for (int i = 0; i < rowCount; i++) {
+ Row row = table.addRow();
+ for (String column : map.keySet()) {
+ row.addContent(map.get(column).get(i));
+ }
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
new file mode 100644
index 0000000..04baa70
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/TablesCommand.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.jdbc.command.completers.DataSourcesNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jdbc", name = "tables", description = "List the tables on a given JDBC datasource")
+@Service
+public class TablesCommand extends JdbcCommandSupport {
+
+ @Argument(index = 0, name = "datasource", description = "The JDBC datasource to use", required = true, multiValued = false)
+ @Completion(DataSourcesNameCompleter.class)
+ String datasource;
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ Map<String, List<String>> map = this.getJdbcService().tables(datasource);
+ int rowCount = 0;
+ for (String column : map.keySet()) {
+ table.column(column);
+ rowCount = map.get(column).size();
+ }
+
+ for (int i = 0; i < rowCount; i++) {
+ Row row = table.addRow();
+ for (String column : map.keySet()) {
+ row.addContent(map.get(column).get(i));
+ }
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
new file mode 100644
index 0000000..8ba0fe9
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesFileNameCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command.completers;
+
+import org.apache.karaf.jdbc.JdbcService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer on the JDBC datasources file name.
+ */
+@Service
+public class DataSourcesFileNameCompleter implements Completer {
+
+ @Reference
+ private JdbcService jdbcService;
+
+ @Override
+ public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (String datasourceFileName : jdbcService.datasourceFileNames()) {
+ delegate.getStrings().add(datasourceFileName.replace("datasource-", "").replace(".xml", ""));
+ }
+ } catch (Exception e) {
+ // nothing to do
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ public JdbcService getJdbcService() {
+ return jdbcService;
+ }
+
+ public void setJdbcService(JdbcService jdbcService) {
+ this.jdbcService = jdbcService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java b/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
new file mode 100644
index 0000000..238910f
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/command/completers/DataSourcesNameCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.command.completers;
+
+import org.apache.karaf.jdbc.JdbcService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer on the JDBC datasources name (JNDI or OSGi service property).
+ */
+@Service
+public class DataSourcesNameCompleter implements Completer {
+
+ @Reference
+ private JdbcService jdbcService;
+
+ @Override
+ public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (String datasource : jdbcService.datasources()) {
+ delegate.getStrings().add(datasource);
+ }
+ } catch (Exception e) {
+ // nothing to do
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ public JdbcService getJdbcService() {
+ return jdbcService;
+ }
+
+ public void setJdbcService(JdbcService jdbcService) {
+ this.jdbcService = jdbcService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
new file mode 100644
index 0000000..11c7ca4
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcConnector.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.internal;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.sql.*;
+import java.util.Deque;
+import java.util.LinkedList;
+
+import javax.sql.DataSource;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+
+import org.apache.karaf.util.StreamUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class JdbcConnector implements Closeable {
+ private BundleContext bundleContext;
+ private String datasourceName;
+ private Connection connection;
+ private Deque<Closeable> resources;
+ private ServiceReference<?> reference;
+
+ public JdbcConnector(BundleContext bundleContext, String datasourceName) {
+ this.bundleContext = bundleContext;
+ this.datasourceName = datasourceName;
+ this.resources = new LinkedList<Closeable>();
+ }
+
+ public Connection connect() throws SQLException {
+ reference = lookupDataSource(datasourceName);
+ Object datasource = bundleContext.getService(reference);
+ if (datasource instanceof DataSource) {
+ connection = ((DataSource) datasource).getConnection();
+ }
+ if (datasource instanceof XADataSource) {
+ connection = ((XADataSource) datasource).getXAConnection().getConnection();
+ }
+ return connection;
+ }
+
+ public Statement createStatement() throws SQLException {
+ if (connection == null) {
+ connect();
+ }
+ if (connection instanceof Connection) {
+ return register(((Connection) connection).createStatement());
+ }
+ if (connection instanceof XAConnection) {
+ return register(((XAConnection) connection).getConnection().createStatement());
+ }
+ return null;
+ }
+
+ public Connection register(final Connection connection) {
+ resources.addFirst(new Closeable() {
+
+ @Override
+ public void close() throws IOException {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ // Ignore
+ }
+ }
+ });
+ return connection;
+ }
+
+ public Statement register(final Statement statement) {
+ resources.addFirst(new Closeable() {
+
+ @Override
+ public void close() throws IOException {
+ try {
+ statement.close();
+ } catch (SQLException e) {
+ // Ignore
+ }
+ }
+ });
+ return statement;
+ }
+
+ public ResultSet register(final ResultSet resultSet) {
+ resources.addFirst(new Closeable() {
+
+ @Override
+ public void close() throws IOException {
+ try {
+ resultSet.close();
+ } catch (SQLException e) {
+ // Ignore
+ }
+ }
+ });
+ return resultSet;
+ }
+
+
+ private ServiceReference<?> lookupDataSource(String name) {
+ ServiceReference<?>[] references;
+ try {
+ references = bundleContext.getServiceReferences((String) null,
+ "(&(|(" + Constants.OBJECTCLASS + "=" + DataSource.class.getName() + ")"
+ + "(" + Constants.OBJECTCLASS + "=" + XADataSource.class.getName() + "))"
+ + "(|(osgi.jndi.service.name=" + name + ")(datasource=" + name + ")(name=" + name + ")(service.id=" + name + ")))");
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Error finding datasource with name " + name, e);
+ }
+ if (references == null || references.length == 0) {
+ throw new IllegalArgumentException("No JDBC datasource found for " + name);
+ }
+ if (references.length > 1) {
+ throw new IllegalArgumentException("Multiple JDBC datasource found for " + name);
+ }
+ return references[0];
+ }
+
+ @Override
+ public void close() {
+ StreamUtils.close(resources.toArray(new Closeable[]{}));
+ if (reference != null) {
+ bundleContext.ungetService(reference);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
new file mode 100644
index 0000000..92bbba8
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcMBeanImpl.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.internal;
+
+import org.apache.karaf.jdbc.JdbcMBean;
+import org.apache.karaf.jdbc.JdbcService;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Default implementation of the JDBC MBean.
+ */
+public class JdbcMBeanImpl implements JdbcMBean {
+
+ private JdbcService jdbcService;
+
+ @Override
+ public TabularData getDatasources() throws MBeanException {
+ try {
+ CompositeType type = new CompositeType("DataSource", "JDBC DataSource",
+ new String[]{ "name", "product", "version", "url "},
+ new String[]{ "Name", "Database product", "Database version", "JDBC URL" },
+ new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING });
+ TabularType tableType = new TabularType("JDBC DataSources", "Table of the JDBC DataSources",
+ type, new String[]{ "name" });
+ TabularData table = new TabularDataSupport(tableType);
+
+ for (String datasource : jdbcService.datasources()) {
+ Map<String, String> info = jdbcService.info(datasource);
+ CompositeData data = new CompositeDataSupport(type,
+ new String[]{ "name", "product", "version", "url" },
+ new Object[]{ datasource, info.get("db.product"), info.get("db.version"), info.get("url") });
+ table.put(data);
+ }
+
+ return table;
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public void create(String name, String type, String driver, String version, String url, String user, String password, boolean installBundles) throws MBeanException {
+ try {
+ jdbcService.create(name, type, driver, version, url, user, password, installBundles);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public void delete(String name) throws MBeanException {
+ try {
+ jdbcService.delete(name);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public Map<String, String> info(String datasource) throws MBeanException {
+ try {
+ return jdbcService.info(datasource);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public TabularData tables(String datasource) throws MBeanException {
+ try {
+ Map<String, List<String>> result = jdbcService.tables(datasource);
+ OpenType[] stringTypes = new OpenType[result.keySet().size()];
+ for (int i = 0; i < stringTypes.length; i++) {
+ stringTypes[i] = SimpleType.STRING;
+ }
+ String[] columns = result.keySet().toArray(new String[result.keySet().size()]);
+
+ CompositeType type = new CompositeType("Columns", "Columns",
+ columns, columns, stringTypes);
+ TabularType rows = new TabularType("Result", "Result Rows", type, columns);
+ TabularData table = new TabularDataSupport(rows);
+
+ int rowCount = result.get(result.keySet().iterator().next()).size();
+
+ for (int i = 0; i < rowCount; i++) {
+ Object[] row = new Object[columns.length];
+ for (int j = 0; j < columns.length; j++) {
+ row[j] = result.get(columns[j]).get(i);
+ }
+ CompositeData data = new CompositeDataSupport(type, columns, row);
+ table.put(data);
+ }
+
+ return table;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public void execute(String datasource, String command) throws MBeanException {
+ try {
+ jdbcService.execute(datasource, command);
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ @Override
+ public TabularData query(String datasource, String query) throws MBeanException {
+ try {
+ Map<String, List<String>> result = jdbcService.query(datasource, query);
+ OpenType[] stringTypes = new OpenType[result.keySet().size()];
+ for (int i = 0; i < stringTypes.length; i++) {
+ stringTypes[i] = SimpleType.STRING;
+ }
+ String[] columns = result.keySet().toArray(new String[result.keySet().size()]);
+
+ CompositeType type = new CompositeType("Columns", "Columns",
+ columns, columns, stringTypes);
+ TabularType rows = new TabularType("Result", "Result Rows", type, columns);
+ TabularData table = new TabularDataSupport(rows);
+
+ int rowCount = result.get(result.keySet().iterator().next()).size();
+
+ for (int i = 0; i < rowCount; i++) {
+ Object[] row = new Object[columns.length];
+ for (int j = 0; j < columns.length; j++) {
+ row[j] = result.get(columns[j]).get(i);
+ }
+ CompositeData data = new CompositeDataSupport(type, columns, row);
+ table.put(data);
+ }
+
+ return table;
+ } catch (Exception e) {
+ throw new MBeanException(null, e.getMessage());
+ }
+ }
+
+ public JdbcService getJdbcService() {
+ return jdbcService;
+ }
+
+ public void setJdbcService(JdbcService jdbcService) {
+ this.jdbcService = jdbcService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
new file mode 100644
index 0000000..50cf8ff
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/karaf/jdbc/internal/JdbcServiceImpl.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jdbc.internal;
+
+import org.apache.karaf.jdbc.JdbcService;
+import org.apache.karaf.util.TemplateUtils;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+
+import java.io.*;
+import java.sql.*;
+import java.util.*;
+
+/**
+ * Default implementation of the JDBC Service.
+ */
+public class JdbcServiceImpl implements JdbcService {
+
+ public static enum TYPES {
+ DB2("wrap:mvn:com.ibm.db2.jdbc/db2jcc/", "9.7", "datasource-db2.xml"),
+ DERBY("mvn:org.apache.derby/derby/", "10.8.2.2", "datasource-derby.xml"),
+ GENERIC(null, null, "datasource-generic.xml"),
+ H2("mvn:com.h2database/h2/", "1.3.163", "datasource-h2.xml"),
+ HSQL("mvn:org.hsqldb/hsqldb/", "2.3.2", "datasource-hsql.xml"),
+ MYSQL("mvn:mysql/mysql-connector-java/", "5.1.18", "datasource-mysql.xml"),
+ MSSQL("wrap:mvn:net.sourceforge.jtds/jtds/", "1.2.4", "datasource-mssql.xml"),
+ ORACLE("wrap:mvn:ojdbc/ojdbc/", "11.2.0.2.0", "datasource-oracle.xml"),
+ POSTGRES("wrap:mvn:postgresql/postgresql/", "9.1-901.jdbc4", "datasource-postgres.xml");
+
+ private final String bundleUrl;
+ private final String defaultVersion;
+ private final String templateFile;
+
+ TYPES(String bundleUrl, String defaultVersion, String templateFile) {
+ this.bundleUrl = bundleUrl;
+ this.defaultVersion = defaultVersion;
+ this.templateFile = templateFile;
+ }
+
+ public void installBundle(BundleContext bundleContext, String version) throws Exception {
+ String location = this.bundleUrl + getWithDefault(version, this.defaultVersion);
+ bundleContext.installBundle(location, null).start();
+ }
+
+ private String getWithDefault(String st, String defaultSt) {
+ return (st == null)? defaultSt : st;
+ }
+
+ public void copyDataSourceFile(File outFile, HashMap<String, String> properties) {
+ InputStream is = this.getClass().getResourceAsStream(templateFile);
+ if (is == null) {
+ throw new IllegalArgumentException("Template resource " + templateFile + " doesn't exist");
+ }
+ TemplateUtils.createFromTemplate(outFile, is, properties);
+ }
+
+ }
+
+ private BundleContext bundleContext;
+
+ @Override
+ public void create(String name, String type, String driverClassName, String version, String url, String user, String password, boolean tryToInstallBundles) throws Exception {
+ if (type == null) {
+ throw new IllegalStateException("No database type supplied");
+ }
+ TYPES dbType = TYPES.valueOf(type.toUpperCase());
+
+ if (tryToInstallBundles) {
+ dbType.installBundle(bundleContext, version);
+ }
+
+ File karafBase = new File(System.getProperty("karaf.base"));
+ File deployFolder = new File(karafBase, "deploy");
+ File outFile = new File(deployFolder, "datasource-" + name + ".xml");
+
+ HashMap<String, String> properties = new HashMap<String, String>();
+ properties.put("name", name);
+ properties.put("driver", driverClassName);
+ properties.put("url", url);
+ properties.put("user", user);
+ properties.put("password", password);
+
+ dbType.copyDataSourceFile(outFile, properties);
+ }
+
+ @Override
+ public void delete(String name) throws Exception {
+ File karafBase = new File(System.getProperty("karaf.base"));
+ File deployFolder = new File(karafBase, "deploy");
+ File datasourceFile = new File(deployFolder, "datasource-" + name + ".xml");
+ if (!datasourceFile.exists()) {
+ throw new IllegalArgumentException("The JDBC datasource file "+ datasourceFile.getPath() + " doesn't exist");
+ }
+ datasourceFile.delete();
+ }
+
+ @Override
+ public List<String> datasources() throws Exception {
+ List<String> datasources = new ArrayList<String>();
+
+ ServiceReference<?>[] references = bundleContext.getServiceReferences((String) null, "(|(" + Constants.OBJECTCLASS + "=" + DataSource.class.getName() + ")("
+ + Constants.OBJECTCLASS + "=" + XADataSource.class.getName() + "))");
+ if (references != null) {
+ for (ServiceReference reference : references) {
+ if (reference.getProperty("osgi.jndi.service.name") != null) {
+ datasources.add((String) reference.getProperty("osgi.jndi.service.name"));
+ } else if (reference.getProperty("datasource") != null) {
+ datasources.add((String) reference.getProperty("datasource"));
+ } else if (reference.getProperty("name") != null) {
+ datasources.add((String) reference.getProperty("name"));
+ } else {
+ datasources.add(reference.getProperty(Constants.SERVICE_ID).toString());
+ }
+ }
+ }
+ return datasources;
+ }
+
+ @Override
+ public List<String> datasourceFileNames() throws Exception {
+ File karafBase = new File(System.getProperty("karaf.base"));
+ File deployFolder = new File(karafBase, "deploy");
+
+ String[] datasourceFileNames = deployFolder.list(new FilenameFilter() {
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("datasource-") && name.endsWith(".xml");
+ }
+ });
+
+ return Arrays.asList(datasourceFileNames);
+ }
+
+ @Override
+ public Map<String, List<String>> query(String datasource, String query) throws Exception {
+ JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
+ try {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ Statement statement = jdbcConnector.createStatement();
+ ResultSet resultSet = jdbcConnector.register(statement.executeQuery(query));
+ ResultSetMetaData metaData = resultSet.getMetaData();
+ for (int c = 1; c <= metaData.getColumnCount(); c++) {
+ map.put(metaData.getColumnLabel(c), new ArrayList<String>());
+ }
+ while (resultSet.next()) {
+ for (int c = 1; c <= metaData.getColumnCount(); c++) {
+ map.get(metaData.getColumnLabel(c)).add(resultSet.getString(c));
+ }
+ }
+ return map;
+ } finally {
+ jdbcConnector.close();
+ }
+ }
+
+ @Override
+ public void execute(String datasource, String command) throws Exception {
+ JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
+ try {
+ jdbcConnector.createStatement().execute(command);
+ } finally {
+ jdbcConnector.close();
+ }
+ }
+
+ @Override
+ public Map<String, List<String>> tables(String datasource) throws Exception {
+ JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
+ try {
+
+ DatabaseMetaData dbMetaData = jdbcConnector.connect().getMetaData();
+ ResultSet resultSet = jdbcConnector.register(dbMetaData.getTables(null, null, null, null));
+ ResultSetMetaData metaData = resultSet.getMetaData();
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ for (int c = 1; c <= metaData.getColumnCount(); c++) {
+ map.put(metaData.getColumnLabel(c), new ArrayList<String>());
+ }
+ while (resultSet.next()) {
+ for (int c = 1; c <= metaData.getColumnCount(); c++) {
+ map.get(metaData.getColumnLabel(c)).add(resultSet.getString(c));
+ }
+ }
+ return map;
+ } finally {
+ jdbcConnector.close();
+ }
+ }
+
+ @Override
+ public Map<String, String> info(String datasource) throws Exception {
+ JdbcConnector jdbcConnector = new JdbcConnector(bundleContext, datasource);
+ try {
+ DatabaseMetaData dbMetaData = jdbcConnector.connect().getMetaData();
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("db.product", dbMetaData.getDatabaseProductName());
+ map.put("db.version", dbMetaData.getDatabaseProductVersion());
+ map.put("url", dbMetaData.getURL());
+ map.put("username", dbMetaData.getUserName());
+ map.put("driver.name", dbMetaData.getDriverName());
+ map.put("driver.version", dbMetaData.getDriverVersion());
+ return map;
+ } finally {
+ jdbcConnector.close();
+ }
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml b/jdbc/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
new file mode 100644
index 0000000..e961697
--- /dev/null
+++ b/jdbc/src/main/resources/OSGI-INF/blueprint/jdbc-core.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ default-activation="lazy">
+
+ <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
+
+ <bean id="jdbcService" class="org.apache.karaf.jdbc.internal.JdbcServiceImpl">
+ <property name="bundleContext" ref="blueprintBundleContext"/>
+ </bean>
+
+ <service ref="jdbcService" interface="org.apache.karaf.jdbc.JdbcService" />
+
+ <!-- Management -->
+ <bean id="jdbcMBeanImpl" class="org.apache.karaf.jdbc.internal.JdbcMBeanImpl">
+ <property name="jdbcService" ref="jdbcService"/>
+ </bean>
+
+ <service ref="jdbcMBeanImpl" auto-export="interfaces">
+ <service-properties>
+ <entry key="jmx.objectname" value="org.apache.karaf:type=jdbc,name=$[karaf.name]"/>
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/OSGI-INF/bundle.info b/jdbc/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..bc7a1cd
--- /dev/null
+++ b/jdbc/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,18 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the JDBC service support.
+
+The JDBC service allows you to create datasources, see the defined datasources, execute query on a datasource, etc.
+
+h1. See also
+
+JDBC - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
new file mode 100644
index 0000000..da220a5
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-db2.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="dataSource" class="com.ibm.db2.jcc.DB2DataSource">
+ <property name="url" value="${url}"/>
+ <property name="user" value="${user}"/>
+ <property name="password" value="${password}"/>
+ </bean>
+
+ <service interface="javax.sql.DataSource" ref="dataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/a9b763f2/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
----------------------------------------------------------------------
diff --git a/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
new file mode 100644
index 0000000..440a439
--- /dev/null
+++ b/jdbc/src/main/resources/org/apache/karaf/jdbc/internal/datasource-derby.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ default-activation="eager">
+
+ <bean id="dataSource" class="org.apache.derby.jdbc.EmbeddedXADataSource">
+ <property name="databaseName" value="${name}"/>
+ <property name="createDatabase" value="create" />
+ </bean>
+
+ <service ref="dataSource" interface="javax.sql.DataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}"/>
+ </service-properties>
+ </service>
+
+ <service ref="dataSource" interface="javax.sql.XADataSource">
+ <service-properties>
+ <entry key="osgi.jndi.service.name" value="jdbc/${name}xa"/>
+ </service-properties>
+ </service>
+
+</blueprint>
[05/33] git commit: [KARAF-2888] Call listeners when features are
installed or uninstalled
Posted by gn...@apache.org.
[KARAF-2888] Call listeners when features are installed or uninstalled
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/6a19214e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/6a19214e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/6a19214e
Branch: refs/heads/master
Commit: 6a19214e566cec14c821aac849c8718a08eadaac
Parents: 4b6b7af
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 16:27:21 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:02 2014 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 28 +++++++++-----------
1 file changed, 12 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/6a19214e/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 6c16650..e6dbc32 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -799,7 +799,10 @@ public class FeaturesServiceImpl implements FeaturesService {
// Install conditionals
List<String> installedFeatureIds = getFeatureIds(allResources);
- List<Feature> installedFeatures = getFeatures(repositories, installedFeatureIds);
+ List<String> newFeatures = new ArrayList<String>(installedFeatureIds);
+ newFeatures.removeAll(installed);
+ List<String> delFeatures = new ArrayList<String>(installed);
+ delFeatures.removeAll(installedFeatureIds);
//
// Compute list of installable resources (those with uris)
@@ -955,25 +958,12 @@ public class FeaturesServiceImpl implements FeaturesService {
//
// Update and save state
//
- List<String> newFeatures = new ArrayList<String>();
synchronized (lock) {
- List<String> allFeatures = new ArrayList<String>();
- for (Resource resource : allResources) {
- String name = FeatureNamespace.getName(resource);
- if (name != null) {
- Version version = FeatureNamespace.getVersion(resource);
- String id = version != null ? name + "/" + version : name;
- allFeatures.add(id);
- if (!state.installedFeatures.contains(id)) {
- newFeatures.add(id);
- }
- }
- }
state.bundleChecksums.putAll(deployment.newCheckums);
state.features.clear();
state.features.addAll(features);
state.installedFeatures.clear();
- state.installedFeatures.addAll(allFeatures);
+ state.installedFeatures.addAll(installedFeatureIds);
state.managedBundles.clear();
state.managedBundles.addAll(managed);
saveState();
@@ -1061,7 +1051,13 @@ public class FeaturesServiceImpl implements FeaturesService {
}
}
- // TODO: call listeners for features added and removed
+ // Call listeners
+ for (Feature feature : getFeatures(repositories, delFeatures)) {
+ callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureUninstalled, false));
+ }
+ for (Feature feature : getFeatures(repositories, newFeatures)) {
+ callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, false));
+ }
print("Done.", verbose);
}
[09/33] git commit: [KARAF-2888] Optimize start bundle sorting which
is really slow
Posted by gn...@apache.org.
[KARAF-2888] Optimize start bundle sorting which is really slow
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/78fbae7f
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/78fbae7f
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/78fbae7f
Branch: refs/heads/master
Commit: 78fbae7faa140f88b76358d89af044dcc8693411
Parents: 286939f
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 15:47:33 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:03 2014 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 5 +-
.../internal/service/RequirementSort.java | 87 +++++++-------------
2 files changed, 33 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/78fbae7f/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 65223d5..7008ef6 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -64,10 +64,7 @@ import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
-import org.osgi.framework.namespace.PackageNamespace;
import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
@@ -1043,7 +1040,7 @@ public class FeaturesServiceImpl implements FeaturesService {
// TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
new CopyOnWriteArrayIdentityList().iterator();
- new RequirementSort();
+ RequirementSort.sort(Collections.<Resource>emptyList());
if (!noRefresh) {
toStop = new HashSet<Bundle>();
http://git-wip-us.apache.org/repos/asf/karaf/blob/78fbae7f/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java b/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
index e9ecece..96b99ee 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
@@ -16,92 +16,69 @@
*/
package org.apache.karaf.features.internal.service;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.CapabilitySet;
import org.apache.karaf.features.internal.resolver.SimpleFilter;
import org.osgi.framework.Constants;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-public class RequirementSort {
+public class RequirementSort<T extends Resource> {
/**
* Sorts {@link Resource} based on their {@link Requirement}s and {@link Capability}s.
- * @param resources
- * @return
*/
public static <T extends Resource> Collection<T> sort(Collection<T> resources) {
+ Set<String> namespaces = new HashSet<String>();
+ for (Resource r : resources) {
+ for (Capability cap : r.getCapabilities(null)) {
+ namespaces.add(cap.getNamespace());
+ }
+ }
+ CapabilitySet capSet = new CapabilitySet(new ArrayList<String>(namespaces));
+ for (Resource r : resources) {
+ for (Capability cap : r.getCapabilities(null)) {
+ capSet.addCapability(cap);
+ }
+ }
Set<T> sorted = new LinkedHashSet<T>();
Set<T> visited = new LinkedHashSet<T>();
for (T r : resources) {
- visit(r, resources, visited, sorted);
+ visit(r, visited, sorted, capSet);
}
return sorted;
}
- private static <T extends Resource> void visit(T resource, Collection<T> resources, Set<T> visited, Set<T> sorted) {
- if (visited.contains(resource)) {
+ private static <T extends Resource> void visit(T resource, Set<T> visited, Set<T> sorted, CapabilitySet capSet) {
+ if (!visited.add(resource)) {
return;
}
- visited.add(resource);
- for (T r : collectDependencies(resource, resources)) {
- visit(r, resources, visited, sorted);
+ for (T r : collectDependencies(resource, capSet)) {
+ visit(r, visited, sorted, capSet);
}
sorted.add(resource);
}
- /**
- * Finds the dependencies of the current resource.
- * @param resource
- * @param allResources
- * @return
- */
- private static <T extends Resource> Set<T> collectDependencies(T resource, Collection<T> allResources) {
+ @SuppressWarnings("unchecked")
+ private static <T extends Resource> Set<T> collectDependencies(T resource, CapabilitySet capSet) {
Set<T> result = new LinkedHashSet<T>();
- List<Requirement> requirements = resource.getRequirements(null);
- for (Requirement requirement : requirements) {
- boolean isSatisfied = false;
- for (Resource r : result) {
- for (Capability capability : r.getCapabilities(null)) {
- if (isSatisfied(requirement, capability)) {
- isSatisfied = true;
- break;
- }
- }
- }
-
- for (T r : allResources) {
- if (!isSatisfied) {
- for (Capability capability : r.getCapabilities(null)) {
- if (isSatisfied(requirement, capability)) {
- result.add(r);
- break;
- }
- }
- }
- }
- }
- return result;
- }
-
- private static boolean isSatisfied(Requirement requirement, Capability capability) {
- RequirementImpl br;
- if (requirement instanceof RequirementImpl) {
- br = (RequirementImpl) requirement;
- } else {
+ for (Requirement requirement : resource.getRequirements(null)) {
String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
SimpleFilter sf = (filter != null)
? SimpleFilter.parse(filter)
: new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
- br = new RequirementImpl(null, requirement.getNamespace(), requirement.getDirectives(), requirement.getAttributes(), sf);
+ for (Capability cap : capSet.match(sf, true)) {
+ result.add((T) cap.getResource());
+ }
}
- return br.matches(capability);
+ return result;
}
+
}
[26/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
new file mode 100644
index 0000000..56e5102
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.net.URI;
+
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+
+/**
+ * The repository implementation.
+ */
+public class RepositoryImpl implements Repository {
+
+ private final URI uri;
+ private Features features;
+
+ public RepositoryImpl(URI uri) {
+ this.uri = uri;
+ }
+
+ public URI getURI() {
+ return uri;
+ }
+
+ public String getName() throws IOException {
+ load();
+ return features.getName();
+ }
+
+ public URI[] getRepositories() throws Exception {
+ load();
+ URI[] result = new URI[features.getRepository().size()];
+ for (int i = 0; i < features.getRepository().size(); i++) {
+ String uri = features.getRepository().get(i);
+ uri = uri.trim();
+ result[i] = URI.create(uri);
+ }
+ return result;
+ }
+
+ public org.apache.karaf.features.Feature[] getFeatures() throws Exception {
+ load();
+ return features.getFeature().toArray(new org.apache.karaf.features.Feature[features.getFeature().size()]);
+ }
+
+
+ public void load() throws IOException {
+ load(false);
+ }
+
+ public void load(boolean validate) throws IOException {
+ if (features == null) {
+ try {
+ InputStream inputStream = uri.toURL().openStream();
+ inputStream = new FilterInputStream(inputStream) {
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (Thread.currentThread().isInterrupted()) {
+ throw new InterruptedIOException();
+ }
+ return super.read(b, off, len);
+ }
+ };
+ try {
+ features = JaxbUtil.unmarshal(uri.toASCIIString(), inputStream, validate);
+ } finally {
+ inputStream.close();
+ }
+ } catch (IllegalArgumentException e) {
+ throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
+ } catch (Exception e) {
+ throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
+ }
+ }
+ }
+
+ @Override
+ public boolean isValid() {
+ throw new UnsupportedOperationException();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
new file mode 100644
index 0000000..96b99ee
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.karaf.features.internal.resolver.CapabilitySet;
+import org.apache.karaf.features.internal.resolver.SimpleFilter;
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class RequirementSort<T extends Resource> {
+
+ /**
+ * Sorts {@link Resource} based on their {@link Requirement}s and {@link Capability}s.
+ */
+ public static <T extends Resource> Collection<T> sort(Collection<T> resources) {
+ Set<String> namespaces = new HashSet<String>();
+ for (Resource r : resources) {
+ for (Capability cap : r.getCapabilities(null)) {
+ namespaces.add(cap.getNamespace());
+ }
+ }
+ CapabilitySet capSet = new CapabilitySet(new ArrayList<String>(namespaces));
+ for (Resource r : resources) {
+ for (Capability cap : r.getCapabilities(null)) {
+ capSet.addCapability(cap);
+ }
+ }
+ Set<T> sorted = new LinkedHashSet<T>();
+ Set<T> visited = new LinkedHashSet<T>();
+ for (T r : resources) {
+ visit(r, visited, sorted, capSet);
+ }
+ return sorted;
+ }
+
+
+ private static <T extends Resource> void visit(T resource, Set<T> visited, Set<T> sorted, CapabilitySet capSet) {
+ if (!visited.add(resource)) {
+ return;
+ }
+ for (T r : collectDependencies(resource, capSet)) {
+ visit(r, visited, sorted, capSet);
+ }
+ sorted.add(resource);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Resource> Set<T> collectDependencies(T resource, CapabilitySet capSet) {
+ Set<T> result = new LinkedHashSet<T>();
+ for (Requirement requirement : resource.getRequirements(null)) {
+ String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+ SimpleFilter sf = (filter != null)
+ ? SimpleFilter.parse(filter)
+ : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+ for (Capability cap : capSet.match(sf, true)) {
+ result.add((T) cap.getResource());
+ }
+ }
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
new file mode 100644
index 0000000..d1f16b9
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.karaf.features.internal.deployment.Downloader;
+import org.apache.karaf.features.internal.deployment.StreamProvider;
+import org.apache.karaf.features.internal.util.MultiException;
+
+public class SimpleDownloader implements Downloader {
+
+ private final MultiException exception = new MultiException("Error");
+
+ @Override
+ public void await() throws InterruptedException, MultiException {
+ exception.throwIfExceptions();
+ }
+
+ @Override
+ public void download(final String location, final DownloadCallback downloadCallback) throws MalformedURLException {
+ final URL url = new URL(location);
+ try {
+ downloadCallback.downloaded(new StreamProvider() {
+ @Override
+ public InputStream open() throws IOException {
+ return url.openStream();
+ }
+ });
+ } catch (Exception e) {
+ exception.addException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
new file mode 100644
index 0000000..c84f4e0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class State {
+
+ public final AtomicBoolean bootDone = new AtomicBoolean();
+ public final Set<String> repositories = new TreeSet<String>();
+ public final Set<String> features = new TreeSet<String>();
+ public final Set<String> installedFeatures = new TreeSet<String>();
+ public final Set<Long> managedBundles = new TreeSet<Long>();
+ public final Map<String, Long> bundleChecksums = new HashMap<String, Long>();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
new file mode 100644
index 0000000..ac54ab0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.karaf.features.Feature;
+
+public abstract class StateStorage {
+
+ public void load(State state) throws IOException {
+ state.repositories.clear();
+ state.features.clear();
+ state.installedFeatures.clear();
+ state.managedBundles.clear();
+ InputStream is = getInputStream();
+ if (is != null) {
+ try {
+ Properties props = new Properties();
+ props.load(is);
+ state.bootDone.set(loadBool(props, "bootDone"));
+ state.repositories.addAll(loadSet(props, "repositories."));
+ state.features.addAll(loadSet(props, "features."));
+ state.installedFeatures.addAll(loadSet(props, "installed."));
+ state.managedBundles.addAll(toLongSet(loadSet(props, "managed.")));
+ state.bundleChecksums.putAll(toStringLongMap(loadMap(props, "checksums.")));
+ } finally {
+ close(is);
+ }
+ }
+ }
+
+ public void save(State state) throws IOException {
+ OutputStream os = getOutputStream();
+ if (os != null) {
+ try {
+ Properties props = new Properties();
+ saveBool(props, "bootDone", state.bootDone.get());
+ saveSet(props, "repositories.", state.repositories);
+ saveSet(props, "features.", state.features);
+ saveSet(props, "installed.", state.installedFeatures);
+ saveSet(props, "managed.", toStringSet(state.managedBundles));
+ saveMap(props, "checksums.", toStringStringMap(state.bundleChecksums));
+ props.store(os, "FeaturesService State");
+ } finally {
+ close(os);
+ }
+ }
+ }
+
+ protected abstract InputStream getInputStream() throws IOException;
+ protected abstract OutputStream getOutputStream() throws IOException;
+
+ protected boolean loadBool(Properties props, String key) {
+ return Boolean.parseBoolean(props.getProperty(key));
+ }
+
+ protected void saveBool(Properties props, String key, boolean val) {
+ props.setProperty(key, Boolean.toString(val));
+ }
+
+ protected Set<String> toStringSet(Set<Long> set) {
+ Set<String> ns = new TreeSet<String>();
+ for (long l : set) {
+ ns.add(Long.toString(l));
+ }
+ return ns;
+ }
+
+ protected Set<Long> toLongSet(Set<String> set) {
+ Set<Long> ns = new TreeSet<Long>();
+ for (String s : set) {
+ ns.add(Long.parseLong(s));
+ }
+ return ns;
+ }
+
+ protected void saveSet(Properties props, String prefix, Set<String> set) {
+ List<String> l = new ArrayList<String>(set);
+ props.put(prefix + "count", Integer.toString(l.size()));
+ for (int i = 0; i < l.size(); i++) {
+ props.put(prefix + "item." + i, l.get(i));
+ }
+ }
+
+ protected Set<String> loadSet(Properties props, String prefix) {
+ Set<String> l = new HashSet<String>();
+ String countStr = (String) props.get(prefix + "count");
+ if (countStr != null) {
+ int count = Integer.parseInt(countStr);
+ for (int i = 0; i < count; i++) {
+ l.add((String) props.get(prefix + "item." + i));
+ }
+ }
+ return l;
+ }
+
+ protected Map<String, String> toStringStringMap(Map<String, Long> map) {
+ Map<String, String> nm = new HashMap<String, String>();
+ for (Map.Entry<String, Long> entry : map.entrySet()) {
+ nm.put(entry.getKey(), Long.toString(entry.getValue()));
+ }
+ return nm;
+ }
+
+ protected Map<String, Long> toStringLongMap(Map<String, String> map) {
+ Map<String, Long> nm = new HashMap<String, Long>();
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ nm.put(entry.getKey(), Long.parseLong(entry.getValue()));
+ }
+ return nm;
+ }
+
+
+ protected void saveMap(Properties props, String prefix, Map<String, String> map) {
+ List<Map.Entry<String, String>> l = new ArrayList<Map.Entry<String, String>>(map.entrySet());
+ props.put(prefix + "count", Integer.toString(l.size()));
+ for (int i = 0; i < l.size(); i++) {
+ props.put(prefix + "key." + i, l.get(i).getKey());
+ props.put(prefix + "val." + i, l.get(i).getValue());
+ }
+ }
+
+ protected Map<String, String> loadMap(Properties props, String prefix) {
+ Map<String, String> l = new HashMap<String, String>();
+ String countStr = (String) props.get(prefix + "count");
+ if (countStr != null) {
+ int count = Integer.parseInt(countStr);
+ for (int i = 0; i < count; i++) {
+ String key = (String) props.get(prefix + "key." + i);
+ String val = (String) props.get(prefix + "val." + i);
+ l.put(key, val);
+ }
+ }
+ return l;
+ }
+
+
+ protected void close(Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
new file mode 100644
index 0000000..19fc706
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.CRC32;
+
+public class ChecksumUtils {
+
+ private ChecksumUtils() {
+ }
+
+ /**
+ * Compute a cheksum for the file or directory that consists of the name, length and the last modified date
+ * for a file and its children in case of a directory
+ *
+ * @param is the input stream
+ * @return a checksum identifying any change
+ */
+ public static long checksum(InputStream is) throws IOException
+ {
+ try {
+ CRC32 crc = new CRC32();
+ byte[] buffer = new byte[8192];
+ int l;
+ while ((l = is.read(buffer)) > 0) {
+ crc.update(buffer, 0, l);
+ }
+ return crc.getValue();
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
new file mode 100644
index 0000000..a53d8a5
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ */
+public class JsonReader {
+
+ public static Object read(Reader reader) throws IOException {
+ return new JsonReader(reader).parse();
+ }
+
+ public static Object read(InputStream is) throws IOException {
+ return new JsonReader(new InputStreamReader(is)).parse();
+ }
+
+ //
+ // Implementation
+ //
+
+ private final Reader reader;
+ private final StringBuilder recorder;
+ private int current;
+ private int line = 1;
+ private int column = 0;
+
+ JsonReader(Reader reader) {
+ this.reader = reader;
+ recorder = new StringBuilder();
+ }
+
+ public Object parse() throws IOException {
+ read();
+ skipWhiteSpace();
+ Object result = readValue();
+ skipWhiteSpace();
+ if (!endOfText()) {
+ throw error("Unexpected character");
+ }
+ return result;
+ }
+
+ private Object readValue() throws IOException {
+ switch (current) {
+ case 'n':
+ return readNull();
+ case 't':
+ return readTrue();
+ case 'f':
+ return readFalse();
+ case '"':
+ return readString();
+ case '[':
+ return readArray();
+ case '{':
+ return readObject();
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return readNumber();
+ default:
+ throw expected("value");
+ }
+ }
+
+ private Collection<?> readArray() throws IOException {
+ read();
+ Collection<Object> array = new ArrayList<Object>();
+ skipWhiteSpace();
+ if (readChar(']')) {
+ return array;
+ }
+ do {
+ skipWhiteSpace();
+ array.add(readValue());
+ skipWhiteSpace();
+ } while (readChar(','));
+ if (!readChar(']')) {
+ throw expected("',' or ']'");
+ }
+ return array;
+ }
+
+ private Map<String, Object> readObject() throws IOException {
+ read();
+ Map<String, Object> object = new HashMap<String, Object>();
+ skipWhiteSpace();
+ if (readChar('}')) {
+ return object;
+ }
+ do {
+ skipWhiteSpace();
+ String name = readName();
+ skipWhiteSpace();
+ if (!readChar(':')) {
+ throw expected("':'");
+ }
+ skipWhiteSpace();
+ object.put(name, readValue());
+ skipWhiteSpace();
+ } while (readChar(','));
+ if (!readChar('}')) {
+ throw expected("',' or '}'");
+ }
+ return object;
+ }
+
+ private Object readNull() throws IOException {
+ read();
+ readRequiredChar('u');
+ readRequiredChar('l');
+ readRequiredChar('l');
+ return null;
+ }
+
+ private Boolean readTrue() throws IOException {
+ read();
+ readRequiredChar('r');
+ readRequiredChar('u');
+ readRequiredChar('e');
+ return Boolean.TRUE;
+ }
+
+ private Boolean readFalse() throws IOException {
+ read();
+ readRequiredChar('a');
+ readRequiredChar('l');
+ readRequiredChar('s');
+ readRequiredChar('e');
+ return Boolean.FALSE;
+ }
+
+ private void readRequiredChar(char ch) throws IOException {
+ if (!readChar(ch)) {
+ throw expected("'" + ch + "'");
+ }
+ }
+
+ private String readString() throws IOException {
+ read();
+ recorder.setLength(0);
+ while (current != '"') {
+ if (current == '\\') {
+ readEscape();
+ } else if (current < 0x20) {
+ throw expected("valid string character");
+ } else {
+ recorder.append((char) current);
+ read();
+ }
+ }
+ read();
+ return recorder.toString();
+ }
+
+ private void readEscape() throws IOException {
+ read();
+ switch (current) {
+ case '"':
+ case '/':
+ case '\\':
+ recorder.append((char) current);
+ break;
+ case 'b':
+ recorder.append('\b');
+ break;
+ case 'f':
+ recorder.append('\f');
+ break;
+ case 'n':
+ recorder.append('\n');
+ break;
+ case 'r':
+ recorder.append('\r');
+ break;
+ case 't':
+ recorder.append('\t');
+ break;
+ case 'u':
+ char[] hexChars = new char[4];
+ for (int i = 0; i < 4; i++) {
+ read();
+ if (!isHexDigit(current)) {
+ throw expected("hexadecimal digit");
+ }
+ hexChars[i] = (char) current;
+ }
+ recorder.append((char) Integer.parseInt(String.valueOf(hexChars), 16));
+ break;
+ default:
+ throw expected("valid escape sequence");
+ }
+ read();
+ }
+
+ private Number readNumber() throws IOException {
+ recorder.setLength(0);
+ readAndAppendChar('-');
+ int firstDigit = current;
+ if (!readAndAppendDigit()) {
+ throw expected("digit");
+ }
+ if (firstDigit != '0') {
+ while (readAndAppendDigit()) {
+ }
+ }
+ readFraction();
+ readExponent();
+ return Double.parseDouble(recorder.toString());
+ }
+
+ private boolean readFraction() throws IOException {
+ if (!readAndAppendChar('.')) {
+ return false;
+ }
+ if (!readAndAppendDigit()) {
+ throw expected("digit");
+ }
+ while (readAndAppendDigit()) {
+ }
+ return true;
+ }
+
+ private boolean readExponent() throws IOException {
+ if (!readAndAppendChar('e') && !readAndAppendChar('E')) {
+ return false;
+ }
+ if (!readAndAppendChar('+')) {
+ readAndAppendChar('-');
+ }
+ if (!readAndAppendDigit()) {
+ throw expected("digit");
+ }
+ while (readAndAppendDigit()) {
+ }
+ return true;
+ }
+
+ private String readName() throws IOException {
+ if (current != '"') {
+ throw expected("name");
+ }
+ readString();
+ return recorder.toString();
+ }
+
+ private boolean readAndAppendChar(char ch) throws IOException {
+ if (current != ch) {
+ return false;
+ }
+ recorder.append(ch);
+ read();
+ return true;
+ }
+
+ private boolean readChar(char ch) throws IOException {
+ if (current != ch) {
+ return false;
+ }
+ read();
+ return true;
+ }
+
+ private boolean readAndAppendDigit() throws IOException {
+ if (!isDigit(current)) {
+ return false;
+ }
+ recorder.append((char) current);
+ read();
+ return true;
+ }
+
+ private void skipWhiteSpace() throws IOException {
+ while (isWhiteSpace(current) && !endOfText()) {
+ read();
+ }
+ }
+
+ private void read() throws IOException {
+ if (endOfText()) {
+ throw error("Unexpected end of input");
+ }
+ column++;
+ if (current == '\n') {
+ line++;
+ column = 0;
+ }
+ current = reader.read();
+ }
+
+ private boolean endOfText() {
+ return current == -1;
+ }
+
+ private IOException expected(String expected) {
+ if (endOfText()) {
+ return error("Unexpected end of input");
+ }
+ return error("Expected " + expected);
+ }
+
+ private IOException error(String message) {
+ return new IOException(message + " at " + line + ":" + column);
+ }
+
+ private static boolean isWhiteSpace(int ch) {
+ return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
+ }
+
+ private static boolean isDigit(int ch) {
+ return ch >= '0' && ch <= '9';
+ }
+
+ private static boolean isHexDigit(int ch) {
+ return ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F';
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
new file mode 100644
index 0000000..cba27fb
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ */
+public class JsonWriter {
+
+ public static void write(Writer writer, Object value) throws IOException {
+ if (value instanceof Map) {
+ writeObject(writer, (Map) value);
+ } else if (value instanceof Collection) {
+ writeArray(writer, (Collection) value);
+ } else if (value instanceof Number) {
+ writeNumber(writer, (Number) value);
+ } else if (value instanceof String) {
+ writeString(writer, (String) value);
+ } else if (value instanceof Boolean) {
+ writeBoolean(writer, (Boolean) value);
+ } else if (value == null) {
+ writeNull(writer);
+ } else {
+ throw new IllegalArgumentException("Unsupported value: " + value);
+ }
+ }
+
+ private static void writeObject(Writer writer, Map<?, ?> value) throws IOException {
+ writer.append('{');
+ boolean first = true;
+ for (Map.Entry entry : value.entrySet()) {
+ if (!first) {
+ writer.append(',');
+ } else {
+ first = false;
+ }
+ writeString(writer, (String) entry.getKey());
+ writer.append(':');
+ write(writer, entry.getValue());
+ }
+ writer.append('}');
+ }
+
+ private static void writeString(Writer writer, String value) throws IOException {
+ writer.append('"');
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ switch (c) {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ writer.append('\\');
+ writer.append(c);
+ break;
+ default:
+ if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
+ String s = Integer.toHexString(c);
+ writer.append('\\');
+ writer.append('u');
+ for (int j = s.length(); j < 4; j++) {
+ writer.append('0');
+ }
+ writer.append(s);
+ } else {
+ writer.append(c);
+ }
+ break;
+ }
+ }
+ writer.append('"');
+ }
+
+ private static void writeNumber(Writer writer, Number value) throws IOException {
+ writer.append(value.toString());
+ }
+
+ private static void writeBoolean(Writer writer, Boolean value) throws IOException {
+ writer.append(Boolean.toString(value));
+ }
+
+ private static void writeArray(Writer writer, Collection<?> value) throws IOException {
+ writer.append('[');
+ boolean first = true;
+ for (Object obj : value) {
+ if (!first) {
+ writer.append(',');
+ } else {
+ first = false;
+ }
+ write(writer, obj);
+ }
+ writer.append(']');
+ }
+
+ private static void writeNull(Writer writer) throws IOException {
+ writer.append("null");
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
new file mode 100644
index 0000000..d30b7b5
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.utils.version.VersionTable;
+import org.osgi.framework.Version;
+
+public class Macro {
+
+ public static String transform(String macro, String value) {
+ if (macro.startsWith("${") && macro.endsWith("}")) {
+ String[] args = macro.substring(2, macro.length() - 1).split(";");
+ if ("version".equals(args[0])) {
+ if (args.length != 2) {
+ throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
+ }
+ return version(args[1], VersionTable.getVersion(value));
+ } else if ("range".equals(args[0])) {
+ if (args.length != 2) {
+ throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
+ }
+ return range(args[1], VersionTable.getVersion(value));
+ } else {
+ throw new IllegalArgumentException("Unknown macro: " + macro);
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Modify a version to set a version policy. Thed policy is a mask that is
+ * mapped to a version.
+ *
+ * <pre>
+ * + increment
+ * - decrement
+ * = maintain
+ * ˜ discard
+ *
+ * ==+ = maintain major, minor, increment micro, discard qualifier
+ * ˜˜˜= = just get the qualifier
+ * version="[${version;==;${@}},${version;=+;${@}})"
+ * </pre>
+ *
+ * @param args
+ * @return
+ */
+ final static String MASK_STRING = "[\\-+=~0123456789]{0,3}[=~]?";
+
+ static String version(String mask, Version version) {
+ StringBuilder sb = new StringBuilder();
+ String del = "";
+
+ for (int i = 0; i < mask.length(); i++) {
+ char c = mask.charAt(i);
+ String result = null;
+ if (c != '~') {
+ if (i > 3) {
+ throw new IllegalArgumentException("Version mask can only specify 3 digits");
+ } else if (i == 3) {
+ result = version.getQualifier();
+ if (result.isEmpty()) {
+ result = null;
+ }
+ } else if (Character.isDigit(c)) {
+ // Handle masks like +00, =+0
+ result = String.valueOf(c);
+ } else {
+ int x = 0;
+ switch (i) {
+ case 0: x = version.getMajor(); break;
+ case 1: x = version.getMinor(); break;
+ case 2: x = version.getMicro(); break;
+ }
+ switch (c) {
+ case '+' :
+ x++;
+ break;
+ case '-' :
+ x--;
+ break;
+ case '=' :
+ break;
+ }
+ result = Integer.toString(x);
+ }
+ if (result != null) {
+ sb.append(del);
+ del = ".";
+ sb.append(result);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Schortcut for version policy
+ *
+ * <pre>
+ * -provide-policy : ${policy;[==,=+)}
+ * -consume-policy : ${policy;[==,+)}
+ * </pre>
+ *
+ * @param args
+ * @return
+ */
+
+ static Pattern RANGE_MASK = Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
+
+ static String range(String spec, Version version) {
+ Matcher m = RANGE_MASK.matcher(spec);
+ m.matches();
+ String floor = m.group(1);
+ String floorMask = m.group(2);
+ String ceilingMask = m.group(3);
+ String ceiling = m.group(4);
+
+ String left = version(floorMask, version);
+ String right = version(ceilingMask, version);
+
+ return floor + left + "," + right + ceiling;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
new file mode 100644
index 0000000..36af452
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class MultiException extends Exception {
+
+ private List<Exception> exceptions = new ArrayList<Exception>();
+
+ public MultiException(String message) {
+ super(message);
+ }
+
+ public MultiException(String message, List<Exception> exceptions) {
+ super(message);
+ this.exceptions = exceptions;
+ }
+
+ public void addException(Exception e) {
+ exceptions.add(e);
+ }
+
+ public void throwIfExceptions() throws MultiException {
+ if (!exceptions.isEmpty()) {
+ throw this;
+ }
+ }
+
+ public Throwable[] getCauses() {
+ return exceptions.toArray(new Throwable[exceptions.size()]);
+ }
+
+ @Override
+ public void printStackTrace()
+ {
+ super.printStackTrace();
+ for (Exception e : exceptions) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /* ------------------------------------------------------------------------------- */
+ /**
+ * @see Throwable#printStackTrace(java.io.PrintStream)
+ */
+ @Override
+ public void printStackTrace(PrintStream out)
+ {
+ super.printStackTrace(out);
+ for (Exception e : exceptions) {
+ e.printStackTrace(out);
+ }
+ }
+
+ @Override
+ public void printStackTrace(PrintWriter out)
+ {
+ super.printStackTrace(out);
+ for (Exception e : exceptions) {
+ e.printStackTrace(out);
+ }
+ }
+
+ public static void throwIf(String message, List<Exception> exceptions) throws MultiException {
+ if (exceptions != null && !exceptions.isEmpty()) {
+ StringBuilder sb = new StringBuilder(message);
+ sb.append(":");
+ for (Exception e : exceptions) {
+ sb.append("\n\t");
+ sb.append(e.getMessage());
+ }
+ throw new MultiException(sb.toString(), exceptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java b/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
new file mode 100644
index 0000000..6afbbed
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.management;
+
+import javax.management.openmbean.TabularData;
+
+public interface FeaturesServiceMBean {
+
+ TabularData getFeatures() throws Exception;
+
+ TabularData getRepositories() throws Exception;
+
+ void addRepository(String url) throws Exception;
+
+ void addRepository(String url, boolean install) throws Exception;
+
+ void removeRepository(String url) throws Exception;
+
+ void removeRepository(String url, boolean uninstall) throws Exception;
+
+ void installFeature(String name) throws Exception;
+
+ void installFeature(String name, boolean noRefresh) throws Exception;
+
+ void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception;
+
+ void installFeature(String name, String version) throws Exception;
+
+ void installFeature(String name, String version, boolean noRefresh) throws Exception;
+
+ void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception;
+
+ TabularData infoFeature(String name) throws Exception;
+
+ TabularData infoFeature(String name, String version) throws Exception;
+
+ void uninstallFeature(String name) throws Exception;
+
+ void uninstallFeature(String name, boolean noRefresh) throws Exception;
+
+ void uninstallFeature(String name, String version) throws Exception;
+
+ void uninstallFeature(String name, String version, boolean noRefresh) throws Exception;
+
+ String FEATURE_NAME = "Name";
+
+ String FEATURE_VERSION = "Version";
+
+ String FEATURE_DEPENDENCIES = "Dependencies";
+
+ String FEATURE_BUNDLES = "Bundles";
+
+ String FEATURE_CONFIGURATIONS = "Configurations";
+
+ String FEATURE_CONFIGURATIONFILES = "Configuration Files";
+
+ String FEATURE_INSTALLED = "Installed";
+
+ String FEATURE_CONFIG_PID = "Pid";
+ String FEATURE_CONFIG_ELEMENTS = "Elements";
+ String FEATURE_CONFIG_ELEMENT_KEY = "Key";
+ String FEATURE_CONFIG_ELEMENT_VALUE = "Value";
+
+ String FEATURE_CONFIG_FILES_ELEMENTS = "Files";
+
+ /**
+ * The type of the event which is emitted for features events
+ */
+ String FEATURE_EVENT_TYPE = "org.apache.karaf.features.featureEvent";
+
+ String FEATURE_EVENT_EVENT_TYPE = "Type";
+
+ String FEATURE_EVENT_EVENT_TYPE_INSTALLED = "Installed";
+
+ String FEATURE_EVENT_EVENT_TYPE_UNINSTALLED = "Uninstalled";
+
+ /**
+ * The item names in the CompositeData representing a feature
+ */
+ String[] FEATURE = { FEATURE_NAME, FEATURE_VERSION, FEATURE_DEPENDENCIES, FEATURE_BUNDLES,
+ FEATURE_CONFIGURATIONS, FEATURE_CONFIGURATIONFILES, FEATURE_INSTALLED };
+
+ String[] FEATURE_IDENTIFIER = { FEATURE_NAME, FEATURE_VERSION };
+
+ String[] FEATURE_CONFIG = { FEATURE_CONFIG_PID, FEATURE_CONFIG_ELEMENTS };
+
+ String[] FEATURE_CONFIG_FILES = { FEATURE_CONFIG_FILES_ELEMENTS };
+
+ String[] FEATURE_CONFIG_ELEMENT = { FEATURE_CONFIG_ELEMENT_KEY, FEATURE_CONFIG_ELEMENT_VALUE };
+
+ /**
+ * The item names in the CompositeData representing the event raised for
+ * feature events within the OSGi container by this bean
+ */
+ String[] FEATURE_EVENT = { FEATURE_NAME, FEATURE_VERSION, FEATURE_EVENT_EVENT_TYPE };
+
+
+ String REPOSITORY_NAME = "Name";
+
+ String REPOSITORY_URI = "Uri";
+
+ String REPOSITORY_REPOSITORIES = "Repositories";
+
+ String REPOSITORY_FEATURES = "Features";
+
+ /**
+ * The type of the event which is emitted for repositories events
+ */
+ String REPOSITORY_EVENT_TYPE = "org.apache.karaf.features.repositoryEvent";
+
+ String REPOSITORY_EVENT_EVENT_TYPE = "Type";
+
+ String REPOSITORY_EVENT_EVENT_TYPE_ADDED = "Added";
+
+ String REPOSITORY_EVENT_EVENT_TYPE_REMOVED = "Removed";
+
+ /**
+ * The item names in the CompositeData representing a feature
+ */
+ String[] REPOSITORY = { REPOSITORY_NAME, REPOSITORY_URI, REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
+
+ /**
+ * The item names in the CompositeData representing the event raised for
+ * feature events within the OSGi container by this bean
+ */
+ String[] REPOSITORY_EVENT = { REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
new file mode 100644
index 0000000..54fa3c0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.management.codec;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxFeature {
+
+ /**
+ * The CompositeType which represents a single feature
+ */
+ public final static CompositeType FEATURE;
+
+ /**
+ * The TabularType which represents a list of features
+ */
+ public final static TabularType FEATURE_TABLE;
+
+ public final static CompositeType FEATURE_IDENTIFIER;
+
+ public final static TabularType FEATURE_IDENTIFIER_TABLE;
+
+ public final static CompositeType FEATURE_CONFIG_ELEMENT;
+
+ public final static TabularType FEATURE_CONFIG_ELEMENT_TABLE;
+
+ public final static CompositeType FEATURE_CONFIG;
+
+ public final static TabularType FEATURE_CONFIG_TABLE;
+
+ public final static CompositeType FEATURE_CONFIG_FILES;
+
+ public final static TabularType FEATURE_CONFIG_FILES_TABLE;
+
+ private final CompositeData data;
+
+ public JmxFeature(Feature feature, boolean installed) {
+ try {
+ String[] itemNames = FeaturesServiceMBean.FEATURE;
+ Object[] itemValues = new Object[itemNames.length];
+ itemValues[0] = feature.getName();
+ itemValues[1] = feature.getVersion();
+ itemValues[2] = getDependencyIdentifierTable(feature.getDependencies());
+ itemValues[3] = getBundleUris(feature.getBundles());
+ itemValues[4] = getConfigTable(feature.getConfigurations());
+ itemValues[5] = getConfigFileList(feature.getConfigurationFiles());
+ itemValues[6] = installed;
+ data = new CompositeDataSupport(FEATURE, itemNames, itemValues);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Cannot form feature open data", e);
+ }
+ }
+
+ public CompositeData asCompositeData() {
+ return data;
+ }
+
+ public static TabularData tableFrom(Collection<JmxFeature> features) {
+ TabularDataSupport table = new TabularDataSupport(FEATURE_TABLE);
+ for (JmxFeature feature : features) {
+ table.put(feature.asCompositeData());
+ }
+ return table;
+ }
+
+ private static TabularData getDependencyIdentifierTable(List<Dependency> features) throws OpenDataException {
+ TabularDataSupport table = new TabularDataSupport(FEATURE_IDENTIFIER_TABLE);
+ Set<String> featureSet = new HashSet<String>();
+ for (Dependency feature : features) {
+ if (featureSet.contains(feature.getName() + feature.getVersion())) {
+ continue;
+ } else {
+ featureSet.add(feature.getName() + feature.getVersion());
+ }
+ String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
+ Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
+ CompositeData ident = new CompositeDataSupport(FEATURE_IDENTIFIER, itemNames, itemValues);
+ table.put(ident);
+ }
+ return table;
+ }
+
+ static String[] getBundleUris(List<BundleInfo> infos) {
+ String[] array = new String[infos.size()];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = infos.get(i).getLocation();
+ }
+ return array;
+ }
+
+ static TabularData getConfigTable(Map<String, Map<String, String>> configs) throws OpenDataException {
+ TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_TABLE);
+ for (Map.Entry<String, Map<String, String>> entry : configs.entrySet()) {
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
+ Object[] itemValues = new Object[2];
+ itemValues[0] = entry.getKey();
+ itemValues[1] = getConfigElementTable(entry.getValue());
+ CompositeData config = new CompositeDataSupport(FEATURE_CONFIG, itemNames, itemValues);
+ table.put(config);
+ }
+ return table;
+ }
+
+ static TabularData getConfigFileList(List<ConfigFileInfo> configFiles) throws OpenDataException {
+ TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_FILES_TABLE);
+ for (ConfigFileInfo configFile : configFiles) {
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
+ Object[] itemValues = { configFile.getFinalname() };
+ CompositeData config = new CompositeDataSupport(FEATURE_CONFIG_FILES, itemNames, itemValues);
+ table.put(config);
+ }
+ return table;
+ }
+
+ static TabularData getConfigElementTable(Map<String, String> config) throws OpenDataException {
+ TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_ELEMENT_TABLE);
+ for (Map.Entry<String, String> entry : config.entrySet()) {
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
+ Object[] itemValues = { entry.getKey(), entry.getValue() };
+ CompositeData element = new CompositeDataSupport(FEATURE_CONFIG_ELEMENT, itemNames, itemValues);
+ table.put(element);
+ }
+ return table;
+ }
+
+
+ static {
+ FEATURE_IDENTIFIER = createFeatureIdentifierType();
+ FEATURE_IDENTIFIER_TABLE = createFeatureIdentifierTableType();
+ FEATURE_CONFIG_ELEMENT = createFeatureConfigElementType();
+ FEATURE_CONFIG_ELEMENT_TABLE = createFeatureConfigElementTableType();
+ FEATURE_CONFIG = createFeatureConfigType();
+ FEATURE_CONFIG_TABLE = createFeatureConfigTableType();
+ FEATURE_CONFIG_FILES = createFeatureConfigFilesType();
+ FEATURE_CONFIG_FILES_TABLE = createFeatureConfigFilesTableType();
+ FEATURE = createFeatureType();
+ FEATURE_TABLE = createFeatureTableType();
+ }
+
+ private static CompositeType createFeatureIdentifierType() {
+ try {
+ String description = "This type identify a Karaf features";
+ String[] itemNames = FeaturesServiceMBean.FEATURE_IDENTIFIER;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+
+ itemDescriptions[0] = "The id of the feature";
+ itemDescriptions[1] = "The version of the feature";
+
+ return new CompositeType("FeatureIdentifier", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build featureIdentifier type", e);
+ }
+ }
+
+ private static TabularType createFeatureIdentifierTableType() {
+ try {
+ return new TabularType("Features", "The table of featureIdentifiers",
+ FEATURE_IDENTIFIER, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build featureIdentifier table type", e);
+ }
+ }
+
+ private static CompositeType createFeatureConfigElementType() {
+ try {
+ String description = "This type encapsulates Karaf feature config element";
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+
+ itemDescriptions[0] = "The key";
+ itemDescriptions[1] = "The value";
+
+ return new CompositeType("ConfigElement", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build configElement type", e);
+ }
+ }
+
+ private static TabularType createFeatureConfigElementTableType() {
+ try {
+ return new TabularType("ConfigElement", "The table of configurations elements",
+ FEATURE_CONFIG_ELEMENT, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT_KEY});
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build feature table type", e);
+ }
+ }
+
+ private static CompositeType createFeatureConfigType() {
+ try {
+ String description = "This type encapsulates Karaf feature config";
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = FEATURE_CONFIG_ELEMENT_TABLE;
+
+ itemDescriptions[0] = "The PID of the config";
+ itemDescriptions[1] = "The configuration elements";
+
+ return new CompositeType("Config", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build configElement type", e);
+ }
+ }
+
+ private static CompositeType createFeatureConfigFilesType() {
+ try {
+ String description = "This type encapsulates Karaf feature config files";
+ String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+
+ itemDescriptions[0] = "The configuration file";
+
+ return new CompositeType("Config", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build configElement type", e);
+ }
+ }
+
+ private static TabularType createFeatureConfigTableType() {
+ try {
+ return new TabularType("Features", "The table of configurations",
+ FEATURE_CONFIG, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_PID});
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build feature table type", e);
+ }
+ }
+
+ private static TabularType createFeatureConfigFilesTableType() {
+ try {
+ return new TabularType("Features", "The table of configuration files",
+ FEATURE_CONFIG_FILES, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_FILES_ELEMENTS });
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build feature table type", e);
+ }
+ }
+
+ private static CompositeType createFeatureType() {
+ try {
+ String description = "This type encapsulates Karaf features";
+ String[] itemNames = FeaturesServiceMBean.FEATURE;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+ itemTypes[2] = FEATURE_IDENTIFIER_TABLE;
+ itemTypes[3] = new ArrayType(1, SimpleType.STRING);
+ itemTypes[4] = FEATURE_CONFIG_TABLE;
+ itemTypes[5] = FEATURE_CONFIG_FILES_TABLE;
+ itemTypes[6] = SimpleType.BOOLEAN;
+
+ itemDescriptions[0] = "The name of the feature";
+ itemDescriptions[1] = "The version of the feature";
+ itemDescriptions[2] = "The feature dependencies";
+ itemDescriptions[3] = "The feature bundles";
+ itemDescriptions[4] = "The feature configurations";
+ itemDescriptions[5] = "The feature configuration files";
+ itemDescriptions[6] = "Whether the feature is installed";
+
+ return new CompositeType("Feature", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build feature type", e);
+ }
+ }
+
+ private static TabularType createFeatureTableType() {
+ try {
+ return new TabularType("Features", "The table of all features",
+ FEATURE, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build feature table type", e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
new file mode 100644
index 0000000..81f446b
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.management.codec;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxFeatureEvent {
+
+ public static final CompositeType FEATURE_EVENT;
+
+ private final CompositeData data;
+
+ public JmxFeatureEvent(FeatureEvent event) {
+ try {
+ String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
+ Object[] itemValues = new Object[itemNames.length];
+ itemValues[0] = event.getFeature().getName();
+ itemValues[1] = event.getFeature().getVersion();
+ switch (event.getType()) {
+ case FeatureInstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_INSTALLED; break;
+ case FeatureUninstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_UNINSTALLED; break;
+ default: throw new IllegalStateException("Unsupported event type: " + event.getType());
+ }
+ data = new CompositeDataSupport(FEATURE_EVENT, itemNames, itemValues);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Cannot form feature event open data", e);
+ }
+ }
+
+ public CompositeData asCompositeData() {
+ return data;
+ }
+
+ static {
+ FEATURE_EVENT = createFeatureEventType();
+ }
+
+ private static CompositeType createFeatureEventType() {
+ try {
+ String description = "This type identify a Karaf feature event";
+ String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+ itemTypes[2] = SimpleType.STRING;
+
+ itemDescriptions[0] = "The id of the feature";
+ itemDescriptions[1] = "The version of the feature";
+ itemDescriptions[2] = "The type of the event";
+
+ return new CompositeType("FeatureEvent", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build featureEvent type", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
new file mode 100644
index 0000000..fee1ab2
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.management.codec;
+
+import java.util.Collection;
+import java.util.Arrays;
+import java.net.URI;
+import java.util.List;
+
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.TabularType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.CompositeDataSupport;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxRepository {
+
+ public final static CompositeType REPOSITORY;
+
+ public final static TabularType REPOSITORY_TABLE;
+
+ private final CompositeData data;
+
+ public JmxRepository(Repository repository) {
+ try {
+ String[] itemNames = FeaturesServiceMBean.REPOSITORY;
+ Object[] itemValues = new Object[itemNames.length];
+ itemValues[0] = repository.getName();
+ itemValues[1] = repository.getURI().toString();
+ itemValues[2] = toStringArray(repository.getRepositories());
+ itemValues[3] = getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
+ data = new CompositeDataSupport(REPOSITORY, itemNames, itemValues);
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot form repository open data", e);
+ }
+ }
+
+ public CompositeData asCompositeData() {
+ return data;
+ }
+
+ public static TabularData tableFrom(Collection<JmxRepository> repositories) {
+ TabularDataSupport table = new TabularDataSupport(REPOSITORY_TABLE);
+ for (JmxRepository repository : repositories) {
+ table.put(repository.asCompositeData());
+ }
+ return table;
+ }
+
+ private static String[] toStringArray(URI[] uris) {
+ if (uris == null) {
+ return null;
+ }
+ String[] res = new String[uris.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = uris[i].toString();
+ }
+ return res;
+ }
+
+ static TabularData getFeatureIdentifierTable(List<Feature> features) throws OpenDataException {
+ TabularDataSupport table = new TabularDataSupport(JmxFeature.FEATURE_IDENTIFIER_TABLE);
+ for (Feature feature : features) {
+ String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
+ Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
+ CompositeData ident = new CompositeDataSupport(JmxFeature.FEATURE_IDENTIFIER, itemNames, itemValues);
+ table.put(ident);
+ }
+ return table;
+ }
+
+ static {
+ REPOSITORY = createRepositoryType();
+ REPOSITORY_TABLE = createRepositoryTableType();
+ }
+
+ private static CompositeType createRepositoryType() {
+ try {
+ String description = "This type identify a Karaf repository";
+ String[] itemNames = FeaturesServiceMBean.REPOSITORY;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+ itemTypes[2] = new ArrayType(1, SimpleType.STRING);
+ itemTypes[3] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
+
+ itemDescriptions[0] = "The name of the repository";
+ itemDescriptions[1] = "The uri of the repository";
+ itemDescriptions[2] = "The dependent repositories";
+ itemDescriptions[3] = "The list of included features";
+
+ return new CompositeType("Repository", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build repository type", e);
+ }
+ }
+
+ private static TabularType createRepositoryTableType() {
+ try {
+ return new TabularType("Features", "The table of repositories",
+ REPOSITORY, new String[] { FeaturesServiceMBean.REPOSITORY_URI });
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build repository table type", e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
new file mode 100644
index 0000000..e00e85d
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.management.codec;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.apache.karaf.features.RepositoryEvent;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxRepositoryEvent {
+
+ public static final CompositeType REPOSITORY_EVENT;
+
+ private final CompositeData data;
+
+ public JmxRepositoryEvent(RepositoryEvent event) {
+ try {
+ String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
+ Object[] itemValues = new Object[itemNames.length];
+ itemValues[0] = event.getRepository().getURI().toString();
+ switch (event.getType()) {
+ case RepositoryAdded: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_ADDED; break;
+ case RepositoryRemoved: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_REMOVED; break;
+ default: throw new IllegalStateException("Unsupported event type: " + event.getType());
+ }
+ data = new CompositeDataSupport(REPOSITORY_EVENT, itemNames, itemValues);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Cannot form repository event open data", e);
+ }
+ }
+
+ public CompositeData asCompositeData() {
+ return data;
+ }
+
+ static {
+ REPOSITORY_EVENT = createRepositoryEventType();
+ }
+
+ private static CompositeType createRepositoryEventType() {
+ try {
+ String description = "This type identify a Karaf repository event";
+ String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
+ OpenType[] itemTypes = new OpenType[itemNames.length];
+ String[] itemDescriptions = new String[itemNames.length];
+ itemTypes[0] = SimpleType.STRING;
+ itemTypes[1] = SimpleType.STRING;
+
+ itemDescriptions[0] = "The uri of the repository";
+ itemDescriptions[1] = "The type of event";
+
+ return new CompositeType("RepositoryEvent", description, itemNames,
+ itemDescriptions, itemTypes);
+ } catch (OpenDataException e) {
+ throw new IllegalStateException("Unable to build repositoryEvent type", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/OSGI-INF/bundle.info b/features/core/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..d5b4180
--- /dev/null
+++ b/features/core/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,20 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the Karaf features support.
+
+Karaf provides a simple, yet flexible, way to provision applications or "features". Such a mechanism is mainly
+provided by a set of commands available in the features shell. The provisioning system uses xml "repositories"
+that define a set of features.
+
+h1. See also
+
+Provisioning - section of the Karaf User Guide
[32/33] git commit: Revert "[KARAF-2852] Merge features/core and
features/command"
Posted by gn...@apache.org.
Revert "[KARAF-2852] Merge features/core and features/command"
This reverts commit 999f4970fecd3710da36b709f2d484cd0db38d09.
We actually need to split the commands from the core service
in order to avoid a refresh when the shell is installed.
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/0c8e8a81
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/0c8e8a81
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/0c8e8a81
Branch: refs/heads/master
Commit: 0c8e8a81e9d8103013f986604c5e840fe32cef5a
Parents: f2669e1
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 19:01:02 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:04 2014 +0200
----------------------------------------------------------------------
assemblies/apache-karaf/pom.xml | 2 +-
.../standard/src/main/feature/feature.xml | 1 +
features/command/NOTICE | 71 +
features/command/pom.xml | 90 ++
.../command/FeaturesCommandSupport.java | 42 +
.../features/command/InfoFeatureCommand.java | 290 ++++
.../features/command/InstallFeatureCommand.java | 69 +
.../command/ListFeatureVersionsCommand.java | 62 +
.../features/command/ListFeaturesCommand.java | 106 ++
.../karaf/features/command/RepoAddCommand.java | 54 +
.../karaf/features/command/RepoListCommand.java | 73 +
.../features/command/RepoRefreshCommand.java | 65 +
.../features/command/RepoRemoveCommand.java | 56 +
.../command/UninstallFeatureCommand.java | 62 +
.../command/completers/AllFeatureCompleter.java | 33 +
.../completers/AvailableFeatureCompleter.java | 33 +
.../completers/AvailableRepoNameCompleter.java | 48 +
.../completers/FeatureCompleterSupport.java | 65 +
.../completers/InstalledRepoNameCompleter.java | 58 +
.../completers/InstalledRepoUriCompleter.java | 59 +
.../completers/RequiredFeatureCompleter.java | 33 +
.../src/main/resources/OSGI-INF/bundle.info | 30 +
features/core/NOTICE | 71 +
features/core/pom.xml | 141 ++
.../org/apache/karaf/features/BootFinished.java | 24 +
.../org/apache/karaf/features/BundleInfo.java | 32 +
.../org/apache/karaf/features/Capability.java | 23 +
.../org/apache/karaf/features/Conditional.java | 35 +
.../apache/karaf/features/ConfigFileInfo.java | 27 +
.../org/apache/karaf/features/Dependency.java | 29 +
.../apache/karaf/features/EventConstants.java | 46 +
.../java/org/apache/karaf/features/Feature.java | 63 +
.../org/apache/karaf/features/FeatureEvent.java | 50 +
.../apache/karaf/features/FeaturesListener.java | 25 +
.../karaf/features/FeaturesNamespaces.java | 41 +
.../apache/karaf/features/FeaturesService.java | 104 ++
.../karaf/features/RegionsPersistence.java | 26 +
.../org/apache/karaf/features/Repository.java | 37 +
.../apache/karaf/features/RepositoryEvent.java | 50 +
.../org/apache/karaf/features/Requirement.java | 23 +
.../org/apache/karaf/features/Resolver.java | 25 +
.../internal/deployment/DeploymentBuilder.java | 354 +++++
.../internal/deployment/Downloader.java | 35 +
.../internal/deployment/StreamProvider.java | 26 +
.../management/FeaturesServiceMBeanImpl.java | 290 ++++
.../management/StandardEmitterMBean.java | 65 +
.../karaf/features/internal/model/Bundle.java | 198 +++
.../features/internal/model/Capability.java | 91 ++
.../features/internal/model/Conditional.java | 69 +
.../karaf/features/internal/model/Config.java | 110 ++
.../features/internal/model/ConfigFile.java | 136 ++
.../karaf/features/internal/model/Content.java | 199 +++
.../features/internal/model/Dependency.java | 121 ++
.../karaf/features/internal/model/Feature.java | 374 +++++
.../karaf/features/internal/model/Features.java | 155 ++
.../karaf/features/internal/model/JaxbUtil.java | 224 +++
.../features/internal/model/ObjectFactory.java | 111 ++
.../features/internal/model/Requirement.java | 87 ++
.../features/internal/model/package-info.java | 21 +
.../karaf/features/internal/osgi/Activator.java | 208 +++
.../repository/AggregateRepository.java | 55 +
.../internal/repository/BaseRepository.java | 86 ++
.../internal/repository/CacheRepository.java | 59 +
.../repository/HttpMetadataProvider.java | 88 ++
.../internal/repository/MetadataProvider.java | 29 +
.../internal/repository/MetadataRepository.java | 43 +
.../internal/repository/StaticRepository.java | 33 +
.../features/internal/resolver/BaseClause.java | 114 ++
.../internal/resolver/CandidateComparator.java | 129 ++
.../internal/resolver/CapabilityImpl.java | 165 ++
.../internal/resolver/CapabilitySet.java | 612 ++++++++
.../internal/resolver/FeatureNamespace.java | 72 +
.../internal/resolver/FeatureResource.java | 133 ++
.../internal/resolver/IdentityCapability.java | 63 +
.../internal/resolver/RequirementImpl.java | 80 +
.../internal/resolver/ResolveContextImpl.java | 102 ++
.../internal/resolver/ResourceBuilder.java | 1129 ++++++++++++++
.../internal/resolver/ResourceImpl.java | 110 ++
.../internal/resolver/ServiceNamespace.java | 30 +
.../internal/resolver/SimpleFilter.java | 649 ++++++++
.../internal/resolver/Slf4jResolverLog.java | 49 +
.../internal/resolver/UriNamespace.java | 47 +
.../features/internal/service/Artifact.java | 56 +
.../internal/service/BootFeaturesInstaller.java | 171 +++
.../internal/service/EventAdminListener.java | 91 ++
.../service/FeatureConfigInstaller.java | 167 +++
.../internal/service/FeatureFinder.java | 68 +
.../internal/service/FeatureValidationUtil.java | 37 +
.../internal/service/FeaturesServiceImpl.java | 1416 ++++++++++++++++++
.../features/internal/service/Overrides.java | 132 ++
.../internal/service/RepositoryImpl.java | 102 ++
.../internal/service/RequirementSort.java | 84 ++
.../internal/service/SimpleDownloader.java | 51 +
.../karaf/features/internal/service/State.java | 34 +
.../features/internal/service/StateStorage.java | 175 +++
.../features/internal/util/ChecksumUtils.java | 56 +
.../features/internal/util/JsonReader.java | 349 +++++
.../features/internal/util/JsonWriter.java | 120 ++
.../karaf/features/internal/util/Macro.java | 142 ++
.../features/internal/util/MultiException.java | 95 ++
.../management/FeaturesServiceMBean.java | 142 ++
.../features/management/codec/JmxFeature.java | 323 ++++
.../management/codec/JmxFeatureEvent.java | 80 +
.../management/codec/JmxRepository.java | 132 ++
.../management/codec/JmxRepositoryEvent.java | 77 +
.../src/main/resources/OSGI-INF/bundle.info | 20 +
.../karaf/features/karaf-features-1.0.0.xsd | 239 +++
.../karaf/features/karaf-features-1.1.0.xsd | 237 +++
.../karaf/features/karaf-features-1.2.0.xsd | 254 ++++
.../karaf/features/karaf-features-1.3.0.xsd | 280 ++++
.../apache/karaf/features/ConditionalTest.java | 54 +
.../org/apache/karaf/features/FeatureTest.java | 32 +
.../karaf/features/FeaturesServiceTest.java | 430 ++++++
.../apache/karaf/features/RepositoryTest.java | 140 ++
.../org/apache/karaf/features/TestBase.java | 105 ++
.../service/BootFeaturesInstallerTest.java | 93 ++
.../internal/service/BundleManagerTest.java | 64 +
.../service/FeaturesServiceImplTest.java | 167 +++
.../service/FeaturesValidationTest.java | 102 ++
.../internal/service/OverridesTest.java | 208 +++
.../karaf/features/internal/service/f01.xml | 92 ++
.../karaf/features/internal/service/f02.xml | 164 ++
.../karaf/features/internal/service/f03.xml | 27 +
.../karaf/features/internal/service/f04.xml | 28 +
.../karaf/features/internal/service/f05.xml | 28 +
.../karaf/features/internal/service/f06.xml | 36 +
.../karaf/features/internal/service/f07.xml | 35 +
.../internal/service/overrides.properties | 23 +
.../karaf/features/internal/service/repo2.xml | 41 +
.../org/apache/karaf/features/repo1.xml | 35 +
.../org/apache/karaf/features/repo2.xml | 37 +
.../org/apache/karaf/features/repo3.xml | 27 +
features/pom.xml | 127 +-
.../org/apache/karaf/features/BootFinished.java | 24 -
.../org/apache/karaf/features/BundleInfo.java | 32 -
.../org/apache/karaf/features/Capability.java | 23 -
.../org/apache/karaf/features/Conditional.java | 35 -
.../apache/karaf/features/ConfigFileInfo.java | 27 -
.../org/apache/karaf/features/Dependency.java | 29 -
.../apache/karaf/features/EventConstants.java | 46 -
.../java/org/apache/karaf/features/Feature.java | 63 -
.../org/apache/karaf/features/FeatureEvent.java | 50 -
.../apache/karaf/features/FeaturesListener.java | 25 -
.../karaf/features/FeaturesNamespaces.java | 41 -
.../apache/karaf/features/FeaturesService.java | 104 --
.../karaf/features/RegionsPersistence.java | 26 -
.../org/apache/karaf/features/Repository.java | 37 -
.../apache/karaf/features/RepositoryEvent.java | 50 -
.../org/apache/karaf/features/Requirement.java | 23 -
.../org/apache/karaf/features/Resolver.java | 25 -
.../command/FeaturesCommandSupport.java | 42 -
.../features/command/InfoFeatureCommand.java | 290 ----
.../features/command/InstallFeatureCommand.java | 69 -
.../command/ListFeatureVersionsCommand.java | 62 -
.../features/command/ListFeaturesCommand.java | 106 --
.../karaf/features/command/RepoAddCommand.java | 54 -
.../karaf/features/command/RepoListCommand.java | 73 -
.../features/command/RepoRefreshCommand.java | 65 -
.../features/command/RepoRemoveCommand.java | 56 -
.../command/UninstallFeatureCommand.java | 62 -
.../command/completers/AllFeatureCompleter.java | 33 -
.../completers/AvailableFeatureCompleter.java | 33 -
.../completers/AvailableRepoNameCompleter.java | 48 -
.../completers/FeatureCompleterSupport.java | 65 -
.../completers/InstalledRepoNameCompleter.java | 58 -
.../completers/InstalledRepoUriCompleter.java | 59 -
.../completers/RequiredFeatureCompleter.java | 33 -
.../internal/deployment/DeploymentBuilder.java | 354 -----
.../internal/deployment/Downloader.java | 35 -
.../internal/deployment/StreamProvider.java | 26 -
.../management/FeaturesServiceMBeanImpl.java | 290 ----
.../management/StandardEmitterMBean.java | 65 -
.../karaf/features/internal/model/Bundle.java | 198 ---
.../features/internal/model/Capability.java | 89 --
.../features/internal/model/Conditional.java | 69 -
.../karaf/features/internal/model/Config.java | 110 --
.../features/internal/model/ConfigFile.java | 136 --
.../karaf/features/internal/model/Content.java | 199 ---
.../features/internal/model/Dependency.java | 121 --
.../karaf/features/internal/model/Feature.java | 374 -----
.../karaf/features/internal/model/Features.java | 155 --
.../karaf/features/internal/model/JaxbUtil.java | 224 ---
.../features/internal/model/ObjectFactory.java | 111 --
.../features/internal/model/Requirement.java | 87 --
.../features/internal/model/package-info.java | 21 -
.../karaf/features/internal/osgi/Activator.java | 208 ---
.../repository/AggregateRepository.java | 55 -
.../internal/repository/BaseRepository.java | 86 --
.../internal/repository/CacheRepository.java | 59 -
.../repository/HttpMetadataProvider.java | 88 --
.../internal/repository/MetadataProvider.java | 29 -
.../internal/repository/MetadataRepository.java | 43 -
.../internal/repository/StaticRepository.java | 33 -
.../features/internal/resolver/BaseClause.java | 114 --
.../internal/resolver/CandidateComparator.java | 129 --
.../internal/resolver/CapabilityImpl.java | 165 --
.../internal/resolver/CapabilitySet.java | 612 --------
.../internal/resolver/FeatureNamespace.java | 72 -
.../internal/resolver/FeatureResource.java | 133 --
.../internal/resolver/IdentityCapability.java | 63 -
.../internal/resolver/RequirementImpl.java | 80 -
.../internal/resolver/ResolveContextImpl.java | 102 --
.../internal/resolver/ResourceBuilder.java | 1129 --------------
.../internal/resolver/ResourceImpl.java | 110 --
.../internal/resolver/ServiceNamespace.java | 30 -
.../internal/resolver/SimpleFilter.java | 649 --------
.../internal/resolver/Slf4jResolverLog.java | 49 -
.../internal/resolver/UriNamespace.java | 47 -
.../features/internal/service/Artifact.java | 56 -
.../internal/service/BootFeaturesInstaller.java | 170 ---
.../internal/service/EventAdminListener.java | 91 --
.../service/FeatureConfigInstaller.java | 167 ---
.../internal/service/FeatureFinder.java | 68 -
.../internal/service/FeatureValidationUtil.java | 37 -
.../internal/service/FeaturesServiceImpl.java | 1416 ------------------
.../features/internal/service/Overrides.java | 132 --
.../internal/service/RepositoryImpl.java | 102 --
.../internal/service/RequirementSort.java | 84 --
.../internal/service/SimpleDownloader.java | 51 -
.../karaf/features/internal/service/State.java | 34 -
.../features/internal/service/StateStorage.java | 174 ---
.../features/internal/util/ChecksumUtils.java | 56 -
.../features/internal/util/JsonReader.java | 349 -----
.../features/internal/util/JsonWriter.java | 120 --
.../karaf/features/internal/util/Macro.java | 142 --
.../features/internal/util/MultiException.java | 95 --
.../management/FeaturesServiceMBean.java | 142 --
.../features/management/codec/JmxFeature.java | 323 ----
.../management/codec/JmxFeatureEvent.java | 80 -
.../management/codec/JmxRepository.java | 132 --
.../management/codec/JmxRepositoryEvent.java | 77 -
.../src/main/resources/OSGI-INF/bundle.info | 20 -
.../karaf/features/karaf-features-1.0.0.xsd | 239 ---
.../karaf/features/karaf-features-1.1.0.xsd | 237 ---
.../karaf/features/karaf-features-1.2.0.xsd | 254 ----
.../karaf/features/karaf-features-1.3.0.xsd | 280 ----
.../apache/karaf/features/ConditionalTest.java | 54 -
.../org/apache/karaf/features/FeatureTest.java | 32 -
.../karaf/features/FeaturesServiceTest.java | 429 ------
.../apache/karaf/features/RepositoryTest.java | 140 --
.../org/apache/karaf/features/TestBase.java | 105 --
.../service/BootFeaturesInstallerTest.java | 93 --
.../internal/service/BundleManagerTest.java | 64 -
.../service/FeaturesServiceImplTest.java | 167 ---
.../service/FeaturesValidationTest.java | 102 --
.../internal/service/OverridesTest.java | 202 ---
.../karaf/features/internal/service/f01.xml | 92 --
.../karaf/features/internal/service/f02.xml | 164 --
.../karaf/features/internal/service/f03.xml | 27 -
.../karaf/features/internal/service/f04.xml | 28 -
.../karaf/features/internal/service/f05.xml | 28 -
.../karaf/features/internal/service/f06.xml | 36 -
.../karaf/features/internal/service/f07.xml | 35 -
.../internal/service/overrides.properties | 23 -
.../karaf/features/internal/service/repo2.xml | 41 -
.../org/apache/karaf/features/repo1.xml | 35 -
.../org/apache/karaf/features/repo2.xml | 37 -
.../org/apache/karaf/features/repo3.xml | 27 -
instance/pom.xml | 2 +-
kar/pom.xml | 2 +-
pom.xml | 5 +
261 files changed, 16137 insertions(+), 15828 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/assemblies/apache-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/pom.xml b/assemblies/apache-karaf/pom.xml
index ce631b8..a799b0a 100644
--- a/assemblies/apache-karaf/pom.xml
+++ b/assemblies/apache-karaf/pom.xml
@@ -161,8 +161,8 @@
</installedFeatures>
<bootFeatures>
<feature>aries-blueprint</feature>
- <feature>shell-compat</feature>
<feature>shell</feature>
+ <feature>shell-compat</feature>
<feature>jaas</feature>
<feature>ssh</feature>
<feature>management</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 86f8270..5e3fd11 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -73,6 +73,7 @@
<bundle dependency="true" start-level="30">mvn:org.jledit/core/${jledit.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.core/${project.version}</bundle>
<bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
+ <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.command/${project.version}</bundle>
</feature>
<feature name="shell-compat" description="Karaf Shell Compatibility" version="${project.version}">
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/NOTICE
----------------------------------------------------------------------
diff --git a/features/command/NOTICE b/features/command/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/features/command/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/pom.xml
----------------------------------------------------------------------
diff --git a/features/command/pom.xml b/features/command/pom.xml
new file mode 100644
index 0000000..4f49bb1
--- /dev/null
+++ b/features/command/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>features</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.karaf.features.command</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Features :: Command</name>
+ <description>This bundle provides the Karaf shell commands to manipulate features.</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>org.apache.karaf.features.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Karaf-Commands>org.apache.karaf.features.command.*</Karaf-Commands>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java b/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
new file mode 100644
index 0000000..076650d
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+
+public abstract class FeaturesCommandSupport implements Action {
+
+ @Reference
+ private FeaturesService featuresService;
+
+ @Override
+ public Object execute() throws Exception {
+ if (featuresService == null) {
+ throw new IllegalStateException("FeaturesService not found");
+ }
+ doExecute(featuresService);
+ return null;
+ }
+
+ protected abstract void doExecute(FeaturesService admin) throws Exception;
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
new file mode 100644
index 0000000..5ad855c
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AllFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
+@Service
+public class InfoFeatureCommand extends FeaturesCommandSupport {
+
+ private static final String INDENT = " ";
+ private static final String FEATURE_CONTENT = "Feature";
+ private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
+
+ @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
+ @Completion(AllFeatureCompleter.class)
+ private String name;
+
+ @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
+ private String version;
+
+ @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false)
+ private boolean config;
+
+ @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false)
+ private boolean dependency;
+
+ @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
+ private boolean bundle;
+
+ @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
+ private boolean conditional;
+
+ @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
+ private boolean tree;
+
+ protected void doExecute(FeaturesService admin) throws Exception {
+ Feature feature = null;
+
+ if (version != null && version.length() > 0) {
+ feature = admin.getFeature(name, version);
+ } else {
+ feature = admin.getFeature(name);
+ }
+
+ if (feature == null) {
+ System.out.println("Feature not found");
+ return;
+ }
+
+ // default behavior
+ if (!config && !dependency && !bundle && !conditional) {
+ config = true;
+ dependency = true;
+ bundle = true;
+ conditional = true;
+ }
+
+ System.out.println("Feature " + feature.getName() + " " + feature.getVersion());
+ if (feature.getDescription() != null) {
+ System.out.println("Description:");
+ System.out.println(INDENT + feature.getDescription());
+ }
+
+ if(feature.getDetails() != null) {
+ System.out.println("Details:");
+ printWithIndent(feature.getDetails());
+ }
+
+ if (config) {
+ displayConfigInformation(feature, FEATURE_CONTENT);
+ displayConfigFileInformation(feature, FEATURE_CONTENT);
+ }
+
+ if (dependency) {
+ displayDependencyInformation(feature, FEATURE_CONTENT);
+ }
+
+ if (bundle) {
+ displayBundleInformation(feature, FEATURE_CONTENT);
+ }
+
+ if(conditional) {
+ displayConditionalInfo(feature);
+ }
+
+ if (tree) {
+ if (config || dependency || bundle) {
+ System.out.println("\nFeature tree");
+ }
+
+ int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
+ if (unresolved > 0) {
+ System.out.println("Tree contains " + unresolved + " unresolved dependencies");
+ System.out.println(" * means that node declares dependency but the dependent feature is not available.");
+ }
+ }
+ }
+
+ private void printWithIndent(String details) {
+ String[] lines = details.split("\r?\n");
+ for (String line : lines) {
+ System.out.println(INDENT + line);
+ }
+ }
+
+ private void displayBundleInformation(Feature feature, String contentType) {
+ List<BundleInfo> bundleInfos = feature.getBundles();
+ if (bundleInfos.isEmpty()) {
+ System.out.println(contentType + " has no bundles.");
+ } else {
+ System.out.println(contentType + " contains followed bundles:");
+ for (BundleInfo featureBundle : bundleInfos) {
+ int startLevel = featureBundle.getStartLevel();
+ StringBuilder sb = new StringBuilder();
+ sb.append(INDENT).append(featureBundle.getLocation());
+ if(startLevel > 0) {
+ sb.append(" start-level=").append(startLevel);
+ }
+ System.out.println(sb.toString());
+ }
+ }
+ }
+
+ private void displayDependencyInformation(Feature feature, String contentType) {
+ List<Dependency> dependencies = feature.getDependencies();
+ if (dependencies.isEmpty()) {
+ System.out.println(contentType + " has no dependencies.");
+ } else {
+ System.out.println(contentType + " depends on:");
+ for (Dependency featureDependency : dependencies) {
+ System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
+ }
+ }
+ }
+
+ private void displayConfigInformation(Feature feature, String contentType) {
+ Map<String, Map<String, String>> configurations = feature.getConfigurations();
+ if (configurations.isEmpty()) {
+ System.out.println(contentType + " has no configuration");
+ } else {
+ System.out.println(contentType + " configuration:");
+ for (String name : configurations.keySet()) {
+ System.out.println(INDENT + name);
+ }
+ }
+ }
+
+ private void displayConfigFileInformation(Feature feature, String contentType) {
+ List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
+ if (configurationFiles.isEmpty()) {
+ System.out.println(contentType + " has no configuration files");
+ } else {
+ System.out.println(contentType + " configuration files: ");
+ for (ConfigFileInfo configFileInfo : configurationFiles) {
+ System.out.println(INDENT + configFileInfo.getFinalname());
+ }
+ }
+ }
+
+ /**
+ * Called originally with featureName and featureVersion that have already been resolved successfully.
+ *
+ * @param admin
+ * @param featureName
+ * @param featureVersion
+ * @param prefix
+ * @return
+ * @throws Exception
+ */
+ private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
+ int unresolved = 0;
+
+ Feature resolved = admin.getFeature(featureName, featureVersion);
+ if (resolved != null) {
+ System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
+ } else {
+ System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
+ unresolved++;
+ }
+
+ if (resolved != null) {
+ if (bundle) {
+ List<String> bundleLocation = new LinkedList<String>();
+ List<BundleInfo> bundles = resolved.getBundles();
+ for (BundleInfo bundleInfo : bundles) {
+ bundleLocation.add(bundleInfo.getLocation());
+ }
+
+ if (conditional) {
+ for (Conditional cond : resolved.getConditional()) {
+ List<String> condition = cond.getCondition();
+ List<BundleInfo> conditionalBundles = cond.getBundles();
+ for (BundleInfo bundleInfo : conditionalBundles) {
+ bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
+ }
+ }
+ }
+ for (int i = 0, j = bundleLocation.size(); i < j; i++) {
+ System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
+ }
+ }
+ prefix += " ";
+ List<Dependency> dependencies = resolved.getDependencies();
+ for (int i = 0, j = dependencies.size(); i < j; i++) {
+ Dependency toDisplay = dependencies.get(i);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+ }
+
+ if (conditional) {
+ for (Conditional cond : resolved.getConditional()) {
+ List<Dependency> conditionDependencies = cond.getDependencies();
+ for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
+ Dependency toDisplay = dependencies.get(i);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+ }
+ }
+ }
+ }
+
+ return unresolved;
+ }
+
+ private void displayConditionalInfo(Feature feature) {
+ List<? extends Conditional> conditionals = feature.getConditional();
+ if (conditionals.isEmpty()) {
+ System.out.println("Feature has no conditionals.");
+ } else {
+ System.out.println("Feature contains followed conditionals:");
+ for (Conditional featureConditional : conditionals) {
+ String conditionDescription = getConditionDescription(featureConditional);
+ Feature wrappedConditional = featureConditional.asFeature(feature.getName(), feature.getVersion());
+ if (config) {
+ displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+
+ if (dependency) {
+ displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+
+ if (bundle) {
+ displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+ }
+ }
+ }
+ }
+
+ private String getConditionDescription(Conditional cond) {
+ StringBuffer sb = new StringBuffer();
+ for (String dep : cond.getCondition()) {
+ if (sb.length() > 0) {
+ sb.append(" ");
+ }
+ sb.append(dep);
+ }
+ return sb.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
new file mode 100644
index 0000000..b7f8184
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AvailableFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "install", description = "Installs a feature with the specified name and version.")
+@Service
+public class InstallFeatureCommand extends FeaturesCommandSupport {
+
+ private static String DEFAULT_VERSION = "0.0.0";
+
+ @Argument(index = 0, name = "feature", description = "The name and version of the features to install. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
+ @Completion(AvailableFeatureCompleter.class)
+ List<String> features;
+
+ @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
+ boolean noRefresh;
+
+ @Option(name = "-s", aliases = "--no-auto-start", description = "Do not start the bundles", required = false, multiValued = false)
+ boolean noStart;
+
+ @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
+ boolean verbose;
+
+ @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
+ boolean simulate;
+
+ protected void doExecute(FeaturesService admin) throws Exception {
+ EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
+ if (simulate) {
+ options.add(FeaturesService.Option.Simulate);
+ }
+ if (noStart) {
+ options.add(FeaturesService.Option.NoAutoStartBundles);
+ }
+ if (noRefresh) {
+ options.add(FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ if (verbose) {
+ options.add(FeaturesService.Option.Verbose);
+ }
+ admin.installFeatures(new HashSet<String>(features), options);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
new file mode 100644
index 0000000..b2c5e42
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.Arrays;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.AllFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "version-list", description = "Lists all versions of a feature available from the currently available repositories.")
+@Service
+public class ListFeatureVersionsCommand extends FeaturesCommandSupport {
+
+ @Argument(index = 0, name = "feature", description = "Name of feature.", required = true, multiValued = false)
+ @Completion(AllFeatureCompleter.class)
+ String feature;
+
+ @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+ boolean noFormat;
+
+ protected void doExecute(FeaturesService admin) throws Exception {
+ ShellTable table = new ShellTable();
+ table.column("Version");
+ table.column("Repository");
+ table.column("Repository URL");
+ table.emptyTableText("No versions available for features '" + feature + "'");
+
+ for (Repository r : Arrays.asList(admin.listRepositories())) {
+ for (Feature f : r.getFeatures()) {
+
+ if (f.getName().equals(feature)) {
+ table.addRow().addContent(f.getVersion(), r.getName(), r.getURI());
+ }
+ }
+ }
+
+ table.print(System.out, !noFormat);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
new file mode 100644
index 0000000..e86ff64
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "list", description = "Lists all existing features available from the defined repositories.")
+@Service
+public class ListFeaturesCommand extends FeaturesCommandSupport {
+
+ @Option(name = "-i", aliases = {"--installed"}, description = "Display a list of all installed features only", required = false, multiValued = false)
+ boolean onlyInstalled;
+
+ @Option(name = "-r", aliases = {"--required"}, description = "Display a list of all required features only", required = false, multiValued = false)
+ boolean onlyRequired;
+
+ @Option(name = "-o", aliases = {"--ordered"}, description = "Display a list using alphabetical order ", required = false, multiValued = false)
+ boolean ordered;
+
+ @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+ boolean noFormat;
+
+ protected void doExecute(FeaturesService featuresService) throws Exception {
+ boolean needsLegend = false;
+
+ ShellTable table = new ShellTable();
+ table.column("Name");
+ table.column("Version");
+ table.column("Required");
+ table.column("Installed");
+ table.column("Repository");
+ table.column("Description").maxSize(50);
+ table.emptyTableText(onlyInstalled ? "No features installed" : "No features available");
+
+ List<Repository> repos = Arrays.asList(featuresService.listRepositories());
+ for (Repository r : repos) {
+ List<Feature> features = Arrays.asList(r.getFeatures());
+ if (ordered) {
+ Collections.sort(features, new FeatureComparator());
+ }
+ for (Feature f : features) {
+ if (onlyInstalled && !featuresService.isInstalled(f)) {
+ // Filter out not installed features if we only want to see the installed ones
+ continue;
+ }
+ if (onlyRequired && !featuresService.isRequired(f)) {
+ // Filter out not installed features if we only want to see the installed ones
+ continue;
+ }
+ table.addRow().addContent(
+ f.getName(),
+ f.getVersion(),
+ featuresService.isRequired(f) ? "x" : "",
+ featuresService.isInstalled(f) ? "x" : "",
+ r.getName(),
+ f.getDescription());
+ if (isInstalledViaDeployDir(r.getName())) {
+ needsLegend = true;
+ }
+ }
+ }
+
+ table.print(System.out, !noFormat);
+
+ if (needsLegend) {
+ System.out.println("* Installed via deploy directory");
+ }
+
+ }
+
+ private boolean isInstalledViaDeployDir(String st) {
+ return (st == null || st.length() <= 1) ? false : (st.charAt(st.length() - 1) == '*');
+ }
+
+ class FeatureComparator implements Comparator<Feature> {
+ public int compare(Feature o1, Feature o2) {
+ return o1.getName().toLowerCase().compareTo( o2.getName().toLowerCase() );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
new file mode 100644
index 0000000..16faf42
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.net.URI;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AvailableRepoNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "repo-add", description = "Add a features repository")
+@Service
+public class RepoAddCommand extends FeaturesCommandSupport {
+
+ @Argument(index = 0, name = "name/url", description = "Shortcut name of the features repository or the full URL", required = true, multiValued = false)
+ @Completion(AvailableRepoNameCompleter.class)
+ private String nameOrUrl;
+
+ @Argument(index = 1, name = "version", description = "The version of the features repository if using features repository name as first argument. It should be empty if using the URL", required = false, multiValued = false)
+ private String version;
+
+ @Option(name = "-i", aliases = { "--install" }, description = "Install all features contained in the features repository", required = false, multiValued = false)
+ private boolean install;
+
+ @Override
+ protected void doExecute(FeaturesService featuresService) throws Exception {
+ String effectiveVersion = (version == null) ? "LATEST" : version;
+ URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
+ if (uri == null) {
+ uri = new URI(nameOrUrl);
+ }
+ System.out.println("Adding feature url " + uri);
+ featuresService.addRepository(uri, install);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
new file mode 100644
index 0000000..55acf79
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.MultiException;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "repo-list", description = "Displays a list of all defined repositories.")
+@Service
+public class RepoListCommand extends FeaturesCommandSupport {
+
+ @Option(name="-r", description="Reload all feature urls", required = false, multiValued = false)
+ boolean reload;
+
+ @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+ boolean noFormat;
+
+ protected void doExecute(FeaturesService featuresService) throws Exception {
+ if (reload) {
+ reloadAllRepos(featuresService);
+ }
+
+ ShellTable table = new ShellTable();
+ table.column("Repository");
+ table.column("URL");
+ table.emptyTableText("No repositories available");
+
+ Repository[] repos = featuresService.listRepositories();
+ for (Repository repo : repos) {
+ if (repo != null) {
+ table.addRow().addContent(repo.getName(), repo.getURI().toString());
+ }
+ }
+ table.print(System.out, !noFormat);
+ }
+
+ private void reloadAllRepos(FeaturesService featuresService) throws Exception {
+ System.out.println("Reloading all repositories from their urls");
+ System.out.println();
+ List<Exception> exceptions = new ArrayList<Exception>();
+ for (Repository repo : featuresService.listRepositories()) {
+ try {
+ featuresService.addRepository(repo.getURI());
+ } catch (Exception e) {
+ exceptions.add(e);
+ }
+ }
+ MultiException.throwIf("Unable to reload repositories", exceptions);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
new file mode 100644
index 0000000..8c7ed79
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+
+@Command(scope = "feature", name = "repo-refresh", description = "Refresh a features repository")
+public class RepoRefreshCommand extends FeaturesCommandSupport {
+ @Argument(index = 0, name = "Feature name or uri", description = "Shortcut name of the feature repository or the full URI", required = false, multiValued = false)
+ @Completion(InstalledRepoUriCompleter.class)
+ private String nameOrUrl;
+
+ @Argument(index = 1, name = "Feature version", description = "The version of the feature if using the feature name. Should be empty if using the uri", required = false, multiValued = false)
+ private String version;
+
+ @Override
+ protected void doExecute(FeaturesService featuresService) throws Exception {
+ List<URI> uris = new ArrayList<URI>();
+ if (nameOrUrl != null) {
+ String effectiveVersion = (version == null) ? "LATEST" : version;
+ URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
+ if (uri == null) {
+ uri = new URI(nameOrUrl);
+ }
+ uris.add(uri);
+ } else {
+ Repository[] repos = featuresService.listRepositories();
+ for (Repository repo : repos) {
+ uris.add(repo.getURI());
+ }
+ }
+ for (URI uri : uris) {
+ try {
+ System.out.println("Refreshing feature url " + uri);
+ featuresService.refreshRepository(uri);
+ } catch (Exception e) {
+ System.err.println("Error refreshing " + uri.toString() + ": " + e.getMessage());
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
new file mode 100644
index 0000000..0710b72
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.net.URI;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "repo-remove", description = "Removes the specified repository features service.")
+@Service
+public class RepoRemoveCommand extends FeaturesCommandSupport {
+
+ @Argument(index = 0, name = "repository", description = "Name or url of the repository to remove.", required = true, multiValued = false)
+ @Completion(InstalledRepoNameCompleter.class)
+ private String repository;
+
+ @Option(name = "-u", aliases = { "--uninstall-all" }, description = "Uninstall all features from the repository", required = false, multiValued = false)
+ private boolean uninstall;
+
+ protected void doExecute(FeaturesService featuresService) throws Exception {
+ URI uri = null;
+ for (Repository r : featuresService.listRepositories()) {
+ if (r.getName() != null && r.getName().equals(repository)) {
+ uri = r.getURI();
+ break;
+ }
+ }
+
+ if (uri == null) {
+ uri = new URI(repository);
+ }
+
+ featuresService.removeRepository(uri, uninstall);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
new file mode 100644
index 0000000..e62f697
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.RequiredFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "uninstall", description = "Uninstalls a feature with the specified name and version.")
+@Service
+public class UninstallFeatureCommand extends FeaturesCommandSupport {
+
+ @Argument(index = 0, name = "features", description = "The name and version of the features to uninstall. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
+ @Completion(RequiredFeatureCompleter.class)
+ List<String> features;
+
+ @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
+ boolean noRefresh;
+
+ @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
+ boolean verbose;
+
+ @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
+ boolean simulate;
+
+ protected void doExecute(FeaturesService admin) throws Exception {
+ // iterate in the provided feature
+ EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
+ if (simulate) {
+ options.add(FeaturesService.Option.Simulate);
+ }
+ if (noRefresh) {
+ options.add(FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ if (verbose) {
+ options.add(FeaturesService.Option.Verbose);
+ }
+ admin.uninstallFeatures(new HashSet<String>(features), options);
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
new file mode 100644
index 0000000..7444b95
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for available features.
+ */
+@Service
+public class AllFeatureCompleter extends FeatureCompleterSupport {
+
+ @Override
+ protected boolean acceptsFeature(Feature feature) {
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
new file mode 100644
index 0000000..79cd280
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for features not installed yet.
+ */
+@Service
+public class AvailableFeatureCompleter extends FeatureCompleterSupport {
+
+ @Override
+ protected boolean acceptsFeature(Feature feature) {
+ return !featuresService.isInstalled(feature);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
new file mode 100644
index 0000000..acefe77
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Shows the list of feature repos that can be installed with their short name
+ */
+@Service
+public class AvailableRepoNameCompleter implements Completer {
+
+ @Reference
+ private FeaturesService featuresService;
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public int complete(Session session, CommandLine commandLine, final List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter(Arrays.asList(featuresService.getRepositoryNames()));
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
new file mode 100644
index 0000000..d01e5af
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Base completer for feature commands.
+ */
+public abstract class FeatureCompleterSupport implements Completer {
+
+ /**
+ * Feature service.
+ */
+ @Reference
+ protected FeaturesService featuresService;
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (Feature feature : featuresService.listFeatures()) {
+ if (acceptsFeature(feature)) {
+ delegate.getStrings().add(feature.getName());
+ }
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ /**
+ * Method for filtering features.
+ *
+ * @param feature The feature.
+ * @return True if feature should be available in completer.
+ */
+ protected abstract boolean acceptsFeature(Feature feature);
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
new file mode 100644
index 0000000..94e4cf7
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * {@link Completer} for Feature Repository URLs.
+ *
+ * Displays a list of currently installed Feature repositories.
+ *
+ */
+@Service
+public class InstalledRepoNameCompleter implements Completer {
+
+ @Reference
+ private FeaturesService featuresService;
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (Repository repository : featuresService.listRepositories()) {
+ delegate.getStrings().add(repository.getName());
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
new file mode 100644
index 0000000..7a760c2
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * {@link Completer} for Feature Repository URLs.
+ *
+ * Displays a list of currently installed Feature repositories.
+ *
+ */
+
+@Service
+public class InstalledRepoUriCompleter implements Completer {
+
+ @Reference
+ private FeaturesService featuresService;
+
+ public void setFeaturesService(FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (Repository repository : featuresService.listRepositories()) {
+ delegate.getStrings().add(repository.getURI().toString());
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
new file mode 100644
index 0000000..a51f75f
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for installed features.
+ */
+@Service
+public class RequiredFeatureCompleter extends FeatureCompleterSupport {
+
+ @Override
+ protected boolean acceptsFeature(Feature feature) {
+ return featuresService.isRequired(feature);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/command/src/main/resources/OSGI-INF/bundle.info b/features/command/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..8f0598b
--- /dev/null
+++ b/features/command/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,30 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides the Karaf shell commands to manipulate features.
+
+The following commands are available:
+
+* features:addUrl - Adds a list of repository URLs to the features service.
+* features:info- Shows information about selected information.
+* features:install- Installs a feature with the specified name and version.
+* features:list - Lists all existing features available from the defined repositories.
+* features:listVersions- Lists all versions of a feature available from the currently available repositories.
+* features:listRepositories- Displays a list of all defined repositories.
+* features:listUrl- Displays a list of all defined repository URLs.
+* features:refreshUrl- Reloads the list of available features from the repositories.
+* features:removeRepository- Removes the specified repository features service.
+* features:removeUrl- Removes the given list of repository URLs from the features service.
+* features:uninstall- Uninstalls a feature with the specified name and version.
+
+h1. See also
+
+Commands- and Provisioning- sections of the Karaf User Guide.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/NOTICE
----------------------------------------------------------------------
diff --git a/features/core/NOTICE b/features/core/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/features/core/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License
[08/33] git commit: [KARAF-2852] Merge jms/core and jms/command
Posted by gn...@apache.org.
[KARAF-2852] Merge jms/core and jms/command
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/0f53437c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/0f53437c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/0f53437c
Branch: refs/heads/master
Commit: 0f53437c5c7d7370ceeb2e075f340f3d647bc5a7
Parents: 53996d9
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 08:21:15 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:02 2014 +0200
----------------------------------------------------------------------
.../enterprise/src/main/feature/feature.xml | 1 -
jms/NOTICE | 71 +++++
jms/command/NOTICE | 71 -----
jms/command/pom.xml | 86 ------
.../apache/karaf/jms/command/BrowseCommand.java | 104 -------
.../jms/command/ConnectionFactoriesCommand.java | 45 ---
.../karaf/jms/command/ConsumeCommand.java | 40 ---
.../apache/karaf/jms/command/CountCommand.java | 41 ---
.../apache/karaf/jms/command/CreateCommand.java | 46 ---
.../apache/karaf/jms/command/DeleteCommand.java | 40 ---
.../apache/karaf/jms/command/InfoCommand.java | 46 ---
.../karaf/jms/command/JmsCommandSupport.java | 36 ---
.../command/JmsConnectionCommandSupport.java | 39 ---
.../apache/karaf/jms/command/MoveCommand.java | 44 ---
.../apache/karaf/jms/command/QueuesCommand.java | 43 ---
.../apache/karaf/jms/command/SendCommand.java | 44 ---
.../apache/karaf/jms/command/TopicsCommand.java | 43 ---
.../ConnectionFactoriesFileNameCompleter.java | 59 ----
.../ConnectionFactoriesNameCompleter.java | 59 ----
.../src/main/resources/OSGI-INF/bundle.info | 29 --
jms/core/NOTICE | 71 -----
jms/core/pom.xml | 102 -------
.../java/org/apache/karaf/jms/JmsMBean.java | 153 ----------
.../java/org/apache/karaf/jms/JmsMessage.java | 164 ----------
.../java/org/apache/karaf/jms/JmsService.java | 159 ----------
.../apache/karaf/jms/internal/JmsConnector.java | 99 ------
.../apache/karaf/jms/internal/JmsMBeanImpl.java | 155 ----------
.../karaf/jms/internal/JmsServiceImpl.java | 300 -------------------
.../resources/OSGI-INF/blueprint/jms-core.xml | 41 ---
.../src/main/resources/OSGI-INF/bundle.info | 18 --
.../jms/internal/connectionfactory-activemq.xml | 44 ---
.../internal/connectionfactory-webspheremq.xml | 36 ---
jms/pom.xml | 86 +++++-
.../java/org/apache/karaf/jms/JmsMBean.java | 153 ++++++++++
.../java/org/apache/karaf/jms/JmsMessage.java | 164 ++++++++++
.../java/org/apache/karaf/jms/JmsService.java | 159 ++++++++++
.../apache/karaf/jms/command/BrowseCommand.java | 104 +++++++
.../jms/command/ConnectionFactoriesCommand.java | 45 +++
.../karaf/jms/command/ConsumeCommand.java | 40 +++
.../apache/karaf/jms/command/CountCommand.java | 41 +++
.../apache/karaf/jms/command/CreateCommand.java | 46 +++
.../apache/karaf/jms/command/DeleteCommand.java | 40 +++
.../apache/karaf/jms/command/InfoCommand.java | 46 +++
.../karaf/jms/command/JmsCommandSupport.java | 36 +++
.../command/JmsConnectionCommandSupport.java | 39 +++
.../apache/karaf/jms/command/MoveCommand.java | 44 +++
.../apache/karaf/jms/command/QueuesCommand.java | 43 +++
.../apache/karaf/jms/command/SendCommand.java | 44 +++
.../apache/karaf/jms/command/TopicsCommand.java | 43 +++
.../ConnectionFactoriesFileNameCompleter.java | 59 ++++
.../ConnectionFactoriesNameCompleter.java | 59 ++++
.../apache/karaf/jms/internal/JmsConnector.java | 99 ++++++
.../apache/karaf/jms/internal/JmsMBeanImpl.java | 155 ++++++++++
.../karaf/jms/internal/JmsServiceImpl.java | 300 +++++++++++++++++++
.../resources/OSGI-INF/blueprint/jms-core.xml | 41 +++
jms/src/main/resources/OSGI-INF/bundle.info | 18 ++
.../jms/internal/connectionfactory-activemq.xml | 44 +++
.../internal/connectionfactory-webspheremq.xml | 36 +++
58 files changed, 2047 insertions(+), 2266 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/assemblies/features/enterprise/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/feature/feature.xml b/assemblies/features/enterprise/src/main/feature/feature.xml
index 0a57038..c68017f 100644
--- a/assemblies/features/enterprise/src/main/feature/feature.xml
+++ b/assemblies/features/enterprise/src/main/feature/feature.xml
@@ -199,7 +199,6 @@
<feature>aries-blueprint</feature>
<bundle>mvn:org.apache.geronimo.specs/geronimo-jms_1.1_spec/${geronimo.jms-spec.version}</bundle>
<bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.core/${project.version}</bundle>
- <bundle>mvn:org.apache.karaf.jms/org.apache.karaf.jms.command/${project.version}</bundle>
</feature>
<feature name="openwebbeans" description="Apache OpenWebBeans CDI container support" version="${openwebbeans.version}" resolver="(obr)">
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/NOTICE
----------------------------------------------------------------------
diff --git a/jms/NOTICE b/jms/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/jms/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/NOTICE
----------------------------------------------------------------------
diff --git a/jms/command/NOTICE b/jms/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jms/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/pom.xml
----------------------------------------------------------------------
diff --git a/jms/command/pom.xml b/jms/command/pom.xml
deleted file mode 100644
index 55eb54b..0000000
--- a/jms/command/pom.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.jms</groupId>
- <artifactId>jms</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.jms.command</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: JMS :: Command</name>
- <description>This bundle provides shell commands to manipulate the JMS server.</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.jms</groupId>
- <artifactId>org.apache.karaf.jms.core</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.core</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>!*</Export-Package>
- <Karaf-Commands>*</Karaf-Commands>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
deleted file mode 100644
index cb86aa6..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import java.util.List;
-
-import org.apache.karaf.jms.JmsMessage;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "browse", description = "Browse a JMS queue")
-@Service
-public class BrowseCommand extends JmsConnectionCommandSupport {
-
- @Argument(index = 1, name = "queue", description = "The JMS queue to browse", required = true, multiValued = false)
- String queue;
-
- @Option(name = "-s", aliases = { "--selector" }, description = "The selector to select the messages to browse", required = false, multiValued = false)
- String selector;
-
- @Option(name = "-v", aliases = { "--verbose" }, description = "Display JMS properties", required = false, multiValued = false)
- boolean verbose = false;
-
- @Override
- public Object execute() throws Exception {
-
- ShellTable table = new ShellTable();
- table.column("Message ID");
- table.column("Content").maxSize(80);
- table.column("Charset");
- table.column("Type");
- table.column("Correlation ID");
- table.column("Delivery Mode");
- table.column("Destination");
- table.column("Expiration");
- table.column("Priority");
- table.column("Redelivered");
- table.column("ReplyTo");
- table.column("Timestamp");
- if (verbose) {
- table.column("Properties");
- }
-
- List<JmsMessage> messages = getJmsService().browse(connectionFactory, queue, selector, username, password);
- for (JmsMessage message : messages) {
- if (verbose) {
- StringBuilder properties = new StringBuilder();
- for (String property : message.getProperties().keySet()) {
- properties.append(property).append("=").append(message.getProperties().get(property)).append("\n");
- }
- table.addRow().addContent(
- message.getMessageId(),
- message.getContent(),
- message.getCharset(),
- message.getType(),
- message.getCorrelationID(),
- message.getDeliveryMode(),
- message.getDestination(),
- message.getExpiration(),
- message.getPriority(),
- message.isRedelivered(),
- message.getReplyTo(),
- message.getTimestamp(),
- properties.toString());
- } else {
- table.addRow().addContent(
- message.getMessageId(),
- message.getContent(),
- message.getCharset(),
- message.getType(),
- message.getCorrelationID(),
- message.getDeliveryMode(),
- message.getDestination(),
- message.getExpiration(),
- message.getPriority(),
- message.isRedelivered(),
- message.getReplyTo(),
- message.getTimestamp());
- }
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
deleted file mode 100644
index b698336..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "connectionfactories", description = "List the JMS connection factories")
-@Service
-public class ConnectionFactoriesCommand extends JmsCommandSupport {
-
- @Override
- public Object execute() throws Exception {
-
- ShellTable table = new ShellTable();
- table.column("JMS Connection Factory");
-
- List<String> connectionFactories = getJmsService().connectionFactories();
- for (String connectionFactory : connectionFactories) {
- table.addRow().addContent(connectionFactory);
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
deleted file mode 100644
index cd8caaf..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jms", name = "consume", description = "Consume messages from a JMS queue.")
-@Service
-public class ConsumeCommand extends JmsConnectionCommandSupport {
-
- @Argument(index = 1, name = "queue", description = "The JMS queue where to consume messages", required = true, multiValued = false)
- String queue;
-
- @Option(name = "-s", aliases = { "--selector" }, description = "The selector to use to select the messages to consume", required = false, multiValued = false)
- String selector;
-
- @Override
- public Object execute() throws Exception {
- System.out.println(getJmsService().consume(connectionFactory, queue, selector, username, password) + " message(s) consumed");
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
deleted file mode 100644
index 576e8dd..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/CountCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "count", description = "Count the number of messages on a JMS queue.")
-@Service
-public class CountCommand extends JmsConnectionCommandSupport {
-
- @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
- String queue;
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
- table.column("Messages Count");
- table.addRow().addContent(getJmsService().count(connectionFactory, queue, username, password));
- table.print(System.out);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
deleted file mode 100644
index c2c7eca..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-@Command(scope = "jms", name = "create", description = "Create a JMS connection factory.")
-@Service
-public class CreateCommand extends JmsCommandSupport {
-
- @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
- String name;
-
- @Option(name = "-t", aliases = { "--type" }, description = "The JMS connection factory type (ActiveMQ or WebsphereMQ)", required = false, multiValued = false)
- @Completion(value = StringsCompleter.class, values = { "activemq", "webspheremq" })
- String type = "ActiveMQ";
-
- @Option(name = "--url", description = "URL of the JMS broker. For WebsphereMQ type, the URL is hostname/port/queuemanager/channel", required = false, multiValued = false)
- String url = "tcp://localhost:61616";
-
- @Override
- public Object execute() throws Exception {
- getJmsService().create(name, type, url);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
deleted file mode 100644
index cab3123..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.jms.command.completers.ConnectionFactoriesFileNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jms", name = "delete", description = "Delete a JMS connection factory")
-@Service
-public class DeleteCommand extends JmsCommandSupport {
-
- @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
- @Completion(ConnectionFactoriesFileNameCompleter.class)
- String name;
-
- @Override
- public Object execute() throws Exception {
- getJmsService().delete(name);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
deleted file mode 100644
index 354db39..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "info", description = "Provides details about a JMS connection factory.")
-@Service
-public class InfoCommand extends JmsConnectionCommandSupport {
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
- table.column("Property");
- table.column("Value");
-
- Map<String, String> info = getJmsService().info(connectionFactory, username, password);
- for (String key : info.keySet()) {
- table.addRow().addContent(key, info.get(key));
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
deleted file mode 100644
index 2f5df8f..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import org.apache.karaf.jms.JmsService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-
-public abstract class JmsCommandSupport implements Action {
-
- @Reference
- private JmsService jmsService;
-
- public JmsService getJmsService() {
- return jmsService;
- }
-
- public void setJmsService(JmsService jmsService) {
- this.jmsService = jmsService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java b/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
deleted file mode 100644
index 64adfe4..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-import org.apache.karaf.jms.command.completers.ConnectionFactoriesNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-
-/**
- * For commands that need a connection factory and authentication information
- */
-public abstract class JmsConnectionCommandSupport extends JmsCommandSupport {
-
- @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
- @Completion(ConnectionFactoriesNameCompleter.class)
- String connectionFactory;
-
- @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
- String username = "karaf";
-
- @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
- String password = "karaf";
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
deleted file mode 100644
index a4c8d12..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jms", name = "move", description = "Move messages from one JMS queue to another one.")
-@Service
-public class MoveCommand extends JmsConnectionCommandSupport {
-
- @Argument(index = 1, name = "source", description = "The source JMS queue", required = true, multiValued = false)
- String source;
-
- @Argument(index = 2, name = "destination", description = "The destination JMS queue", required = true, multiValued = false)
- String destination;
-
- @Option(name = "-s", aliases = { "--selector" }, description = "Selector to move only some messages", required = false, multiValued = false)
- String selector;
-
- @Override
- public Object execute() throws Exception {
- System.out.println(getJmsService().move(connectionFactory, source, destination, selector, username, password) + " message(s) moved");
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
deleted file mode 100644
index 7cf1dac..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "queues", description = "List the JMS queues.")
-@Service
-public class QueuesCommand extends JmsConnectionCommandSupport {
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- table.column("JMS Queues");
-
- for (String queue : getJmsService().queues(connectionFactory, username, password)) {
- table.addRow().addContent(queue);
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
deleted file mode 100644
index 63d3f4a..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/SendCommand.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jms", name = "send", description = "Send a message to ")
-@Service
-public class SendCommand extends JmsConnectionCommandSupport {
-
- @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
- String queue;
-
- @Argument(index = 2, name = "message", description = "The JMS message content", required = true, multiValued = false)
- String message;
-
- @Option(name = "-r", aliases = { "--replyTo" }, description = "Set the message ReplyTo", required = false, multiValued = false)
- String replyTo;
-
- @Override
- public Object execute() throws Exception {
- getJmsService().send(connectionFactory, queue, message, replyTo, username, password);
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java b/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
deleted file mode 100644
index b583bc4..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command;
-
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "jms", name = "topics", description = "List the JMS topics.")
-@Service
-public class TopicsCommand extends JmsConnectionCommandSupport {
-
- @Override
- public Object execute() throws Exception {
- ShellTable table = new ShellTable();
-
- table.column("JMS Topics");
-
- for (String topic : getJmsService().topics(connectionFactory, username, password)) {
- table.addRow().addContent(topic);
- }
-
- table.print(System.out);
-
- return null;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
deleted file mode 100644
index c33ff62..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.jms.JmsService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Completer on the JMS connection factory file names.
- */
-@Service
-public class ConnectionFactoriesFileNameCompleter implements Completer {
-
- @Reference
- private JmsService jmsService;
-
- @Override
- public int complete(Session session, CommandLine commandLine, List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (String connectionFactory : jmsService.connectionFactoryFileNames()) {
- delegate.getStrings().add(connectionFactory.replace("connectionfactory-", "").replace(".xml", ""));
- }
- } catch (Exception e) {
- // nothing to do
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
- public JmsService getJmsService() {
- return jmsService;
- }
-
- public void setJmsService(JmsService jmsService) {
- this.jmsService = jmsService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java b/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
deleted file mode 100644
index 98f97b3..0000000
--- a/jms/command/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.jms.JmsService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Completer on the JMS connection factories name.
- */
-@Service
-public class ConnectionFactoriesNameCompleter implements Completer {
-
- @Reference
- private JmsService jmsService;
-
- @Override
- public int complete(Session session, CommandLine commandLine, List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (String connectionFactory : jmsService.connectionFactories()) {
- delegate.getStrings().add(connectionFactory);
- }
- } catch (Exception e) {
- // nothing to do
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
- public JmsService getJmsService() {
- return jmsService;
- }
-
- public void setJmsService(JmsService jmsService) {
- this.jmsService = jmsService;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jms/command/src/main/resources/OSGI-INF/bundle.info b/jms/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 8b83f13..0000000
--- a/jms/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,29 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the shell commands to manipulate the JMS service.
-
-The following commands are available:
-
-* jms:create
-* jms:delete
-* jms:connectionfactories
-* jms:info
-* jms:count
-* jms:queues
-* jms:topics
-* jms:send
-* jms:consume
-* jms:move
-
-h1. See also
-
-JMS - section of the Karaf User Guide
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/NOTICE
----------------------------------------------------------------------
diff --git a/jms/core/NOTICE b/jms/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jms/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/pom.xml
----------------------------------------------------------------------
diff --git a/jms/core/pom.xml b/jms/core/pom.xml
deleted file mode 100644
index 720d361..0000000
--- a/jms/core/pom.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.jms</groupId>
- <artifactId>jms</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.jms.core</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: JMS :: Core</name>
- <description>This bundle provides core implementation of the JMS service.</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-jms_1.1_spec</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.activemq</groupId>
- <artifactId>activemq-pool</artifactId>
- <version>5.9.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf</groupId>
- <artifactId>org.apache.karaf.util</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>
- org.apache.karaf.jms
- </Export-Package>
- <Import-Package>
- org.apache.activemq*;resolution:=optional,
- *
- </Import-Package>
- <Private-Package>
- org.apache.karaf.jms.internal,
- org.apache.karaf.util
- </Private-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
deleted file mode 100644
index 8540b86..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/JmsMBean.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-import java.util.List;
-import java.util.Map;
-
-/**
- * JMS MBean.
- */
-public interface JmsMBean {
-
- /**
- * List the JMS connection factories.
- *
- * @return the list of the JMS connection factories name.
- * @throws MBeanException
- */
- List<String> getConnectionfactories() throws MBeanException;
-
- /**
- * Create a JMS connection factory.
- *
- * @param name the JMS connection factory name.
- * @param type the JMS connection factory type (ActiveMQ or WebsphereMQ).
- * @param url the JMS connection factory URL. NB: when type is WebsphereMQ, the URL has the format host/port/queuemanager/channel.
- * @throws MBeanException
- */
- void create(String name, String type, String url) throws MBeanException;
-
- /**
- * Delete a JMS connection factory.
- *
- * @param name the JMS connection factory name.
- * @throws MBeanException
- */
- void delete(String name) throws MBeanException;
-
- /**
- * Get details about a JMS connection factory.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return a map (property/value) containing details.
- * @throws MBeanException
- */
- Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException;
-
- /**
- * Count the messages on a given JMS queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the JMS queue name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return
- * @throws MBeanException
- */
- int count(String connectionFactory, String queue, String username, String password) throws MBeanException;
-
- /**
- * List the JMS queues.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the list of JMS queues.
- * @throws MBeanException
- */
- List<String> queues(String connectionFactory, String username, String password) throws MBeanException;
-
- /**
- * List the JMS topics.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the list of JMS topics.
- * @throws MBeanException
- */
- List<String> topics(String connectionFactory, String username, String password) throws MBeanException;
-
- /**
- * Browse the messages in a JMS queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the JMS queue name.
- * @param selector a selector to use to browse only certain messages.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return a tabular data with messages details.
- * @throws MBeanException
- */
- TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
-
- /**
- * Send a JMS message to given queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the JMS queue name.
- * @param content the message content.
- * @param replyTo the message ReplyTo.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @throws MBeanException
- */
- void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException;
-
- /**
- * Consume JMS messages from a given queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the JMS queue name.
- * @param selector a selector to use to consume only certain messages.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the number of messages consumed.
- * @throws MBeanException
- */
- int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
-
- /**
- * Move JMS messages from one queue to another.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param source the source JMS queue name.
- * @param destination the destination JMS queue name.
- * @param selector a selector to move only certain messages.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the number of messages moved.
- * @throws MBeanException
- */
- int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
deleted file mode 100644
index a85af10..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/JmsMessage.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms;
-
-import javax.jms.*;
-import java.io.UnsupportedEncodingException;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Describe a JMS message is more human readable way.
- */
-public class JmsMessage {
-
- private Map<String, Object> properties = new HashMap<String, Object>();
-
- private String content;
- private String charset = "UTF-8";
- private String correlationID;
- private String deliveryMode;
- private String destination;
- private String expiration;
- private String messageId;
- private int priority;
- private boolean redelivered;
- private String replyTo;
- private String timestamp;
- private String type;
-
- public JmsMessage(Message message) {
- try {
- initFromMessage(message);
- } catch (JMSException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
- public void initFromMessage(Message message) throws JMSException {
- @SuppressWarnings("unchecked")
- Enumeration<String> names = message.getPropertyNames();
- while (names.hasMoreElements()) {
- String key = names.nextElement();
- Object value = message.getObjectProperty(key);
- properties.put(key, value);
- }
-
- correlationID = message.getJMSCorrelationID();
- if (message.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT) {
- deliveryMode = "Non Persistent";
- } else {
- deliveryMode = "Persistent";
- }
- Destination destinationDest = message.getJMSDestination();
- if (destinationDest != null) {
- destination = destinationDest.toString();
- }
- if (message.getJMSExpiration() > 0) {
- expiration = new Date(message.getJMSExpiration()).toString();
- } else {
- expiration = "Never";
- }
- messageId = message.getJMSMessageID();
- priority = message.getJMSPriority();
- redelivered = message.getJMSRedelivered();
- Destination replyToDest = message.getJMSReplyTo();
- if (replyToDest != null) {
- replyTo = replyToDest.toString();
- }
- if (message.getJMSTimestamp() > 0) {
- timestamp = new Date(message.getJMSTimestamp()).toString();
- } else {
- timestamp = "";
- }
- type = message.getJMSType();
- content = getMessageContent(message);
- }
-
-
- private String getMessageContent(Message message) throws JMSException {
- if (message instanceof TextMessage) {
- return ((TextMessage) message).getText();
- } else if (message instanceof BytesMessage) {
- BytesMessage bMessage = (BytesMessage) message;
- long length = bMessage.getBodyLength();
- byte[] content = new byte[(int) length];
- bMessage.readBytes(content);
- try {
- return new String(content, charset);
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
- return "";
- }
-
- public Map<String, Object> getProperties() {
- return properties;
- }
-
- public String getContent() {
- return content;
- }
-
- public String getCharset() {
- return charset;
- }
-
- public String getCorrelationID() {
- return correlationID;
- }
-
- public String getDeliveryMode() {
- return deliveryMode;
- }
-
- public String getDestination() {
- return destination;
- }
-
- public String getExpiration() {
- return expiration;
- }
-
- public String getMessageId() {
- return messageId;
- }
-
- public int getPriority() {
- return priority;
- }
-
- public boolean isRedelivered() {
- return redelivered;
- }
-
- public String getReplyTo() {
- return replyTo;
- }
-
- public String getTimestamp() {
- return timestamp;
- }
-
- public String getType() {
- return type;
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java b/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
deleted file mode 100644
index 8aa970f..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/JmsService.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * JMS Service.
- */
-public interface JmsService {
-
- /**
- * List the JMS connection factories.
- *
- * @return the list of JMS connection factory names.
- * @throws Exception
- */
- List<String> connectionFactories() throws Exception;
-
- /**
- * List the JMS connecion factories file names.
- *
- * @return the list of JMS connection factory file names.
- * @throws Exception
- */
- List<String> connectionFactoryFileNames() throws Exception;
-
- /**
- * Create a new JMS connection factory.
- *
- * @param name the JMS connection factory name.
- * @param type the JMS connection factory type (ActiveMQ, WebsphereMQ, ...).
- * @param url the JMS URL to use.
- * @throws Exception
- */
- void create(String name, String type, String url) throws Exception;
-
- /**
- * Delete a JMS connection factory.
- *
- * @param name the JMS connection factory name.
- * @throws Exception
- */
- void delete(String name) throws Exception;
-
- /**
- * Get details about a given JMS connection factory.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return a map (property/value) containing details.
- * @throws Exception
- */
- Map<String, String> info(String connectionFactory, String username, String password) throws Exception;
-
- /**
- * Count the number of messages in a JMS queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the queue name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the number of messages in a JMS queue.
- * @throws Exception
- */
- int count(String connectionFactory, String queue, String username, String password) throws Exception;
-
- /**
- * List the queues.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the list of queues.
- * @throws Exception
- */
- List<String> queues(String connectionFactory, String username, String password) throws Exception;
-
- /**
- * List the topics.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the list of topics.
- * @throws Exception
- */
- List<String> topics(String connectionFactory, String username, String password) throws Exception;
-
- /**
- * Browse a destination.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the queue name.
- * @param selector the selector.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the list of messages.
- * @throws Exception
- */
- List<JmsMessage> browse(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
-
- /**
- * Send a message on the given queue.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the queue name.
- * @param body the message body.
- * @param replyTo the message replyTo header.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @throws Exception
- */
- void send(String connectionFactory, String queue, String body, String replyTo, String username, String password) throws Exception;
-
- /**
- * Consume messages from a given destination.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param queue the queue name.
- * @param selector the messages selector.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the number of messages consumed.
- * @throws Exception
- */
- int consume(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
-
- /**
- * Move messages from a destination to another.
- *
- * @param connectionFactory the JMS connection factory name.
- * @param sourceQueue the source queue.
- * @param targetQueue the target queue.
- * @param selector the messages selector on the source queue.
- * @param username optional username to connect to the JMS broker.
- * @param password optional password to connect to the JMS broker.
- * @return the number of messages moved.
- * @throws Exception
- */
- int move(String connectionFactory, String sourceQueue, String targetQueue, String selector, String username, String password) throws Exception;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
deleted file mode 100644
index ecace89..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.internal;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Collection;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.JMSException;
-import javax.jms.Session;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-public class JmsConnector implements Closeable {
- private BundleContext bc;
- private ServiceReference<ConnectionFactory> reference;
- private Connection connection;
- private Session session;
- private String connectionFactoryName;
- private String username;
- private String password;
-
- public JmsConnector(BundleContext bc, String connectionFactoryName, String username, String password) throws JMSException {
- this.bc = bc;
- this.connectionFactoryName = connectionFactoryName;
- this.username = username;
- this.password = password;
- }
-
- private ServiceReference<ConnectionFactory> lookupConnectionFactory(String name) {
- Collection<ServiceReference<ConnectionFactory>> references;
- try {
- references = bc.getServiceReferences(ConnectionFactory.class, "(|(osgi.jndi.service.name=" + name + ")(name=" + name + ")(service.id=" + name + "))");
- } catch (InvalidSyntaxException e) {
- throw new RuntimeException("Error finding connection factory service " + name, e);
- }
- if (references == null || references.size() == 0) {
- throw new IllegalArgumentException("No JMS connection factory found for " + name);
- }
- if (references.size() > 1) {
- throw new IllegalArgumentException("Multiple JMS connection factories found for " + name);
- }
- return references.iterator().next();
- }
-
- @Override
- public void close() throws IOException {
- if (session != null) {
- try {
- session.close();
- } catch (JMSException e) {
- // Ignore
- }
- }
- if (connection != null) {
- try {
- connection.close();
- } catch (JMSException e) {
- // Ignore
- }
- }
- if (reference != null) {
- bc.ungetService(reference);
- }
- }
-
- public Connection connect() throws JMSException {
- reference = this.lookupConnectionFactory(connectionFactoryName);
- ConnectionFactory cf = (ConnectionFactory) bc.getService(reference);
- connection = cf.createConnection(username, password);
- connection.start();
- return connection;
- }
-
- public Session createSession() throws JMSException {
- if (connection == null) {
- connect();
- }
- return session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
deleted file mode 100644
index cc46434..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.internal;
-
-import org.apache.karaf.jms.JmsMBean;
-import org.apache.karaf.jms.JmsMessage;
-import org.apache.karaf.jms.JmsService;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.*;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Default implementation of the JMS MBean.
- */
-public class JmsMBeanImpl implements JmsMBean {
-
- private JmsService jmsService;
-
- @Override
- public List<String> getConnectionfactories() throws MBeanException {
- try {
- return jmsService.connectionFactories();
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public void create(String name, String type, String url) throws MBeanException {
- try {
- jmsService.create(name, type, url);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public void delete(String name) throws MBeanException {
- try {
- jmsService.delete(name);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException {
- try {
- return jmsService.info(connectionFactory, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public int count(String connectionFactory, String queue, String username, String password) throws MBeanException {
- try {
- return jmsService.count(connectionFactory, queue, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public List<String> queues(String connectionFactory, String username, String password) throws MBeanException {
- try {
- return jmsService.queues(connectionFactory, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public List<String> topics(String connectionFactory, String username, String password) throws MBeanException {
- try {
- return jmsService.topics(connectionFactory, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException {
- try {
- jmsService.send(connectionFactory, queue, content, replyTo, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
- try {
- return jmsService.consume(connectionFactory, queue, selector, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException {
- try {
- return jmsService.move(connectionFactory, source, destination, selector, username, password);
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- @Override
- public TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
- try {
- CompositeType type = new CompositeType("message", "JMS Message",
- new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
- new String[]{ "Message ID", "Content", "Charset", "Type", "Correlation ID", "Delivery Mode", "Destination", "Expiration Date", "Priority", "Redelivered", "Reply-To", "Timestamp" },
- new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.STRING });
- TabularType tableType = new TabularType("messages", "JMS Messages", type, new String[]{ "id" });
- TabularData table = new TabularDataSupport(tableType);
- for (JmsMessage message : getJmsService().browse(connectionFactory, queue, selector, username, password)) {
- CompositeData data = new CompositeDataSupport(type,
- new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
- new Object[]{ message.getMessageId(), message.getContent(), message.getCharset(), message.getType(), message.getCorrelationID(), message.getDeliveryMode(), message.getDestination(), message.getExpiration(), message.getPriority(), message.isRedelivered(), message.getReplyTo(), message.getTimestamp() }
- );
- table.put(data);
- }
- return table;
- } catch (Throwable t) {
- throw new MBeanException(null, t.getMessage());
- }
- }
-
- public JmsService getJmsService() {
- return jmsService;
- }
-
- public void setJmsService(JmsService jmsService) {
- this.jmsService = jmsService;
- }
-
-}
[25/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
new file mode 100644
index 0000000..9536ba1
--- /dev/null
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+ targetNamespace="http://karaf.apache.org/xmlns/features/v1.0.0"
+ xmlns:tns="http://karaf.apache.org/xmlns/features/v1.0.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+ ]]></xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType name="features">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Root element of the Feature definition. It contains an optional attribute for
+designating the name of the repository of this feature. The Karaf shell will
+show the repository name when displaying information about the feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="repository" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="feature" type="tns:feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature definition.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" />
+ </xs:complexType>
+
+ <xs:complexType name="feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="details" minOccurs="0" type="xs:string">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The help text shown for this feature when using the feature:info console command.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ </xs:choice>
+ <xs:attribute name="name" type="tns:featureName" use="required" />
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ <xs:attribute name="description" type="xs:string" />
+ <xs:attribute name="resolver" type="tns:resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="install" type="tns:install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If true, marks that the feature should start automatically when placed in the deploy folder.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for the bundles in this feature different
+from the default start level defined in Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="region" type="xs:string"/>
+ </xs:complexType>
+
+ <xs:complexType name="bundle">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Deployable element to install.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in Karaf's config.properties.
+
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start" type="xs:boolean" default="true">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If false, leaves the bundle in resolved state rather than the default active state.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="dependency" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="dependency">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Dependency of feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="tns:featureName">
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="config">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="configFile">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="finalname" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The final destination path and name for the configuration file (relative to the KARAF_BASE).
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="override" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="featureName">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature name should be non empty string.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which has following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="features" type="tns:features" />
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
new file mode 100644
index 0000000..7138573
--- /dev/null
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+ targetNamespace="http://karaf.apache.org/xmlns/features/v1.1.0"
+ xmlns:tns="http://karaf.apache.org/xmlns/features/v1.1.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+ ]]></xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType name="features">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="repository" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="feature" type="tns:feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature definition.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="details" minOccurs="0" type="xs:string">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ </xs:choice>
+ <xs:attribute name="name" type="tns:featureName" use="required" />
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ <xs:attribute name="description" type="xs:string" />
+ <xs:attribute name="resolver" type="tns:resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="install" type="tns:install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <xs:complexType name="bundle">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Deployable element to install.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start" type="xs:boolean" default="true">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="dependency" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="dependency">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Dependency of feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="tns:featureName">
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="config">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="configFile">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="finalname" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="override" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="featureName">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature name should be non empty string.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="features" type="tns:features" />
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
new file mode 100644
index 0000000..dbc4bfa
--- /dev/null
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+ targetNamespace="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:tns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+ ]]></xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType name="features">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="repository" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="feature" type="tns:feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature definition.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="details" minOccurs="0" type="xs:string">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ <xs:element name="conditional" type="tns:conditional" />
+ </xs:choice>
+ <xs:attribute name="name" type="tns:featureName" use="required" />
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ <xs:attribute name="description" type="xs:string" />
+ <xs:attribute name="resolver" type="tns:resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="install" type="tns:install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <xs:complexType name="conditional">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Conditional.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
+ </xs:choice>
+ </xs:complexType>
+
+
+ <xs:complexType name="bundle">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Deployable element to install.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start" type="xs:boolean" default="true">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="dependency" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="dependency">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Dependency of feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="tns:featureName">
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="config">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="configFile">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="finalname" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="override" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="featureName">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature name should be non empty string.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="features" type="tns:features" />
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
new file mode 100644
index 0000000..60ec8d2
--- /dev/null
+++ b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+ targetNamespace="http://karaf.apache.org/xmlns/features/v1.3.0"
+ xmlns:tns="http://karaf.apache.org/xmlns/features/v1.3.0"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+ ]]></xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType name="features">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="repository" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="feature" type="tns:feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature definition.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+
+ <xs:complexType name="feature">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="details" minOccurs="0" type="xs:string">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ <xs:element name="conditional" type="tns:conditional" />
+ <xs:element name="requirement" type="tns:requirement" />
+ <xs:element name="capability" type="tns:capability" />
+ </xs:choice>
+ <xs:attribute name="name" type="tns:featureName" use="required" />
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ <xs:attribute name="description" type="xs:string" />
+ <xs:attribute name="resolver" type="tns:resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="install" type="tns:install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <xs:complexType name="conditional">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Definition of the Conditional.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="config" type="tns:config" />
+ <xs:element name="configfile" type="tns:configFile" />
+ <xs:element name="feature" type="tns:dependency" />
+ <xs:element name="bundle" type="tns:bundle" />
+ <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
+ </xs:choice>
+ </xs:complexType>
+
+
+ <xs:complexType name="bundle">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Deployable element to install.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="start-level" type="xs:int">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="start" type="xs:boolean" default="true">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="dependency" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+ ]]>
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="dependency">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Dependency of feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="tns:featureName">
+ <xs:attribute name="version" type="xs:string" default="0.0.0" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="config">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="name" type="xs:string" use="required" />
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="configFile">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="finalname" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="override" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+ ]]></xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="requirement">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional requirements of this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:complexType name="capability">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Additional capability of this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+ <xs:simpleType name="featureName">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Feature name should be non empty string.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:simpleType name="resolver">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="install">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1" />
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:element name="features" type="tns:features" />
+
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java b/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
new file mode 100644
index 0000000..b103683
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import junit.framework.TestCase;
+import org.apache.karaf.features.internal.service.RepositoryImpl;
+
+
+public class ConditionalTest extends TestCase {
+
+ public void testLoad() throws Exception {
+ RepositoryImpl r = new RepositoryImpl(getClass().getResource("internal/service/f06.xml").toURI());
+ // Check repo
+ Feature[] features = r.getFeatures();
+ assertNotNull(features);
+ assertEquals(1, features.length);
+ Feature feature = features[0];
+
+ assertNotNull(feature.getConditional());
+ assertEquals(2,feature.getConditional().size());
+
+ Conditional conditional = feature.getConditional().get(0);
+ assertNotNull(conditional.getCondition());
+ assertEquals(1,conditional.getCondition().size());
+ String dependency = conditional.getCondition().get(0);
+ assertNotNull(dependency);
+ assertEquals("http", dependency);
+ assertNotNull(conditional.getBundles());
+ assertEquals(1, feature.getConditional().get(0).getBundles().size());
+
+ conditional = feature.getConditional().get(1);
+ assertNotNull(conditional.getCondition());
+ assertEquals(1,conditional.getCondition().size());
+ dependency = conditional.getCondition().get(0);
+ assertNotNull(dependency);
+ assertEquals("req:osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(!(version>=1.7)))\"", dependency);
+
+ String wrapperName = "my6/1.5.3-beta-3".replaceAll("[^A-Za-z0-9 ]", "_");
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java b/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
new file mode 100644
index 0000000..b7d4c27
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import junit.framework.TestCase;
+
+public class FeatureTest extends TestCase {
+
+ public void testValueOf() {
+ Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf("name" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + "version");
+ assertEquals(feature.getName(), "name");
+ assertEquals(feature.getVersion(), "version");
+ feature = org.apache.karaf.features.internal.model.Feature.valueOf("name");
+ assertEquals(feature.getName(), "name");
+ assertEquals(feature.getVersion(), org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
new file mode 100644
index 0000000..9f7e67b
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -0,0 +1,430 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.service.StateStorage;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class FeaturesServiceTest extends TestBase {
+ private static final String FEATURE_WITH_INVALID_BUNDLE = "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1'><bundle>%s</bundle><bundle>zfs:unknown</bundle></feature>"
+ + " <feature name='f2'><bundle>%s</bundle></feature>"
+ + "</features>";
+
+ File dataFile;
+
+ @Before
+ public void setUp() throws IOException {
+ dataFile = File.createTempFile("features", null, null);
+ }
+
+ private URI createTempRepo(String repoContent, Object ... variables) throws IOException {
+ File tmp = File.createTempFile("karaf", ".feature");
+ PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+ pw.printf(repoContent, variables);
+ pw.close();
+ return tmp.toURI();
+ }
+
+ /*
+ TODO: migrate those tests
+
+ @Test
+ public void testInstallFeature() throws Exception {
+ URI uri = createTempRepo(
+ "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1'><bundle start='true'>bundle-f1</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ Bundle installedBundle = createDummyBundle(12345L, "bundle-f1", headers());
+ FeaturesServiceImpl svc = testAddRepository("bundle-f1", uri, bundleManager, installedBundle);
+
+ reset(bundleManager);
+
+ expect(bundleManager.installBundleIfNeeded(eq("bundle-f1"), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true));
+ expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
+ ignoreRefreshes(bundleManager);
+ replay(bundleManager);
+ svc.installFeature("f1", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+ verify(bundleManager);
+
+ Feature[] installed = svc.listInstalledFeatures();
+ assertEquals(1, installed.length);
+ assertEquals("f1", installed[0].getName());
+ }
+
+ private FeaturesServiceImpl testAddRepository(String name, URI uri, BundleManager bundleManager,
+ Bundle installedBundle) throws IOException, BundleException, Exception {
+ expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
+ expect(bundleManager.installBundleIfNeeded(eq(name), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true)).anyTimes();
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+ Repository[] repositories = svc.listRepositories();
+ verify(bundleManager);
+
+ assertNotNull(repositories);
+ assertEquals(1, repositories.length);
+ assertNotNull(repositories[0]);
+ Feature[] features = repositories[0].getFeatures();
+ assertNotNull(features);
+ assertEquals(1, features.length);
+ assertNotNull(features[0]);
+ assertEquals("f1", features[0].getName());
+ assertNotNull(features[0].getDependencies());
+ assertEquals(0, features[0].getDependencies().size());
+ assertNotNull(features[0].getBundles());
+ assertEquals(1, features[0].getBundles().size());
+ assertEquals(name, features[0].getBundles().get(0).getLocation());
+ assertTrue(features[0].getBundles().get(0).isStart());
+ return svc;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testUninstallFeatureWithTwoVersions() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+ + " <feature name='f1' version='0.2'><bundle>bundle-0.1</bundle></feature>"
+ + "</features>");
+
+ Bundle bundlef101 = createDummyBundle(12345L, "bundle-0.1", headers());
+
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile).anyTimes();
+ expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
+ expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, false));
+ expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+ ignoreRefreshes(bundleManager);
+ bundleManager.uninstall(Collections.EMPTY_LIST, true);
+ EasyMock.expectLastCall().times(2);
+
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+
+ try {
+ svc.uninstallFeature("f1");
+ fail("Uninstall should have failed as feature is not installed");
+ } catch (Exception e) {
+ // ok
+ }
+
+ svc.installFeature("f1", "0.1", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+ svc.installFeature("f1", "0.2", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+
+ try {
+ svc.uninstallFeature("f1");
+ fail("Uninstall should have failed as feature is installed in multiple versions");
+ } catch (Exception e) {
+ // ok
+ }
+
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f1");
+ verify(bundleManager);
+ }
+
+ @Test
+ public void testAddAndRemoveRepository() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><bundle>bundle-f1-0.1</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ EasyMock.verify(bundleManager);
+
+ svc.addRepository(uri);
+ svc.removeRepository(uri);
+ verify(bundleManager);
+ }
+
+ // Tests install of a Repository that includes a feature
+ // with a feature dependency
+ // The dependant feature is in the same repository
+ // Tests uninstall of features
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testInstallFeatureWithDependantFeatures() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
+ + " <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ Bundle bundlef101 = createDummyBundle(12345L, "bundle-f1-0.1", headers());
+ Bundle bundlef201 = createDummyBundle(54321L, "bundle-f2-0.1", headers());
+ expect(bundleManager.getDataFile(EasyMock.<String> anyObject())).andReturn(dataFile).anyTimes();
+ expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null))
+ .andReturn(new BundleInstallerResult(bundlef101, true));
+ expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null))
+ .andReturn(new BundleInstallerResult(bundlef201, true));
+ expect(bundleManager.getBundleContext()).andReturn(bundleContext).anyTimes();
+ expect(bundleContext.getBundle(12345)).andReturn(bundlef101).anyTimes();
+ ignoreRefreshes(bundleManager);
+ bundleManager.uninstall(Collections.EMPTY_LIST, true);
+
+ EasyMock.expectLastCall().anyTimes();
+ replay(bundleManager);
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+ svc.installFeature("f1", "0.1");
+ svc.uninstallFeature("f1", "0.1");
+ verify(bundleManager);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ private BundleManager prepareBundleManagerForInstallUninstall(String bundleUri, String bundlename) throws Exception {
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ Bundle installedBundle = createDummyBundle(12345L, bundlename, headers());
+ expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+ expect(bundleManager.installBundleIfNeeded(bundleUri, 0, null)).andReturn(new BundleInstallerResult(installedBundle, true));
+ expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+ ignoreRefreshes(bundleManager);
+ bundleManager.uninstall(Collections.EMPTY_LIST, true);
+ EasyMock.expectLastCall().times(2);
+ return bundleManager;
+ }
+
+ @Test
+ public void testInstallFeatureWithDependantFeaturesAndVersionWithoutPreinstall() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><feature version='0.1'>f2</feature></feature>"
+ + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+ + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.1", "bundle-0.1");
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+ svc.installFeature("f1", "0.1");
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.1");
+ verify(bundleManager);
+ }
+
+ @Test
+ public void testInstallFeatureWithDependantFeaturesAndNoVersionWithoutPreinstall() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><feature>f2</feature></feature>"
+ + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+ + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.2", "bundle-0.2");
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+ svc.installFeature("f1", "0.1");
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.2");
+ verify(bundleManager);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testInstallFeatureWithDependantFeaturesAndRangeWithoutPreinstall() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+ + " <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+ + " <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+ + "</features>");
+
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ Bundle bundleVer02 = createDummyBundle(54321L, "bundleVer02", headers());
+ expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+ expect(bundleManager.installBundleIfNeeded("bundle-0.2", 0, null)).andReturn(new BundleInstallerResult(bundleVer02, true));
+ expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+ ignoreRefreshes(bundleManager);
+ bundleManager.uninstall(Collections.EMPTY_LIST, true);
+
+ EasyMock.expectLastCall().times(2);
+
+ replay(bundleManager);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+ svc.addRepository(uri);
+ svc.installFeature("f1", "0.1");
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.2");
+ verify(bundleManager);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testInstallFeatureWithDependantFeaturesAndRangeWithPreinstall() throws Exception {
+ String bundleVer01Uri = "bundle-0.1";
+ String bundleVer02Uri = "bundle-0.2";
+
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + "<feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+ + " <feature name='f2' version='0.1'><bundle>%s</bundle></feature>"
+ + " <feature name='f2' version='0.2'><bundle>%s</bundle></feature>"
+ + "</features>", bundleVer01Uri, bundleVer02Uri);
+
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+ replay(bundleContext);
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null);
+ svc.addRepository(uri);
+ svc.installFeature("f2", "0.1");
+ svc.installFeature("f1", "0.1");
+ svc.uninstallFeature("f1", "0.1");
+ svc.uninstallFeature("f2", "0.1");
+
+ verify(bundleContext);
+ }
+ */
+
+ @Test
+ public void testGetFeaturesShouldHandleDifferentVersionPatterns() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+ + " <feature name='f2' version='0.1'><bundle>bundle1</bundle></feature>"
+ + " <feature name='f2' version='0.2'><bundle>bundle2</bundle></feature>"
+ + "</features>");
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+ svc.addRepository(uri);
+
+ assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "[0.1,0.3)"));
+ assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.0.0"));
+ assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.2"));
+ assertNull(svc.getFeature("f2", "0.3"));
+ }
+
+ @Test
+ public void testInstallBatchFeatureWithFailure() throws Exception {
+ String bundle1Uri = "file:bundle1";
+ String bundle2Uri = "file:bundle2";
+
+ URI uri = createTempRepo(FEATURE_WITH_INVALID_BUNDLE, bundle1Uri, bundle2Uri);
+
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+ replay(bundleContext);
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null);
+ svc.addRepository(uri);
+ try {
+ List<String> features = new ArrayList<String>();
+ for (Feature feature : svc.listFeatures()) {
+ features.add(feature.getId());
+ }
+ Collections.reverse(features);
+ svc.installFeatures(new CopyOnWriteArraySet<String>(features),
+ EnumSet.noneOf(FeaturesService.Option.class));
+ fail("Call should have thrown an exception");
+ } catch (MalformedURLException e) {
+ }
+ verify(bundleContext);
+ }
+
+ /**
+ * This test checks schema validation of submited uri.
+ */
+ @Test
+ public void testSchemaValidation() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <featur><bundle>somebundle</bundle></featur></features>");
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+ try {
+ svc.addRepository(uri);
+ fail("exception expected");
+ } catch (Exception e) {
+ assertTrue(e.getMessage().contains("Unable to validate"));
+ }
+ }
+
+ /**
+ * This test checks feature service behavior with old, non namespaced descriptor.
+ */
+ @Test
+ public void testLoadOldFeatureFile() throws Exception {
+ URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+ + " <feature name='f1'><bundle>file:bundle1</bundle><bundle>file:bundle2</bundle></feature>"
+ + "</features>");
+
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+ svc.addRepository(uri);
+ Feature feature = svc.getFeature("f1");
+ Assert.assertNotNull("No feature named fi found", feature);
+ List<BundleInfo> bundles = feature.getBundles();
+ Assert.assertEquals(2, bundles.size());
+ }
+
+ static class Storage extends StateStorage {
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ return null;
+ }
+ @Override
+ protected OutputStream getOutputStream() throws IOException {
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java b/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
new file mode 100644
index 0000000..164dc79
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.net.URI;
+
+import junit.framework.TestCase;
+import org.apache.karaf.features.internal.resolver.FeatureResource;
+import org.apache.karaf.features.internal.service.RepositoryImpl;
+import org.osgi.resource.Resource;
+
+
+public class RepositoryTest extends TestCase {
+
+ public void testLoad() throws Exception {
+ RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo1.xml").toURI());
+ // Check repo
+ URI[] repos = r.getRepositories();
+ assertNotNull(repos);
+ assertEquals(1, repos.length);
+ assertEquals(URI.create("urn:r1"), repos[0]);
+ // Check features
+ Feature[] features = r.getFeatures();
+ assertNotNull(features);
+ assertEquals(3, features.length);
+ assertNotNull(features[0]);
+ assertEquals("f1", features[0].getName());
+ assertNotNull(features[0].getConfigurations());
+ assertEquals(1, features[0].getConfigurations().size());
+ assertNotNull(features[0].getConfigurations().get("c1"));
+ assertEquals(1, features[0].getConfigurations().get("c1").size());
+ assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
+ assertNotNull(features[0].getDependencies());
+ assertEquals(0, features[0].getDependencies().size());
+ assertNotNull(features[0].getBundles());
+ assertEquals(2, features[0].getBundles().size());
+ assertEquals("b1", features[0].getBundles().get(0).getLocation());
+ assertEquals("b2", features[0].getBundles().get(1).getLocation());
+ assertNotNull(features[1]);
+ assertEquals("f2", features[1].getName());
+ assertNotNull(features[1].getConfigurations());
+ assertEquals(0, features[1].getConfigurations().size());
+ assertNotNull(features[1].getDependencies());
+ assertEquals(1, features[1].getDependencies().size());
+ assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
+ assertNotNull(features[1].getBundles());
+ assertEquals(1, features[1].getBundles().size());
+ assertEquals("b3", features[1].getBundles().get(0).getLocation());
+ assertEquals("f3", features[2].getName());
+ assertNotNull(features[2].getConfigurationFiles());
+ assertEquals(1, features[2].getConfigurationFiles().size());
+ assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
+ assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
+ assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
+ }
+
+ public void testLoadFormattedRepo() throws Exception {
+ RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo2.xml").toURI());
+ // Check repo
+ URI[] repos = r.getRepositories();
+ assertNotNull(repos);
+ assertEquals(1, repos.length);
+ assertEquals(URI.create("urn:r1"), repos[0]);
+ // Check features
+ Feature[] features = r.getFeatures();
+ assertNotNull(features);
+ assertEquals(3, features.length);
+ assertNotNull(features[0]);
+ assertEquals("f1", features[0].getName());
+ assertNotNull(features[0].getConfigurations());
+ assertEquals(1, features[0].getConfigurations().size());
+ assertNotNull(features[0].getConfigurations().get("c1"));
+ assertEquals(1, features[0].getConfigurations().get("c1").size());
+ assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
+ assertNotNull(features[0].getDependencies());
+ assertEquals(0, features[0].getDependencies().size());
+ assertNotNull(features[0].getBundles());
+ assertEquals(2, features[0].getBundles().size());
+ assertEquals("b1", features[0].getBundles().get(0).getLocation());
+ assertEquals("b2", features[0].getBundles().get(1).getLocation());
+ assertNotNull(features[1]);
+ assertEquals("f2", features[1].getName());
+ assertNotNull(features[1].getConfigurations());
+ assertEquals(0, features[1].getConfigurations().size());
+ assertNotNull(features[1].getDependencies());
+ assertEquals(1, features[1].getDependencies().size());
+ assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
+ assertNotNull(features[1].getBundles());
+ assertEquals(1, features[1].getBundles().size());
+ assertEquals("b3", features[1].getBundles().get(0).getLocation());
+ assertEquals("f3", features[2].getName());
+ assertNotNull(features[2].getConfigurationFiles());
+ assertEquals(1, features[2].getConfigurationFiles().size());
+ assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
+ assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
+ assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
+ }
+
+ public void testLoadRepoWithCapabilitiesAndRequirement() throws Exception {
+ RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo3.xml").toURI());
+ // Check features
+ Feature[] features = r.getFeatures();
+ assertNotNull(features);
+ assertEquals(1, features.length);
+ assertNotNull(features[0]);
+ assertEquals("f1", features[0].getName());
+ assertEquals(1, features[0].getCapabilities().size());
+ assertEquals("cap", features[0].getCapabilities().get(0).getValue().trim());
+ assertEquals(1, features[0].getRequirements().size());
+ assertEquals("req", features[0].getRequirements().get(0).getValue().trim());
+
+ Resource res = FeatureResource.build(features[0], null, null);
+ assertEquals(1, res.getCapabilities("cap").size());
+ assertEquals(1, res.getRequirements("req").size());
+ }
+
+ public void testShowWrongUriInException() throws Exception {
+ String uri = "src/test/resources/org/apache/karaf/shell/features/repo1.xml";
+ RepositoryImpl r = new RepositoryImpl(new URI(uri));
+ try {
+ r.load();
+ } catch (Exception e) {
+ assertTrue(e.getMessage().contains(uri));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/TestBase.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/TestBase.java b/features/core/src/test/java/org/apache/karaf/features/TestBase.java
new file mode 100644
index 0000000..ac8f3d9
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/TestBase.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
+import static java.util.Arrays.asList;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+public class TestBase {
+ public Bundle createDummyBundle(long id, final String symbolicName, Dictionary<String,String> headers) {
+ Bundle bundle = EasyMock.createNiceMock(Bundle.class);
+
+ // Be aware that this means all bundles are treated as different
+ expect(bundle.compareTo(EasyMock.<Bundle>anyObject())).andReturn(1).anyTimes();
+
+ expect(bundle.getBundleId()).andReturn(id).anyTimes();
+ expect(bundle.getSymbolicName()).andReturn(symbolicName).anyTimes();
+ expect(bundle.getHeaders()).andReturn(headers).anyTimes();
+ BundleStartLevel sl = EasyMock.createMock(BundleStartLevel.class);
+ expect(sl.isPersistentlyStarted()).andReturn(true).anyTimes();
+ expect(bundle.adapt(BundleStartLevel.class)).andReturn(sl).anyTimes();
+ replay(bundle, sl);
+ return bundle;
+ }
+
+ public Dictionary<String, String> headers(String ... keyAndHeader) {
+ Hashtable<String, String> headersTable = new Hashtable<String, String>();
+ int c=0;
+ while (c < keyAndHeader.length) {
+ String key = keyAndHeader[c++];
+ String value = keyAndHeader[c++];
+ headersTable.put(key, value);
+ }
+ return headersTable;
+ }
+
+ public Map<String, Map<String, Feature>> features(Feature ... features) {
+ final Map<String, Map<String, Feature>> featuresMap = new HashMap<String, Map<String,Feature>>();
+ for (Feature feature : features) {
+ Map<String, Feature> featureVersion = getOrCreate(featuresMap, feature);
+ featureVersion.put(feature.getVersion(), feature);
+ }
+ return featuresMap;
+ }
+
+ private Map<String, Feature> getOrCreate(final Map<String, Map<String, Feature>> featuresMap, Feature feature) {
+ Map<String, Feature> featureVersion = featuresMap.get(feature.getName());
+ if (featureVersion == null) {
+ featureVersion = new HashMap<String, Feature>();
+ featuresMap.put(feature.getName(), featureVersion);
+ }
+ return featureVersion;
+ }
+
+ public Feature feature(String name) {
+ return feature(name, null);
+ }
+
+ public Feature feature(String name, String version) {
+ return new org.apache.karaf.features.internal.model.Feature(name, version);
+ }
+
+ public Set<Bundle> setOf(Bundle ... elements) {
+ return new HashSet<Bundle>(Arrays.asList(elements));
+ }
+
+ public Set<Long> setOf(Long ... elements) {
+ return new HashSet<Long>(Arrays.asList(elements));
+ }
+
+ public Set<String> setOf(String ... elements) {
+ return new HashSet<String>(asList(elements));
+ }
+
+ public Set<Feature> setOf(Feature ... elements) {
+ return new HashSet<Feature>(Arrays.asList(elements));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
new file mode 100644
index 0000000..31f4f29
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import static java.util.Arrays.asList;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.util.EnumSet;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService.Option;
+import org.apache.karaf.features.TestBase;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BootFeaturesInstallerTest extends TestBase {
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testParser() {
+ BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, "", "", false);
+ Assert.assertEquals(asList(setOf("test1", "test2"),setOf("test3")), installer.parseBootFeatures("(test1, test2), test3"));
+ Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures("test1, test2, test3"));
+ }
+
+ @Test
+ public void testDefaultBootFeatures() throws Exception {
+ FeaturesServiceImpl impl = EasyMock.createMock(FeaturesServiceImpl.class);
+
+ impl.installFeatures(setOf("config", "standard", "region"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+ EasyMock.expectLastCall();
+
+ impl.bootDone();
+ EasyMock.expectLastCall();
+
+ replay(impl);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "", "config,standard,region", false);
+ bootFeatures.installBootFeatures();
+ EasyMock.verify(impl);
+ }
+
+ @Test
+ public void testStagedBoot() throws Exception {
+ FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
+
+ impl.installFeatures(setOf("transaction"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+ EasyMock.expectLastCall();
+ impl.installFeatures(setOf("ssh"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+ EasyMock.expectLastCall();
+
+ impl.bootDone();
+ EasyMock.expectLastCall();
+
+ replay(impl);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , "", "(transaction), ssh", false);
+ bootFeatures.installBootFeatures();
+ EasyMock.verify(impl);
+ }
+
+ @Test
+ public void testStartDoesNotFailWithOneInvalidUri() throws Exception {
+ FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
+ impl.addRepository(URI.create("mvn:inexistent/features/1.0/xml/features"));
+ EasyMock.expectLastCall().andThrow(new IllegalArgumentException());
+
+ impl.bootDone();
+ EasyMock.expectLastCall();
+
+ replay(impl);
+ BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "mvn:inexistent/features/1.0/xml/features", "", false);
+ bootFeatures.installBootFeatures();
+ EasyMock.verify(impl);
+ }
+
+}
[28/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
new file mode 100644
index 0000000..cb2c36a
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
@@ -0,0 +1,1129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class ResourceBuilder {
+
+ public static final String RESOLUTION_DYNAMIC = "dynamic";
+
+ public static Resource build(String uri, Map<String, String> headerMap)
+ throws BundleException {
+
+ // Verify that only manifest version 2 is specified.
+ String manifestVersion = getManifestVersion(headerMap);
+ if (manifestVersion == null || !manifestVersion.equals("2")) {
+ throw new BundleException("Unsupported 'Bundle-ManifestVersion' value: " + manifestVersion);
+ }
+
+ //
+ // Parse bundle version.
+ //
+
+ Version bundleVersion = Version.emptyVersion;
+ if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
+ bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
+ }
+
+ //
+ // Parse bundle symbolic name.
+ //
+
+ String bundleSymbolicName = null;
+ ParsedHeaderClause bundleCap = parseBundleSymbolicName(headerMap);
+ if (bundleCap == null) {
+ throw new BundleException("Bundle manifest must include bundle symbolic name");
+ }
+ bundleSymbolicName = (String) bundleCap.attrs.get(BundleRevision.BUNDLE_NAMESPACE);
+
+ // Now that we have symbolic name and version, create the resource
+ String type = headerMap.get(Constants.FRAGMENT_HOST) == null ? IdentityNamespace.TYPE_BUNDLE : IdentityNamespace.TYPE_FRAGMENT;
+ ResourceImpl resource = new ResourceImpl(bundleSymbolicName, type, bundleVersion);
+ if (uri != null) {
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(UriNamespace.URI_NAMESPACE, uri);
+ resource.addCapability(new CapabilityImpl(resource, UriNamespace.URI_NAMESPACE, Collections.<String, String>emptyMap(), attrs));
+ }
+
+ // Add a bundle and host capability to all
+ // non-fragment bundles. A host capability is the same
+ // as a require capability, but with a different capability
+ // namespace. Bundle capabilities resolve required-bundle
+ // dependencies, while host capabilities resolve fragment-host
+ // dependencies.
+ if (headerMap.get(Constants.FRAGMENT_HOST) == null) {
+ // All non-fragment bundles have bundle capability.
+ resource.addCapability(new CapabilityImpl(resource, BundleRevision.BUNDLE_NAMESPACE, bundleCap.dirs, bundleCap.attrs));
+ // A non-fragment bundle can choose to not have a host capability.
+ String attachment = bundleCap.dirs.get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
+ attachment = (attachment == null) ? Constants.FRAGMENT_ATTACHMENT_RESOLVETIME : attachment;
+ if (!attachment.equalsIgnoreCase(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
+ Map<String, Object> hostAttrs = new HashMap<String, Object>(bundleCap.attrs);
+ Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE);
+ hostAttrs.put(BundleRevision.HOST_NAMESPACE, value);
+ resource.addCapability(new CapabilityImpl(
+ resource, BundleRevision.HOST_NAMESPACE,
+ bundleCap.dirs,
+ hostAttrs));
+ }
+ }
+
+ //
+ // Parse Fragment-Host.
+ //
+
+ List<RequirementImpl> hostReqs = parseFragmentHost(resource, headerMap);
+
+ //
+ // Parse Require-Bundle
+ //
+
+ List<ParsedHeaderClause> rbClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_BUNDLE));
+ rbClauses = normalizeRequireClauses(rbClauses);
+ List<Requirement> rbReqs = convertRequires(rbClauses, resource);
+
+ //
+ // Parse Import-Package.
+ //
+
+ List<ParsedHeaderClause> importClauses = parseStandardHeader(headerMap.get(Constants.IMPORT_PACKAGE));
+ importClauses = normalizeImportClauses(importClauses);
+ List<Requirement> importReqs = convertImports(importClauses, resource);
+
+ //
+ // Parse DynamicImport-Package.
+ //
+
+ List<ParsedHeaderClause> dynamicClauses = parseStandardHeader(headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
+ dynamicClauses = normalizeDynamicImportClauses(dynamicClauses);
+ List<Requirement> dynamicReqs = convertImports(dynamicClauses, resource);
+
+ //
+ // Parse Require-Capability.
+ //
+
+ List<ParsedHeaderClause> requireClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_CAPABILITY));
+ requireClauses = normalizeRequireCapabilityClauses(requireClauses);
+ List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
+
+ //
+ // Parse Export-Package.
+ //
+
+ List<ParsedHeaderClause> exportClauses = parseStandardHeader(headerMap.get(Constants.EXPORT_PACKAGE));
+ exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
+ List<Capability> exportCaps = convertExports(exportClauses, resource);
+
+ //
+ // Parse Provide-Capability.
+ //
+
+ List<ParsedHeaderClause> provideClauses = parseStandardHeader(headerMap.get(Constants.PROVIDE_CAPABILITY));
+ provideClauses = normalizeProvideCapabilityClauses(provideClauses);
+ List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
+
+ //
+ // Parse Import-Service and Export-Service
+ // if Require-Capability and Provide-Capability are not set for services
+ //
+
+ boolean hasServiceReferenceCapability = false;
+ for (Capability cap : exportCaps) {
+ hasServiceReferenceCapability |= ServiceNamespace.SERVICE_NAMESPACE.equals(cap.getNamespace());
+ }
+ if (!hasServiceReferenceCapability) {
+ List<ParsedHeaderClause> exportServices = parseStandardHeader(headerMap.get(Constants.EXPORT_SERVICE));
+ List<Capability> caps = convertExportService(exportServices, resource);
+ provideCaps.addAll(caps);
+ }
+
+ boolean hasServiceReferenceRequirement = false;
+ for (Requirement req : requireReqs) {
+ hasServiceReferenceRequirement |= ServiceNamespace.SERVICE_NAMESPACE.equals(req.getNamespace());
+ }
+ if (!hasServiceReferenceRequirement) {
+ List<ParsedHeaderClause> importServices = parseStandardHeader(headerMap.get(Constants.IMPORT_SERVICE));
+ List<Requirement> reqs = convertImportService(importServices, resource);
+ requireReqs.addAll(reqs);
+ }
+
+ // Combine all capabilities.
+ resource.addCapabilities(exportCaps);
+ resource.addCapabilities(provideCaps);
+
+ // Combine all requirements.
+ resource.addRequirements(hostReqs);
+ resource.addRequirements(importReqs);
+ resource.addRequirements(rbReqs);
+ resource.addRequirements(requireReqs);
+ resource.addRequirements(dynamicReqs);
+
+ return resource;
+ }
+
+ public static List<Requirement> parseImport(Resource resource, String imports) throws BundleException {
+ List<ParsedHeaderClause> importClauses = parseStandardHeader(imports);
+ importClauses = normalizeImportClauses(importClauses);
+ List<Requirement> importReqs = convertImports(importClauses, resource);
+ return importReqs;
+ }
+
+ public static List<Requirement> parseRequirement(Resource resource, String requirement) throws BundleException {
+ List<ParsedHeaderClause> requireClauses = parseStandardHeader(requirement);
+ requireClauses = normalizeRequireCapabilityClauses(requireClauses);
+ List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
+ return requireReqs;
+ }
+
+ public static List<Capability> parseExport(Resource resource, String bundleSymbolicName, Version bundleVersion, String exports) throws BundleException {
+ List<ParsedHeaderClause> exportClauses = parseStandardHeader(exports);
+ exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
+ List<Capability> exportCaps = convertExports(exportClauses, resource);
+ return exportCaps;
+ }
+
+ public static List<Capability> parseCapability(Resource resource, String capability) throws BundleException {
+ List<ParsedHeaderClause> provideClauses = parseStandardHeader(capability);
+ provideClauses = normalizeProvideCapabilityClauses(provideClauses);
+ List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
+ return provideCaps;
+ }
+
+ @SuppressWarnings( "deprecation" )
+ private static List<ParsedHeaderClause> normalizeImportClauses(
+ List<ParsedHeaderClause> clauses)
+ throws BundleException {
+ // Verify that the values are equals if the package specifies
+ // both version and specification-version attributes.
+ Set<String> dupeSet = new HashSet<String>();
+ for (ParsedHeaderClause clause : clauses) {
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+ Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null)) {
+ // Verify they are equal.
+ if (!((String) v).trim().equals(((String) sv).trim())) {
+ throw new IllegalArgumentException(
+ "Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the VersionRange type.
+ if ((v != null) || (sv != null)) {
+ clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+ }
+
+ // If bundle version is specified, then convert its type to VersionRange.
+ v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ if (v != null) {
+ clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+ }
+
+ // Verify java.* is not imported, nor any duplicate imports.
+ for (String pkgName : clause.paths) {
+ if (!dupeSet.contains(pkgName)) {
+ // Verify that java.* packages are not imported.
+ if (pkgName.startsWith("java.")) {
+ throw new BundleException("Importing java.* packages not allowed: " + pkgName);
+ }
+ // The character "." has no meaning in the OSGi spec except
+ // when placed on the bundle class path. Some people, however,
+ // mistakenly think it means the default package when imported
+ // or exported. This is not correct. It is invalid.
+ else if (pkgName.equals(".")) {
+ throw new BundleException("Importing '.' is invalid.");
+ }
+ // Make sure a package name was specified.
+ else if (pkgName.length() == 0) {
+ throw new BundleException(
+ "Imported package names cannot be zero length.");
+ }
+ dupeSet.add(pkgName);
+ } else {
+ throw new BundleException("Duplicate import: " + pkgName);
+ }
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<Capability> convertExportService(List<ParsedHeaderClause> clauses, Resource resource) {
+ List<Capability> capList = new ArrayList<Capability>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String path : clause.paths) {
+ Map<String, String> dirs = new LinkedHashMap<String, String>();
+ dirs.put(ServiceNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
+ Map<String, Object> attrs = new LinkedHashMap<String, Object>();
+ attrs.put(Constants.OBJECTCLASS, path);
+ attrs.putAll(clause.attrs);
+ capList.add(new CapabilityImpl(
+ resource,
+ ServiceNamespace.SERVICE_NAMESPACE,
+ dirs,
+ attrs));
+ }
+ }
+ return capList;
+ }
+
+ private static List<Requirement> convertImportService(List<ParsedHeaderClause> clauses, Resource resource) throws BundleException {
+ try {
+ List<Requirement> reqList = new ArrayList<Requirement>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String path : clause.paths) {
+ String multiple = clause.dirs.get("multiple");
+ String avail = clause.dirs.get("availability");
+ String filter = (String) clause.attrs.get("filter");
+ Map<String, String> dirs = new LinkedHashMap<String, String>();
+ dirs.put(ServiceNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
+ if ("optional".equals(avail)) {
+ dirs.put(ServiceNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, ServiceNamespace.RESOLUTION_OPTIONAL);
+ }
+ if ("true".equals(multiple)) {
+ dirs.put(ServiceNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE, ServiceNamespace.CARDINALITY_MULTIPLE);
+ }
+ if (filter == null) {
+ filter = "(" + Constants.OBJECTCLASS + "=" + path + ")";
+ } else if (!filter.startsWith("(") && !filter.endsWith(")")) {
+ filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")(" + filter + "))";
+ } else {
+ filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")" + filter + ")";
+ }
+ dirs.put(ServiceNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
+ reqList.add(new RequirementImpl(
+ resource,
+ ServiceNamespace.SERVICE_NAMESPACE,
+ dirs,
+ Collections.<String, Object>emptyMap(),
+ SimpleFilter.parse(filter)));
+ }
+ }
+ return reqList;
+ } catch (Exception ex) {
+ throw new BundleException("Error creating requirement: " + ex, ex);
+ }
+ }
+
+ private static List<Requirement> convertImports(List<ParsedHeaderClause> clauses, Resource resource) {
+ // Now convert generic header clauses into requirements.
+ List<Requirement> reqList = new ArrayList<Requirement>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String path : clause.paths) {
+ // Prepend the package name to the array of attributes.
+ Map<String, Object> attrs = clause.attrs;
+ // Note that we use a linked hash map here to ensure the
+ // package attribute is first, which will make indexing
+ // more efficient.
+ // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+ // Prepend the package name to the array of attributes.
+ Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+ // We want this first from an indexing perspective.
+ newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
+ newAttrs.putAll(attrs);
+ // But we need to put it again to make sure it wasn't overwritten.
+ newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
+
+ // Create filter now so we can inject filter directive.
+ SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+ // Inject filter directive.
+ // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+ Map<String, String> dirs = clause.dirs;
+ Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+ newDirs.putAll(dirs);
+ newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+ // Create package requirement and add to requirement list.
+ reqList.add(
+ new RequirementImpl(
+ resource,
+ BundleRevision.PACKAGE_NAMESPACE,
+ newDirs,
+ Collections.<String, Object>emptyMap(),
+ sf));
+ }
+ }
+
+ return reqList;
+ }
+
+ @SuppressWarnings( "deprecation" )
+ private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
+ List<ParsedHeaderClause> clauses)
+ throws BundleException {
+ // Verify that the values are equals if the package specifies
+ // both version and specification-version attributes.
+ for (ParsedHeaderClause clause : clauses) {
+ // Add the resolution directive to indicate that these are
+ // dynamic imports.
+ clause.dirs.put(Constants.RESOLUTION_DIRECTIVE, RESOLUTION_DYNAMIC);
+
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+ Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null)) {
+ // Verify they are equal.
+ if (!((String) v).trim().equals(((String) sv).trim())) {
+ throw new IllegalArgumentException(
+ "Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the VersionRange type.
+ if ((v != null) || (sv != null)) {
+ clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+ }
+
+ // If bundle version is specified, then convert its type to VersionRange.
+ v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ if (v != null) {
+ clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+ }
+
+ // Dynamic imports can have duplicates, so verify that java.*
+ // packages are not imported.
+ for (String pkgName : clause.paths) {
+ if (pkgName.startsWith("java.")) {
+ throw new BundleException("Dynamically importing java.* packages not allowed: " + pkgName);
+ } else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*")) {
+ throw new BundleException("Partial package name wild carding is not allowed: " + pkgName);
+ }
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<ParsedHeaderClause> normalizeRequireCapabilityClauses(
+ List<ParsedHeaderClause> clauses)
+ throws BundleException {
+
+ return clauses;
+ }
+
+ private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
+ List<ParsedHeaderClause> clauses)
+ throws BundleException
+ {
+
+ // Convert attributes into specified types.
+ for (ParsedHeaderClause clause : clauses)
+ {
+ for (Map.Entry<String, String> entry : clause.types.entrySet())
+ {
+ String type = entry.getValue();
+ if (!type.equals("String"))
+ {
+ if (type.equals("Double"))
+ {
+ clause.attrs.put(
+ entry.getKey(),
+ new Double(clause.attrs.get(entry.getKey()).toString().trim()));
+ }
+ else if (type.equals("Version"))
+ {
+ clause.attrs.put(
+ entry.getKey(),
+ new Version(clause.attrs.get(entry.getKey()).toString().trim()));
+ }
+ else if (type.equals("Long"))
+ {
+ clause.attrs.put(
+ entry.getKey(),
+ new Long(clause.attrs.get(entry.getKey()).toString().trim()));
+ }
+ else if (type.startsWith("List"))
+ {
+ int startIdx = type.indexOf('<');
+ int endIdx = type.indexOf('>');
+ if (((startIdx > 0) && (endIdx <= startIdx))
+ || ((startIdx < 0) && (endIdx > 0)))
+ {
+ throw new BundleException(
+ "Invalid Provide-Capability attribute list type for '"
+ + entry.getKey()
+ + "' : "
+ + type);
+ }
+
+ String listType = "String";
+ if (endIdx > startIdx)
+ {
+ listType = type.substring(startIdx + 1, endIdx).trim();
+ }
+
+ List<String> tokens = parseDelimitedString(
+ clause.attrs.get(entry.getKey()).toString(), ",", false);
+ List<Object> values = new ArrayList<Object>(tokens.size());
+ for (String token : tokens)
+ {
+ if (listType.equals("String"))
+ {
+ values.add(token);
+ }
+ else if (listType.equals("Double"))
+ {
+ values.add(new Double(token.trim()));
+ }
+ else if (listType.equals("Version"))
+ {
+ values.add(new Version(token.trim()));
+ }
+ else if (listType.equals("Long"))
+ {
+ values.add(new Long(token.trim()));
+ }
+ else
+ {
+ throw new BundleException(
+ "Unknown Provide-Capability attribute list type for '"
+ + entry.getKey()
+ + "' : "
+ + type);
+ }
+ }
+ clause.attrs.put(
+ entry.getKey(),
+ values);
+ }
+ else
+ {
+ throw new BundleException(
+ "Unknown Provide-Capability attribute type for '"
+ + entry.getKey()
+ + "' : "
+ + type);
+ }
+ }
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<Requirement> convertRequireCapabilities(
+ List<ParsedHeaderClause> clauses, Resource resource)
+ throws BundleException {
+ // Now convert generic header clauses into requirements.
+ List<Requirement> reqList = new ArrayList<Requirement>();
+ for (ParsedHeaderClause clause : clauses) {
+ try {
+ String filterStr = clause.dirs.get(Constants.FILTER_DIRECTIVE);
+ SimpleFilter sf = (filterStr != null)
+ ? SimpleFilter.parse(filterStr)
+ : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+ for (String path : clause.paths) {
+ // Create requirement and add to requirement list.
+ reqList.add(new RequirementImpl(
+ resource, path, clause.dirs, clause.attrs, sf));
+ }
+ } catch (Exception ex) {
+ throw new BundleException("Error creating requirement: " + ex, ex);
+ }
+ }
+
+ return reqList;
+ }
+
+ private static List<Capability> convertProvideCapabilities(
+ List<ParsedHeaderClause> clauses, Resource resource)
+ throws BundleException {
+ List<Capability> capList = new ArrayList<Capability>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String path : clause.paths) {
+ if (path.startsWith("osgi.wiring.")) {
+// throw new BundleException("Manifest cannot use Provide-Capability for '" + path + "' namespace.");
+ }
+
+ // Create package capability and add to capability list.
+ capList.add(new CapabilityImpl(resource, path, clause.dirs, clause.attrs));
+ }
+ }
+
+ return capList;
+ }
+
+ @SuppressWarnings( "deprecation" )
+ private static List<ParsedHeaderClause> normalizeExportClauses(
+ List<ParsedHeaderClause> clauses,
+ String bsn, Version bv)
+ throws BundleException {
+ // Verify that "java.*" packages are not exported.
+ for (ParsedHeaderClause clause : clauses) {
+ // Verify that the named package has not already been declared.
+ for (String pkgName : clause.paths) {
+ // Verify that java.* packages are not exported.
+ if (pkgName.startsWith("java.")) {
+ throw new BundleException("Exporting java.* packages not allowed: " + pkgName);
+ }
+ // The character "." has no meaning in the OSGi spec except
+ // when placed on the bundle class path. Some people, however,
+ // mistakenly think it means the default package when imported
+ // or exported. This is not correct. It is invalid.
+ else if (pkgName.equals(".")) {
+ throw new BundleException("Exporing '.' is invalid.");
+ }
+ // Make sure a package name was specified.
+ else if (pkgName.length() == 0) {
+ throw new BundleException("Exported package names cannot be zero length.");
+ }
+ }
+
+ // Check for "version" and "specification-version" attributes
+ // and verify they are the same if both are specified.
+ Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+ Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+ if ((v != null) && (sv != null)) {
+ // Verify they are equal.
+ if (!((String) v).trim().equals(((String) sv).trim())) {
+ throw new IllegalArgumentException("Both version and specification-version are specified, but they are not equal.");
+ }
+ }
+
+ // Always add the default version if not specified.
+ if ((v == null) && (sv == null)) {
+ v = Version.emptyVersion;
+ }
+
+ // Ensure that only the "version" attribute is used and convert
+ // it to the appropriate type.
+ if ((v != null) || (sv != null)) {
+ // Convert version attribute to type Version.
+ clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+ v = (v == null) ? sv : v;
+ clause.attrs.put(Constants.VERSION_ATTRIBUTE, Version.parseVersion(v.toString()));
+ }
+
+ // Find symbolic name and version attribute, if present.
+ if (clause.attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)
+ || clause.attrs.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)) {
+ throw new BundleException("Exports must not specify bundle symbolic name or bundle version.");
+ }
+
+ // Now that we know that there are no bundle symbolic name and version
+ // attributes, add them since the spec says they are there implicitly.
+ clause.attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
+ clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bv);
+ }
+
+ return clauses;
+ }
+
+ private static List<Capability> convertExports(
+ List<ParsedHeaderClause> clauses, Resource resource) {
+ List<Capability> capList = new ArrayList<Capability>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String pkgName : clause.paths) {
+ // Prepend the package name to the array of attributes.
+ Map<String, Object> attrs = clause.attrs;
+ Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
+ newAttrs.putAll(attrs);
+ newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName);
+
+ // Create package capability and add to capability list.
+ capList.add(new CapabilityImpl(resource, BundleRevision.PACKAGE_NAMESPACE, clause.dirs, newAttrs));
+ }
+ }
+
+ return capList;
+ }
+
+ private static String getManifestVersion(Map<String, String> headerMap) {
+ String manifestVersion = headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
+ return (manifestVersion == null) ? "1" : manifestVersion.trim();
+ }
+
+ private static List<ParsedHeaderClause> calculateImplicitImports(
+ List<BundleCapability> exports, List<ParsedHeaderClause> imports)
+ throws BundleException {
+ List<ParsedHeaderClause> clauseList = new ArrayList<ParsedHeaderClause>();
+
+ // Since all R3 exports imply an import, add a corresponding
+ // requirement for each existing export capability. Do not
+ // duplicate imports.
+ Map<String, String> map = new HashMap<String, String>();
+ // Add existing imports.
+ for (ParsedHeaderClause anImport : imports) {
+ for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
+ map.put(anImport.paths.get(pathIdx), anImport.paths.get(pathIdx));
+ }
+ }
+ // Add import requirement for each export capability.
+ for (BundleCapability export : exports) {
+ if (map.get(export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()) == null) {
+ // Convert Version to VersionRange.
+ Object version = export.getAttributes().get(Constants.VERSION_ATTRIBUTE);
+ ParsedHeaderClause clause = new ParsedHeaderClause();
+ if (version != null) {
+ clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(version.toString()));
+ }
+ clause.paths.add((String) export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
+ clauseList.add(clause);
+ }
+ }
+
+ return clauseList;
+ }
+
+ private static List<Capability> calculateImplicitUses(
+ List<Capability> exports, List<ParsedHeaderClause> imports)
+ throws BundleException {
+ // Add a "uses" directive onto each export of R3 bundles
+ // that references every other import (which will include
+ // exports, since export implies import); this is
+ // necessary since R3 bundles assumed a single class space,
+ // but R4 allows for multiple class spaces.
+ String usesValue = "";
+ for (ParsedHeaderClause anImport : imports) {
+ for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
+ usesValue = usesValue
+ + ((usesValue.length() > 0) ? "," : "")
+ + anImport.paths.get(pathIdx);
+ }
+ }
+ for (int i = 0; i < exports.size(); i++) {
+ Map<String, String> dirs = new HashMap<String, String>(1);
+ dirs.put(Constants.USES_DIRECTIVE, usesValue);
+ exports.set(i, new CapabilityImpl(
+ exports.get(i).getResource(),
+ BundleRevision.PACKAGE_NAMESPACE,
+ dirs,
+ exports.get(i).getAttributes()));
+ }
+
+ return exports;
+ }
+
+ private static ParsedHeaderClause parseBundleSymbolicName(Map<String, String> headerMap)
+ throws BundleException {
+ List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+ if (clauses.size() > 0) {
+ if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
+ throw new BundleException("Cannot have multiple symbolic names: " + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+ }
+
+ // Get bundle version.
+ Version bundleVersion = Version.emptyVersion;
+ if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
+ bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
+ }
+
+ // Create a require capability and return it.
+ ParsedHeaderClause clause = clauses.get(0);
+ String symName = clause.paths.get(0);
+ clause.attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName);
+ clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
+ return clause;
+ }
+
+ return null;
+ }
+
+ private static List<RequirementImpl> parseFragmentHost(
+ Resource resource, Map<String, String> headerMap)
+ throws BundleException {
+ List<RequirementImpl> reqs = new ArrayList<RequirementImpl>();
+
+ List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.FRAGMENT_HOST));
+ if (clauses.size() > 0) {
+ // Make sure that only one fragment host symbolic name is specified.
+ if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
+ throw new BundleException("Fragments cannot have multiple hosts: " + headerMap.get(Constants.FRAGMENT_HOST));
+ }
+
+ // If the bundle-version attribute is specified, then convert
+ // it to the proper type.
+ Object value = clauses.get(0).attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ value = (value == null) ? "0.0.0" : value;
+ clauses.get(0).attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
+
+ // Note that we use a linked hash map here to ensure the
+ // host symbolic name is first, which will make indexing
+ // more efficient.
+ // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+ // Prepend the host symbolic name to the map of attributes.
+ Map<String, Object> attrs = clauses.get(0).attrs;
+ Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+ // We want this first from an indexing perspective.
+ newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
+ newAttrs.putAll(attrs);
+ // But we need to put it again to make sure it wasn't overwritten.
+ newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
+
+ // Create filter now so we can inject filter directive.
+ SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+ // Inject filter directive.
+ // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+ Map<String, String> dirs = clauses.get(0).dirs;
+ Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+ newDirs.putAll(dirs);
+ newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+ reqs.add(new RequirementImpl(
+ resource, BundleRevision.HOST_NAMESPACE,
+ newDirs,
+ newAttrs));
+ }
+
+ return reqs;
+ }
+
+ private static List<ParsedHeaderClause> normalizeRequireClauses(List<ParsedHeaderClause> clauses) {
+ // Convert bundle version attribute to VersionRange type.
+ for (ParsedHeaderClause clause : clauses) {
+ Object value = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+ if (value != null) {
+ clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
+ }
+ }
+
+ return clauses;
+ }
+
+ private static List<Requirement> convertRequires(List<ParsedHeaderClause> clauses, Resource resource) {
+ List<Requirement> reqList = new ArrayList<Requirement>();
+ for (ParsedHeaderClause clause : clauses) {
+ for (String path : clause.paths) {
+ // Prepend the bundle symbolic name to the array of attributes.
+ Map<String, Object> attrs = clause.attrs;
+ // Note that we use a linked hash map here to ensure the
+ // symbolic name attribute is first, which will make indexing
+ // more efficient.
+ // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+ // Prepend the symbolic name to the array of attributes.
+ Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+ // We want this first from an indexing perspective.
+ newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
+ newAttrs.putAll(attrs);
+ // But we need to put it again to make sure it wasn't overwritten.
+ newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
+
+ // Create filter now so we can inject filter directive.
+ SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+ // Inject filter directive.
+ // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+ Map<String, String> dirs = clause.dirs;
+ Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+ newDirs.putAll(dirs);
+ newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+ // Create package requirement and add to requirement list.
+ reqList.add(new RequirementImpl(resource, BundleRevision.BUNDLE_NAMESPACE, newDirs, newAttrs));
+ }
+ }
+
+ return reqList;
+ }
+
+ private static final char EOF = (char) -1;
+
+ private static char charAt(int pos, String headers, int length)
+ {
+ if (pos >= length)
+ {
+ return EOF;
+ }
+ return headers.charAt(pos);
+ }
+
+ private static final int CLAUSE_START = 0;
+ private static final int PARAMETER_START = 1;
+ private static final int KEY = 2;
+ private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
+ private static final int ARGUMENT = 8;
+ private static final int VALUE = 16;
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static List<ParsedHeaderClause> parseStandardHeader(String header)
+ {
+ List<ParsedHeaderClause> clauses = new ArrayList<ParsedHeaderClause>();
+ if (header == null)
+ {
+ return clauses;
+ }
+ ParsedHeaderClause clause = null;
+ String key = null;
+ Map targetMap = null;
+ int state = CLAUSE_START;
+ int currentPosition = 0;
+ int startPosition = 0;
+ int length = header.length();
+ boolean quoted = false;
+ boolean escaped = false;
+
+ char currentChar = EOF;
+ do
+ {
+ currentChar = charAt(currentPosition, header, length);
+ switch (state)
+ {
+ case CLAUSE_START:
+ clause = new ParsedHeaderClause();
+ clauses.add(clause);
+ state = PARAMETER_START;
+ case PARAMETER_START:
+ startPosition = currentPosition;
+ state = KEY;
+ case KEY:
+ switch (currentChar)
+ {
+ case ':':
+ case '=':
+ key = header.substring(startPosition, currentPosition).trim();
+ startPosition = currentPosition + 1;
+ targetMap = clause.attrs;
+ state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
+ break;
+ case EOF:
+ case ',':
+ case ';':
+ clause.paths.add(header.substring(startPosition, currentPosition).trim());
+ state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
+ break;
+ default:
+ break;
+ }
+ currentPosition++;
+ break;
+ case DIRECTIVE_OR_TYPEDATTRIBUTE:
+ switch(currentChar)
+ {
+ case '=':
+ if (startPosition != currentPosition)
+ {
+ clause.types.put(key, header.substring(startPosition, currentPosition).trim());
+ }
+ else
+ {
+ targetMap = clause.dirs;
+ }
+ state = ARGUMENT;
+ startPosition = currentPosition + 1;
+ break;
+ default:
+ break;
+ }
+ currentPosition++;
+ break;
+ case ARGUMENT:
+ if (currentChar == '\"')
+ {
+ quoted = true;
+ currentPosition++;
+ }
+ else
+ {
+ quoted = false;
+ }
+ if (!Character.isWhitespace(currentChar)) {
+ state = VALUE;
+ }
+ else {
+ currentPosition++;
+ }
+ break;
+ case VALUE:
+ if (escaped)
+ {
+ escaped = false;
+ }
+ else
+ {
+ if (currentChar == '\\' )
+ {
+ escaped = true;
+ }
+ else if (quoted && currentChar == '\"')
+ {
+ quoted = false;
+ }
+ else if (!quoted)
+ {
+ String value = null;
+ switch(currentChar)
+ {
+ case EOF:
+ case ';':
+ case ',':
+ value = header.substring(startPosition, currentPosition).trim();
+ if (value.startsWith("\"") && value.endsWith("\""))
+ {
+ value = value.substring(1, value.length() - 1);
+ }
+ if (targetMap.put(key, value) != null)
+ {
+ throw new IllegalArgumentException(
+ "Duplicate '" + key + "' in: " + header);
+ }
+ state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ currentPosition++;
+ break;
+ default:
+ break;
+ }
+ } while ( currentChar != EOF);
+
+ if (state > PARAMETER_START)
+ {
+ throw new IllegalArgumentException("Unable to parse header: " + header);
+ }
+ return clauses;
+ }
+
+ public static List<String> parseDelimitedString(String value, String delim)
+ {
+ return parseDelimitedString(value, delim, true);
+ }
+
+ /**
+ * Parses delimited string and returns an array containing the tokens. This
+ * parser obeys quotes, so the delimiter character will be ignored if it is
+ * inside of a quote. This method assumes that the quote character is not
+ * included in the set of delimiter characters.
+ * @param value the delimited string to parse.
+ * @param delim the characters delimiting the tokens.
+ * @return a list of string or an empty list if there are none.
+ **/
+ public static List<String> parseDelimitedString(String value, String delim, boolean trim)
+ {
+ if (value == null)
+ {
+ value = "";
+ }
+
+ List<String> list = new ArrayList();
+
+ int CHAR = 1;
+ int DELIMITER = 2;
+ int STARTQUOTE = 4;
+ int ENDQUOTE = 8;
+
+ StringBuffer sb = new StringBuffer();
+
+ int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+ boolean isEscaped = false;
+ for (int i = 0; i < value.length(); i++)
+ {
+ char c = value.charAt(i);
+
+ boolean isDelimiter = (delim.indexOf(c) >= 0);
+
+ if (!isEscaped && (c == '\\'))
+ {
+ isEscaped = true;
+ continue;
+ }
+
+ if (isEscaped)
+ {
+ sb.append(c);
+ }
+ else if (isDelimiter && ((expecting & DELIMITER) > 0))
+ {
+ if (trim)
+ {
+ list.add(sb.toString().trim());
+ }
+ else
+ {
+ list.add(sb.toString());
+ }
+ sb.delete(0, sb.length());
+ expecting = (CHAR | DELIMITER | STARTQUOTE);
+ }
+ else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
+ {
+ sb.append(c);
+ expecting = CHAR | ENDQUOTE;
+ }
+ else if ((c == '"') && ((expecting & ENDQUOTE) > 0))
+ {
+ sb.append(c);
+ expecting = (CHAR | STARTQUOTE | DELIMITER);
+ }
+ else if ((expecting & CHAR) > 0)
+ {
+ sb.append(c);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Invalid delimited string: " + value);
+ }
+
+ isEscaped = false;
+ }
+
+ if (sb.length() > 0)
+ {
+ if (trim)
+ {
+ list.add(sb.toString().trim());
+ }
+ else
+ {
+ list.add(sb.toString());
+ }
+ }
+
+ return list;
+ }
+
+
+ static class ParsedHeaderClause {
+ public final List<String> paths = new ArrayList<String>();
+ public final Map<String, String> dirs = new LinkedHashMap<String, String>();
+ public final Map<String, Object> attrs = new LinkedHashMap<String, Object>();
+ public final Map<String, String> types = new LinkedHashMap<String, String>();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
new file mode 100644
index 0000000..18e0dc3
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public class ResourceImpl implements Resource {
+
+ private final List<Capability> m_caps;
+ private final List<Requirement> m_reqs;
+
+ public ResourceImpl(String name, Version version) {
+ this(name, IdentityNamespace.TYPE_BUNDLE, version);
+ }
+
+ public ResourceImpl(String name, String type, Version version)
+ {
+ m_caps = new ArrayList<Capability>();
+ m_caps.add(0, new IdentityCapability(this, name, type, version));
+ m_reqs = new ArrayList<Requirement>();
+ }
+
+ public void addCapability(Capability capability) {
+ assert capability.getResource() == this;
+ m_caps.add(capability);
+ }
+
+ public void addCapabilities(Iterable<? extends Capability> capabilities) {
+ for (Capability cap : capabilities) {
+ addCapability(cap);
+ }
+ }
+
+ public void addRequirement(Requirement requirement) {
+ assert requirement.getResource() == this;
+ m_reqs.add(requirement);
+ }
+
+ public void addRequirements(Iterable<? extends Requirement> requirements) {
+ for (Requirement req : requirements) {
+ addRequirement(req);
+ }
+ }
+
+ public List<Capability> getCapabilities(String namespace)
+ {
+ List<Capability> result = m_caps;
+ if (namespace != null)
+ {
+ result = new ArrayList<Capability>();
+ for (Capability cap : m_caps)
+ {
+ if (cap.getNamespace().equals(namespace))
+ {
+ result.add(cap);
+ }
+ }
+ }
+ return result;
+ }
+
+ public List<Requirement> getRequirements(String namespace)
+ {
+ List<Requirement> result = m_reqs;
+ if (namespace != null)
+ {
+ result = new ArrayList<Requirement>();
+ for (Requirement req : m_reqs)
+ {
+ if (req.getNamespace().equals(namespace))
+ {
+ result.add(req);
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String toString()
+ {
+ Capability cap = getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
+ return cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/"
+ + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
new file mode 100644
index 0000000..4fe3bf8
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import org.osgi.resource.Namespace;
+
+/**
+ */
+public final class ServiceNamespace extends Namespace {
+
+ public static final String SERVICE_NAMESPACE = "service-reference";
+
+ private ServiceNamespace() {
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
new file mode 100644
index 0000000..ae10441
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
@@ -0,0 +1,649 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.felix.utils.version.VersionRange;
+
+public class SimpleFilter
+{
+ public static final int MATCH_ALL = 0;
+ public static final int AND = 1;
+ public static final int OR = 2;
+ public static final int NOT = 3;
+ public static final int EQ = 4;
+ public static final int LTE = 5;
+ public static final int GTE = 6;
+ public static final int SUBSTRING = 7;
+ public static final int PRESENT = 8;
+ public static final int APPROX = 9;
+
+ private final String m_name;
+ private final Object m_value;
+ private final int m_op;
+
+ public SimpleFilter(String attr, Object value, int op)
+ {
+ m_name = attr;
+ m_value = value;
+ m_op = op;
+ }
+
+ public String getName()
+ {
+ return m_name;
+ }
+
+ public Object getValue()
+ {
+ return m_value;
+ }
+
+ public int getOperation()
+ {
+ return m_op;
+ }
+
+ public String toString()
+ {
+ String s = null;
+ switch (m_op)
+ {
+ case AND:
+ s = "(&" + toString((List) m_value) + ")";
+ break;
+ case OR:
+ s = "(|" + toString((List) m_value) + ")";
+ break;
+ case NOT:
+ s = "(!" + toString((List) m_value) + ")";
+ break;
+ case EQ:
+ s = "(" + m_name + "=" + toEncodedString(m_value) + ")";
+ break;
+ case LTE:
+ s = "(" + m_name + "<=" + toEncodedString(m_value) + ")";
+ break;
+ case GTE:
+ s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
+ break;
+ case SUBSTRING:
+ s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
+ break;
+ case PRESENT:
+ s = "(" + m_name + "=*)";
+ break;
+ case APPROX:
+ s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
+ break;
+ case MATCH_ALL:
+ s = "(*)";
+ break;
+ }
+ return s;
+ }
+
+ private static String toString(List list)
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < list.size(); i++)
+ {
+ sb.append(list.get(i).toString());
+ }
+ return sb.toString();
+ }
+
+ private static String toDecodedString(String s, int startIdx, int endIdx)
+ {
+ StringBuffer sb = new StringBuffer(endIdx - startIdx);
+ boolean escaped = false;
+ for (int i = 0; i < (endIdx - startIdx); i++)
+ {
+ char c = s.charAt(startIdx + i);
+ if (!escaped && (c == '\\'))
+ {
+ escaped = true;
+ }
+ else
+ {
+ escaped = false;
+ sb.append(c);
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private static String toEncodedString(Object o)
+ {
+ if (o instanceof String)
+ {
+ String s = (String) o;
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+ if ((c == '\\') || (c == '(') || (c == ')') || (c == '*'))
+ {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+
+ o = sb.toString();
+ }
+
+ return o.toString();
+ }
+
+ public static SimpleFilter parse(String filter)
+ {
+ int idx = skipWhitespace(filter, 0);
+
+ if ((filter == null) || (filter.length() == 0) || (idx >= filter.length()))
+ {
+ throw new IllegalArgumentException("Null or empty filter.");
+ }
+ else if (filter.charAt(idx) != '(')
+ {
+ throw new IllegalArgumentException("Missing opening parenthesis: " + filter);
+ }
+
+ SimpleFilter sf = null;
+ List stack = new ArrayList();
+ boolean isEscaped = false;
+ while (idx < filter.length())
+ {
+ if (sf != null)
+ {
+ throw new IllegalArgumentException(
+ "Only one top-level operation allowed: " + filter);
+ }
+
+ if (!isEscaped && (filter.charAt(idx) == '('))
+ {
+ // Skip paren and following whitespace.
+ idx = skipWhitespace(filter, idx + 1);
+
+ if (filter.charAt(idx) == '&')
+ {
+ int peek = skipWhitespace(filter, idx + 1);
+ if (filter.charAt(peek) == '(')
+ {
+ idx = peek - 1;
+ stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.AND));
+ }
+ else
+ {
+ stack.add(0, new Integer(idx));
+ }
+ }
+ else if (filter.charAt(idx) == '|')
+ {
+ int peek = skipWhitespace(filter, idx + 1);
+ if (filter.charAt(peek) == '(')
+ {
+ idx = peek - 1;
+ stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.OR));
+ }
+ else
+ {
+ stack.add(0, new Integer(idx));
+ }
+ }
+ else if (filter.charAt(idx) == '!')
+ {
+ int peek = skipWhitespace(filter, idx + 1);
+ if (filter.charAt(peek) == '(')
+ {
+ idx = peek - 1;
+ stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT));
+ }
+ else
+ {
+ stack.add(0, new Integer(idx));
+ }
+ }
+ else
+ {
+ stack.add(0, new Integer(idx));
+ }
+ }
+ else if (!isEscaped && (filter.charAt(idx) == ')'))
+ {
+ Object top = stack.remove(0);
+ if (top instanceof SimpleFilter)
+ {
+ if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+ {
+ ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
+ }
+ else
+ {
+ sf = (SimpleFilter) top;
+ }
+ }
+ else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+ {
+ ((List) ((SimpleFilter) stack.get(0)).m_value).add(
+ SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx));
+ }
+ else
+ {
+ sf = SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx);
+ }
+ }
+ else if (!isEscaped && (filter.charAt(idx) == '\\'))
+ {
+ isEscaped = true;
+ }
+ else
+ {
+ isEscaped = false;
+ }
+
+ idx = skipWhitespace(filter, idx + 1);
+ }
+
+ if (sf == null)
+ {
+ throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
+ }
+
+ return sf;
+ }
+
+ private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
+ {
+ final String opChars = "=<>~";
+
+ // Determine the ending index of the attribute name.
+ int attrEndIdx = startIdx;
+ for (int i = 0; i < (endIdx - startIdx); i++)
+ {
+ char c = filter.charAt(startIdx + i);
+ if (opChars.indexOf(c) >= 0)
+ {
+ break;
+ }
+ else if (!Character.isWhitespace(c))
+ {
+ attrEndIdx = startIdx + i + 1;
+ }
+ }
+ if (attrEndIdx == startIdx)
+ {
+ throw new IllegalArgumentException(
+ "Missing attribute name: " + filter.substring(startIdx, endIdx));
+ }
+ String attr = filter.substring(startIdx, attrEndIdx);
+
+ // Skip the attribute name and any following whitespace.
+ startIdx = skipWhitespace(filter, attrEndIdx);
+
+ // Determine the operator type.
+ int op = -1;
+ switch (filter.charAt(startIdx))
+ {
+ case '=':
+ op = EQ;
+ startIdx++;
+ break;
+ case '<':
+ if (filter.charAt(startIdx + 1) != '=')
+ {
+ throw new IllegalArgumentException(
+ "Unknown operator: " + filter.substring(startIdx, endIdx));
+ }
+ op = LTE;
+ startIdx += 2;
+ break;
+ case '>':
+ if (filter.charAt(startIdx + 1) != '=')
+ {
+ throw new IllegalArgumentException(
+ "Unknown operator: " + filter.substring(startIdx, endIdx));
+ }
+ op = GTE;
+ startIdx += 2;
+ break;
+ case '~':
+ if (filter.charAt(startIdx + 1) != '=')
+ {
+ throw new IllegalArgumentException(
+ "Unknown operator: " + filter.substring(startIdx, endIdx));
+ }
+ op = APPROX;
+ startIdx += 2;
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Unknown operator: " + filter.substring(startIdx, endIdx));
+ }
+
+ // Parse value.
+ Object value = toDecodedString(filter, startIdx, endIdx);
+
+ // Check if the equality comparison is actually a substring
+ // or present operation.
+ if (op == EQ)
+ {
+ String valueStr = filter.substring(startIdx, endIdx);
+ List<String> values = parseSubstring(valueStr);
+ if ((values.size() == 2)
+ && (values.get(0).length() == 0)
+ && (values.get(1).length() == 0))
+ {
+ op = PRESENT;
+ }
+ else if (values.size() > 1)
+ {
+ op = SUBSTRING;
+ value = values;
+ }
+ }
+
+ return new SimpleFilter(attr, value, op);
+ }
+
+ public static List<String> parseSubstring(String value)
+ {
+ List<String> pieces = new ArrayList();
+ StringBuffer ss = new StringBuffer();
+ // int kind = SIMPLE; // assume until proven otherwise
+ boolean wasStar = false; // indicates last piece was a star
+ boolean leftstar = false; // track if the initial piece is a star
+ boolean rightstar = false; // track if the final piece is a star
+
+ int idx = 0;
+
+ // We assume (sub)strings can contain leading and trailing blanks
+ boolean escaped = false;
+ loop: for (;;)
+ {
+ if (idx >= value.length())
+ {
+ if (wasStar)
+ {
+ // insert last piece as "" to handle trailing star
+ rightstar = true;
+ }
+ else
+ {
+ pieces.add(ss.toString());
+ // accumulate the last piece
+ // note that in the case of
+ // (cn=); this might be
+ // the string "" (!=null)
+ }
+ ss.setLength(0);
+ break loop;
+ }
+
+ // Read the next character and account for escapes.
+ char c = value.charAt(idx++);
+ if (!escaped && (c == '*'))
+ {
+ // If we have successive '*' characters, then we can
+ // effectively collapse them by ignoring succeeding ones.
+ if (!wasStar)
+ {
+ if (ss.length() > 0)
+ {
+ pieces.add(ss.toString()); // accumulate the pieces
+ // between '*' occurrences
+ }
+ ss.setLength(0);
+ // if this is a leading star, then track it
+ if (pieces.isEmpty())
+ {
+ leftstar = true;
+ }
+ wasStar = true;
+ }
+ }
+ else if (!escaped && (c == '\\'))
+ {
+ escaped = true;
+ }
+ else
+ {
+ escaped = false;
+ wasStar = false;
+ ss.append(c);
+ }
+ }
+ if (leftstar || rightstar || pieces.size() > 1)
+ {
+ // insert leading and/or trailing "" to anchor ends
+ if (rightstar)
+ {
+ pieces.add("");
+ }
+ if (leftstar)
+ {
+ pieces.add(0, "");
+ }
+ }
+ return pieces;
+ }
+
+ public static String unparseSubstring(List<String> pieces)
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < pieces.size(); i++)
+ {
+ if (i > 0)
+ {
+ sb.append("*");
+ }
+ sb.append(toEncodedString(pieces.get(i)));
+ }
+ return sb.toString();
+ }
+
+ public static boolean compareSubstring(List<String> pieces, String s)
+ {
+ // Walk the pieces to match the string
+ // There are implicit stars between each piece,
+ // and the first and last pieces might be "" to anchor the match.
+ // assert (pieces.length > 1)
+ // minimal case is <string>*<string>
+
+ boolean result = true;
+ int len = pieces.size();
+
+ // Special case, if there is only one piece, then
+ // we must perform an equality test.
+ if (len == 1)
+ {
+ return s.equals(pieces.get(0));
+ }
+
+ // Otherwise, check whether the pieces match
+ // the specified string.
+
+ int index = 0;
+
+ loop: for (int i = 0; i < len; i++)
+ {
+ String piece = pieces.get(i);
+
+ // If this is the first piece, then make sure the
+ // string starts with it.
+ if (i == 0)
+ {
+ if (!s.startsWith(piece))
+ {
+ result = false;
+ break loop;
+ }
+ }
+
+ // If this is the last piece, then make sure the
+ // string ends with it.
+ if (i == (len - 1))
+ {
+ if (s.endsWith(piece) && (s.length() >= (index + piece.length())))
+ {
+ result = true;
+ }
+ else
+ {
+ result = false;
+ }
+ break loop;
+ }
+
+ // If this is neither the first or last piece, then
+ // make sure the string contains it.
+ if ((i > 0) && (i < (len - 1)))
+ {
+ index = s.indexOf(piece, index);
+ if (index < 0)
+ {
+ result = false;
+ break loop;
+ }
+ }
+
+ // Move string index beyond the matching piece.
+ index += piece.length();
+ }
+
+ return result;
+ }
+
+ private static int skipWhitespace(String s, int startIdx)
+ {
+ int len = s.length();
+ while ((startIdx < len) && Character.isWhitespace(s.charAt(startIdx)))
+ {
+ startIdx++;
+ }
+ return startIdx;
+ }
+
+ /**
+ * Converts a attribute map to a filter. The filter is created by iterating
+ * over the map's entry set. If ordering of attributes is important (e.g.,
+ * for hitting attribute indices), then the map's entry set should iterate
+ * in the desired order. Equality testing is assumed for all attribute types
+ * other than version ranges, which are handled appropriated. If the attribute
+ * map is empty, then a filter that matches anything is returned.
+ * @param attrs Map of attributes to convert to a filter.
+ * @return A filter corresponding to the attributes.
+ */
+ public static SimpleFilter convert(Map<String, Object> attrs)
+ {
+ // Rather than building a filter string to be parsed into a SimpleFilter,
+ // we will just create the parsed SimpleFilter directly.
+
+ List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
+
+ for (Entry<String, Object> entry : attrs.entrySet())
+ {
+ if (entry.getValue() instanceof VersionRange)
+ {
+ VersionRange vr = (VersionRange) entry.getValue();
+ if (!vr.isOpenFloor())
+ {
+ filters.add(
+ new SimpleFilter(
+ entry.getKey(),
+ vr.getFloor().toString(),
+ SimpleFilter.GTE));
+ }
+ else
+ {
+ SimpleFilter not =
+ new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+ ((List) not.getValue()).add(
+ new SimpleFilter(
+ entry.getKey(),
+ vr.getFloor().toString(),
+ SimpleFilter.LTE));
+ filters.add(not);
+ }
+
+ if (vr.getCeiling() != null)
+ {
+ if (!vr.isOpenCeiling())
+ {
+ filters.add(
+ new SimpleFilter(
+ entry.getKey(),
+ vr.getCeiling().toString(),
+ SimpleFilter.LTE));
+ }
+ else
+ {
+ SimpleFilter not =
+ new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+ ((List) not.getValue()).add(
+ new SimpleFilter(
+ entry.getKey(),
+ vr.getCeiling().toString(),
+ SimpleFilter.GTE));
+ filters.add(not);
+ }
+ }
+ }
+ else
+ {
+ List<String> values = SimpleFilter.parseSubstring(entry.getValue().toString());
+ if (values.size() > 1)
+ {
+ filters.add(
+ new SimpleFilter(
+ entry.getKey(),
+ values,
+ SimpleFilter.SUBSTRING));
+ }
+ else
+ {
+ filters.add(
+ new SimpleFilter(
+ entry.getKey(),
+ values.get(0),
+ SimpleFilter.EQ));
+ }
+ }
+ }
+
+ SimpleFilter sf = null;
+
+ if (filters.size() == 1)
+ {
+ sf = filters.get(0);
+ }
+ else if (attrs.size() > 1)
+ {
+ sf = new SimpleFilter(null, filters, SimpleFilter.AND);
+ }
+ else if (filters.isEmpty())
+ {
+ sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+ }
+
+ return sf;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
new file mode 100644
index 0000000..2f4a1f3
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import org.slf4j.Logger;
+
+/**
+ */
+public class Slf4jResolverLog extends org.apache.felix.resolver.Logger {
+
+ private final Logger logger;
+
+ public Slf4jResolverLog(Logger logger) {
+ super(LOG_DEBUG);
+ this.logger = logger;
+ }
+
+ @Override
+ protected void doLog(int level, String msg, Throwable throwable) {
+ switch (level) {
+ case LOG_ERROR:
+ logger.error(msg, throwable);
+ break;
+ case LOG_WARNING:
+ logger.warn(msg, throwable);
+ break;
+ case LOG_INFO:
+ logger.info(msg, throwable);
+ break;
+ case LOG_DEBUG:
+ logger.debug(msg, throwable);
+ break;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
new file mode 100644
index 0000000..b5158bf
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.List;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public final class UriNamespace extends Namespace {
+
+ public static final String URI_NAMESPACE = "karaf.uri";
+
+ public static String getUri(Resource resource)
+ {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps)
+ {
+ if (cap.getNamespace().equals(UriNamespace.URI_NAMESPACE))
+ {
+ return cap.getAttributes().get(UriNamespace.URI_NAMESPACE).toString();
+ }
+ }
+ return null;
+ }
+
+
+ private UriNamespace() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
new file mode 100644
index 0000000..44e9a7c
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.net.URI;
+
+/**
+ * Simple abstraction of a maven artifact to avoid external deps
+ */
+public class Artifact {
+ String groupId;
+ String artifactId;
+ String version;
+ String extension;
+ String classifier;
+
+ public Artifact(String coords) {
+ String[] coordsAr = coords.split(":");
+ if (coordsAr.length != 5) {
+ throw new IllegalArgumentException("Maven URL " + coords + " is malformed or not complete");
+ }
+ this.groupId = coordsAr[0];
+ this.artifactId = coordsAr[1];
+ this.version = coordsAr[4];
+ this.extension = coordsAr[2];
+ this.classifier = coordsAr[3];
+ }
+
+ public Artifact(String coords, String version) {
+ this(coords);
+ this.version = version;
+ }
+
+ public URI getMavenUrl(String version) {
+ String uriSt = "mvn:" + this.groupId + "/" + this.artifactId + "/" + version + "/" + this.extension + "/" + this.classifier;
+ try {
+ return new URI(uriSt);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
[22/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
deleted file mode 100644
index 2d5dd98..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.deployment;
-
-import java.net.MalformedURLException;
-
-import org.apache.karaf.features.internal.util.MultiException;
-
-public interface Downloader {
-
- void await() throws InterruptedException, MultiException;
-
- void download(String location, DownloadCallback downloadCallback) throws MalformedURLException;
-
- interface DownloadCallback {
-
- void downloaded(StreamProvider provider) throws Exception;
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
deleted file mode 100644
index 60a3dfc..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.deployment;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public interface StreamProvider {
-
- InputStream open() throws IOException;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java b/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
deleted file mode 100644
index b1a5865..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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.
- */
-package org.apache.karaf.features.internal.management;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Hashtable;
-import java.util.List;
-
-import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.ObjectName;
-import javax.management.openmbean.TabularData;
-
-import org.apache.karaf.features.*;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-import org.apache.karaf.features.management.codec.JmxFeature;
-import org.apache.karaf.features.management.codec.JmxFeatureEvent;
-import org.apache.karaf.features.management.codec.JmxRepository;
-import org.apache.karaf.features.management.codec.JmxRepositoryEvent;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * Implementation of {@link FeaturesServiceMBean}.
- */
-public class FeaturesServiceMBeanImpl extends StandardEmitterMBean implements
- MBeanRegistration, FeaturesServiceMBean {
-
- private ServiceRegistration<FeaturesListener> registration;
-
- private BundleContext bundleContext;
-
- private ObjectName objectName;
-
- private volatile long sequenceNumber = 0;
-
- private org.apache.karaf.features.FeaturesService featuresService;
-
- public FeaturesServiceMBeanImpl() throws NotCompliantMBeanException {
- super(FeaturesServiceMBean.class);
- }
-
- public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
- objectName = name;
- return name;
- }
-
- public void postRegister(Boolean registrationDone) {
- registration = bundleContext.registerService(FeaturesListener.class,
- getFeaturesListener(), new Hashtable<String, String>());
- }
-
- public void preDeregister() throws Exception {
- registration.unregister();
- }
-
- public void postDeregister() {
- }
-
- /**
- * {@inheritDoc}
- */
- public TabularData getFeatures() throws Exception {
- try {
- List<Feature> allFeatures = Arrays.asList(featuresService.listFeatures());
- List<Feature> insFeatures = Arrays.asList(featuresService.listInstalledFeatures());
- ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
- for (Feature feature : allFeatures) {
- try {
- features.add(new JmxFeature(feature, insFeatures.contains(feature)));
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
- TabularData table = JmxFeature.tableFrom(features);
- return table;
- } catch (Throwable t) {
- t.printStackTrace();
- return null;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public TabularData getRepositories() throws Exception {
- try {
- List<Repository> allRepositories = Arrays.asList(featuresService.listRepositories());
- ArrayList<JmxRepository> repositories = new ArrayList<JmxRepository>();
- for (Repository repository : allRepositories) {
- try {
- repositories.add(new JmxRepository(repository));
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
- TabularData table = JmxRepository.tableFrom(repositories);
- return table;
- } catch (Throwable t) {
- t.printStackTrace();
- return null;
- }
- }
-
- public void addRepository(String uri) throws Exception {
- featuresService.addRepository(new URI(uri));
- }
-
- public void addRepository(String uri, boolean install) throws Exception {
- featuresService.addRepository(new URI(uri), install);
- }
-
- public void removeRepository(String uri) throws Exception {
- featuresService.removeRepository(new URI(uri));
- }
-
- public void removeRepository(String uri, boolean uninstall) throws Exception {
- featuresService.removeRepository(new URI(uri), uninstall);
- }
-
- public void installFeature(String name) throws Exception {
- featuresService.installFeature(name);
- }
-
- public void installFeature(String name, boolean noRefresh) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- featuresService.installFeature(name, options);
- }
-
- public void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- if (noStart) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
- }
- featuresService.installFeature(name, options);
- }
-
- public void installFeature(String name, String version) throws Exception {
- featuresService.installFeature(name, version);
- }
-
- public void installFeature(String name, String version, boolean noRefresh) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- featuresService.installFeature(name, version, options);
- }
-
- public void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- if (noStart) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
- }
- featuresService.installFeature(name, version, options);
- }
-
- public TabularData infoFeature(String name) throws Exception {
- try {
- Feature feature = featuresService.getFeature(name);
- return infoFeature(feature);
- } catch (Throwable t) {
- t.printStackTrace();
- return null;
- }
- }
-
- public TabularData infoFeature(String name, String version) throws Exception {
- try {
- Feature feature = featuresService.getFeature(name, version);
- return infoFeature(feature);
- } catch (Throwable t) {
- t.printStackTrace();
- return null;
- }
- }
-
- private TabularData infoFeature(Feature feature) throws Exception {
- JmxFeature jmxFeature = null;
- if (featuresService.isInstalled(feature)) {
- jmxFeature = new JmxFeature(feature, true);
- } else {
- jmxFeature = new JmxFeature(feature, false);
- }
- ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
- features.add(jmxFeature);
- TabularData table = JmxFeature.tableFrom(features);
- return table;
- }
-
- public void uninstallFeature(String name) throws Exception {
- featuresService.uninstallFeature(name);
- }
-
- public void uninstallFeature(String name, boolean noRefresh) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- featuresService.uninstallFeature(name, options);
- }
-
- public void uninstallFeature(String name, String version) throws Exception {
- featuresService.uninstallFeature(name, version);
- }
-
- public void uninstallFeature(String name, String version, boolean noRefresh) throws Exception {
- EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
- if (noRefresh) {
- options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
- }
- featuresService.uninstallFeature(name, version, options);
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
- public void setFeaturesService(org.apache.karaf.features.FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-
- public FeaturesListener getFeaturesListener() {
- return new FeaturesListener() {
- public void featureEvent(FeatureEvent event) {
- if (!event.isReplay()) {
- Notification notification = new Notification(FEATURE_EVENT_TYPE, objectName, sequenceNumber++);
- notification.setUserData(new JmxFeatureEvent(event).asCompositeData());
- sendNotification(notification);
- }
- }
-
- public void repositoryEvent(RepositoryEvent event) {
- if (!event.isReplay()) {
- Notification notification = new Notification(REPOSITORY_EVENT_TYPE, objectName, sequenceNumber++);
- notification.setUserData(new JmxRepositoryEvent(event).asCompositeData());
- sendNotification(notification);
- }
- }
-
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- return o.equals(this);
- }
-
- };
- }
-
- public MBeanNotificationInfo[] getNotificationInfo() {
- return getBroadcastInfo();
- }
-
- private static MBeanNotificationInfo[] getBroadcastInfo() {
- String type = Notification.class.getCanonicalName();
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(new String[]{FEATURE_EVENT_EVENT_TYPE},
- type, "Some features notification");
- MBeanNotificationInfo info2 = new MBeanNotificationInfo(new String[]{REPOSITORY_EVENT_EVENT_TYPE},
- type, "Some repository notification");
- return new MBeanNotificationInfo[]{info1, info2};
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java b/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
deleted file mode 100644
index 13a4b6c..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.
- */
-package org.apache.karaf.features.internal.management;
-
-import javax.management.*;
-
-public class StandardEmitterMBean extends StandardMBean implements NotificationEmitter {
-
- private final NotificationBroadcasterSupport emitter;
-
- @SuppressWarnings("rawtypes")
- public StandardEmitterMBean(Class mbeanInterface) throws NotCompliantMBeanException {
- super(mbeanInterface);
- this.emitter = new NotificationBroadcasterSupport() {
- @Override
- public MBeanNotificationInfo[] getNotificationInfo() {
- return StandardEmitterMBean.this.getNotificationInfo();
- }
- };
- }
-
- public void sendNotification(Notification notification) {
- emitter.sendNotification(notification);
- }
-
-
- public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
- emitter.removeNotificationListener(listener, filter, handback);
- }
-
- public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
- emitter.addNotificationListener(listener, filter, handback);
- }
-
- public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
- emitter.removeNotificationListener(listener);
- }
-
- public MBeanNotificationInfo[] getNotificationInfo() {
- return new MBeanNotificationInfo[0];
- }
-
- @Override
- public MBeanInfo getMBeanInfo() {
- MBeanInfo mbeanInfo = super.getMBeanInfo();
- if (mbeanInfo != null) {
- MBeanNotificationInfo[] notificationInfo = getNotificationInfo();
- mbeanInfo = new MBeanInfo(mbeanInfo.getClassName(), mbeanInfo.getDescription(), mbeanInfo.getAttributes(),
- mbeanInfo.getConstructors(), mbeanInfo.getOperations(), notificationInfo);
- }
- return mbeanInfo;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java b/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
deleted file mode 100644
index 7eebbe5..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import org.apache.karaf.features.BundleInfo;
-
-
-/**
- *
- * Deployable element to install.
- *
- *
- * <p>Java class for bundle complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="bundle">
- * <simpleContent>
- * <extension base="<http://www.w3.org/2001/XMLSchema>anyURI">
- * <attribute name="start-level" type="{http://www.w3.org/2001/XMLSchema}int" />
- * <attribute name="start" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- * <attribute name="dependency" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "bundle", propOrder = {
- "value"
-})
-public class Bundle implements BundleInfo {
-
- @XmlValue
- @XmlSchemaType(name = "anyURI")
- protected String value;
- @XmlAttribute(name = "start-level")
- protected Integer startLevel;
- @XmlAttribute
- protected Boolean start;// = true;
- @XmlAttribute
- protected Boolean dependency;
-
-
- public Bundle() {
- }
-
- public Bundle(String value) {
- this.value = value;
- }
-
- /**
- * Gets the value of the value property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLocation() {
- return value;
- }
-
- /**
- * Sets the value of the value property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLocation(String value) {
- this.value = value;
- }
-
- /**
- * Gets the value of the startLevel property.
- *
- * @return
- * possible object is
- * {@link Integer }
- *
- */
- public int getStartLevel() {
- return startLevel == null? 0: startLevel;
- }
-
- /**
- * Sets the value of the startLevel property.
- *
- * @param value
- * allowed object is
- * {@link Integer }
- *
- */
- public void setStartLevel(Integer value) {
- this.startLevel = value;
- }
-
- /**
- * Gets the value of the start property.
- *
- * @return
- * possible object is
- * {@link Boolean }
- *
- */
- public boolean isStart() {
- return start == null? true: start;
- }
-
- /**
- * Sets the value of the start property.
- *
- * @param value
- * allowed object is
- * {@link Boolean }
- *
- */
- public void setStart(Boolean value) {
- this.start = value;
- }
-
- /**
- * Gets the value of the dependency property.
- *
- * @return
- * possible object is
- * {@link Boolean }
- *
- */
- public boolean isDependency() {
- return dependency == null? false: dependency;
- }
-
- /**
- * Sets the value of the dependency property.
- *
- * @param value
- * allowed object is
- * {@link Boolean }
- *
- */
- public void setDependency(Boolean value) {
- this.dependency = value;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Bundle bundle = (Bundle) o;
-
- if (dependency != bundle.dependency) return false;
- if (start != bundle.start) return false;
- if (startLevel != bundle.startLevel) return false;
- if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = value != null ? value.hashCode() : 0;
- result = 31 * result + getStartLevel();
- result = 31 * result + (isStart() ? 1 : 0);
- result = 31 * result + (isDependency() ? 1 : 0);
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java b/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
deleted file mode 100644
index ef60454..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-import org.apache.karaf.features.BundleInfo;
-
-
-/**
- *
- * Additional capability for a feature.
- *
- *
- * <p>Java class for bundle complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="capability">
- * <simpleContent>
- * <extension base="<http://www.w3.org/2001/XMLSchema>string">
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "capability", propOrder = {
- "value"
-})
-public class Capability implements org.apache.karaf.features.Capability {
-
- @XmlValue
- protected String value;
-
-
- public Capability() {
- }
-
- public Capability(String value) {
- this.value = value;
- }
-
- public String getValue() {
- return value;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Capability bundle = (Capability) o;
-
- if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = value != null ? value.hashCode() : 0;
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java b/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
deleted file mode 100644
index ed0e8ff..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.karaf.features.Feature;
-
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "conditional", propOrder = {
- "condition",
- "config",
- "configfile",
- "feature",
- "bundle"
-})
-public class Conditional extends Content implements org.apache.karaf.features.Conditional {
-
- @XmlElement(name = "condition")
- protected List<String> condition;
-
- public List<String> getCondition() {
- if (condition == null) {
- this.condition = new ArrayList<String>();
- }
- return condition;
- }
-
- @Override
- public Feature asFeature(String name, String version) {
- String conditionName = name + "-condition-" + getConditionId().replaceAll("[^A-Za-z0-9 ]", "_");
- org.apache.karaf.features.internal.model.Feature f = new org.apache.karaf.features.internal.model.Feature(conditionName, version);
- f.getBundle().addAll(getBundle());
- f.getConfig().addAll(getConfig());
- f.getConfigfile().addAll(getConfigfile());
- f.getFeature().addAll(getFeature());
- return f;
- }
-
- private String getConditionId() {
- StringBuffer sb = new StringBuffer();
- for (String cond : getCondition()) {
- if (sb.length() > 0) {
- sb.append("_");
- }
- sb.append(cond);
- }
- return sb.toString();
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Config.java b/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
deleted file mode 100644
index a2c6674..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- *
- * Configuration entries which should be created during feature installation. This
- * configuration may be used with OSGi Configuration Admin.
- *
- *
- * <p>Java class for config complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="config">
- * <simpleContent>
- * <extension base="<http://www.w3.org/2001/XMLSchema>string">
- * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "config", propOrder = {
- "value"
-})
-public class Config {
-
- @XmlValue
- protected String value;
- @XmlAttribute(required = true)
- protected String name;
-
- /**
- * Gets the value of the value property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getValue() {
- return value;
- }
-
- /**
- * Sets the value of the value property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setValue(String value) {
- this.value = value;
- }
-
- /**
- * Gets the value of the name property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getName() {
- return name;
- }
-
- /**
- * Sets the value of the name property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setName(String value) {
- this.name = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java b/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
deleted file mode 100644
index e5d9d94..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import org.apache.karaf.features.ConfigFileInfo;
-
-
-/**
- *
- * Additional configuration files which should be created during feature installation.
- *
- *
- * <p>Java class for configFile complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="configFile">
- * <simpleContent>
- * <extension base="<http://www.w3.org/2001/XMLSchema>string">
- * <attribute name="finalname" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="override" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "configFile", propOrder = {
- "value"
-})
-public class ConfigFile implements ConfigFileInfo {
-
- @XmlValue
- protected String value;
- @XmlAttribute(required = true)
- protected String finalname;
- @XmlAttribute
- protected Boolean override;
-
- /**
- * Gets the value of the value property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLocation() {
- return value;
- }
-
- /**
- * Sets the value of the value property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLocation(String value) {
- this.value = value;
- }
-
- /**
- * Gets the value of the finalname property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getFinalname() {
- return finalname;
- }
-
- /**
- * Sets the value of the finalname property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setFinalname(String value) {
- this.finalname = value;
- }
-
- /**
- * Gets the value of the override property.
- *
- * @return
- * possible object is
- * {@link Boolean }
- *
- */
- public boolean isOverride() {
- return override == null? false: override;
- }
-
- /**
- * Sets the value of the override property.
- *
- * @param value
- * allowed object is
- * {@link Boolean }
- *
- */
- public void setOverride(Boolean value) {
- this.override = value;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Content.java b/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
deleted file mode 100644
index 756e4c1..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.model;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.xml.bind.annotation.XmlTransient;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
-
-@XmlTransient
-public class Content {
-
- protected List<Config> config;
- protected List<ConfigFile> configfile;
- protected List<Dependency> feature;
- protected List<Bundle> bundle;
-
- /**
- * Gets the value of the config property.
- * <p/>
- * <p/>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the config property.
- * <p/>
- * <p/>
- * For example, to add a new item, do as follows:
- * <pre>
- * getConfig().add(newItem);
- * </pre>
- * <p/>
- * <p/>
- * <p/>
- * Objects of the following type(s) are allowed in the list
- * {@link Config }
- */
- public List<Config> getConfig() {
- if (config == null) {
- config = new ArrayList<Config>();
- }
- return this.config;
- }
-
- /**
- * Gets the value of the configfile property.
- * <p/>
- * <p/>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the configfile property.
- * <p/>
- * <p/>
- * For example, to add a new item, do as follows:
- * <pre>
- * getConfigfile().add(newItem);
- * </pre>
- * <p/>
- * <p/>
- * <p/>
- * Objects of the following type(s) are allowed in the list
- * {@link ConfigFile }
- */
- public List<ConfigFile> getConfigfile() {
- if (configfile == null) {
- configfile = new ArrayList<ConfigFile>();
- }
- return this.configfile;
- }
-
- /**
- * Gets the value of the feature property.
- * <p/>
- * <p/>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the feature property.
- * <p/>
- * <p/>
- * For example, to add a new item, do as follows:
- * <pre>
- * getFeature().add(newItem);
- * </pre>
- * <p/>
- * <p/>
- * <p/>
- * Objects of the following type(s) are allowed in the list
- * {@link Dependency }
- */
- public List<Dependency> getFeature() {
- if (feature == null) {
- feature = new ArrayList<Dependency>();
- }
- return this.feature;
- }
-
- /**
- * Gets the value of the bundle property.
- * <p/>
- * <p/>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the bundle property.
- * <p/>
- * <p/>
- * For example, to add a new item, do as follows:
- * <pre>
- * getBundle().add(newItem);
- * </pre>
- * <p/>
- * <p/>
- * <p/>
- * Objects of the following type(s) are allowed in the list
- * {@link Bundle }
- */
- public List<Bundle> getBundle() {
- if (bundle == null) {
- bundle = new ArrayList<Bundle>();
- }
- return this.bundle;
- }
-
- public List<org.apache.karaf.features.Dependency> getDependencies() {
- return Collections.<org.apache.karaf.features.Dependency>unmodifiableList(getFeature());
- }
-
- public List<BundleInfo> getBundles() {
- return Collections.<BundleInfo>unmodifiableList(getBundle());
- }
-
- public Map<String, Map<String, String>> getConfigurations() {
- Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
- for (Config config : getConfig()) {
- String name = config.getName();
- StringReader propStream = new StringReader(config.getValue());
- Properties props = new Properties();
- try {
- props.load(propStream);
- } catch (IOException e) {
- //ignore??
- }
- interpolation(props);
- Map<String, String> propMap = new HashMap<String, String>();
- for (Map.Entry<Object, Object> entry : props.entrySet()) {
- propMap.put((String) entry.getKey(), (String) entry.getValue());
- }
- result.put(name, propMap);
- }
- return result;
- }
-
- public List<ConfigFileInfo> getConfigurationFiles() {
- return Collections.<ConfigFileInfo>unmodifiableList(getConfigfile());
- }
-
- @SuppressWarnings("rawtypes")
- protected void interpolation(Properties properties) {
- for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
- String key = (String) e.nextElement();
- String val = properties.getProperty(key);
- Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
- while (matcher.find()) {
- String rep = System.getProperty(matcher.group(1));
- if (rep != null) {
- val = val.replace(matcher.group(0), rep);
- matcher.reset(val);
- }
- }
- properties.put(key, val);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java b/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
deleted file mode 100644
index 9c92a93..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- *
- * Dependency of feature.
- *
- *
- * <p>Java class for dependency complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="dependency">
- * <simpleContent>
- * <extension base="<http://karaf.apache.org/xmlns/features/v1.0.0>featureName">
- * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "dependency", propOrder = {
- "value"
-})
-public class Dependency implements org.apache.karaf.features.Dependency {
-
- @XmlValue
- protected String value;
- @XmlAttribute
- protected String version;
-
- /**
- *
- * Feature name should be non empty string.
- *
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getName() {
- return value;
- }
-
- /**
- * Sets the value of the value property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setName(String value) {
- this.value = value;
- }
-
- /**
- * Gets the value of the version property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getVersion() {
- if (version == null) {
- return "0.0.0";
- } else {
- return version;
- }
- }
-
- /**
- * Sets the value of the version property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setVersion(String value) {
- this.version = value;
- }
-
- public String toString() {
- String ret = getName() + Feature.SPLIT_FOR_NAME_AND_VERSION + getVersion();
- return ret;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java b/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
deleted file mode 100644
index 46580da..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-package org.apache.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- *
- * Definition of the Feature.
- *
- *
- * <p>Java class for feature complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="feature">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="details" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- * <element name="config" type="{http://karaf.apache.org/xmlns/features/v1.0.0}config" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="configfile" type="{http://karaf.apache.org/xmlns/features/v1.0.0}configFile" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}dependency" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="bundle" type="{http://karaf.apache.org/xmlns/features/v1.0.0}bundle" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="conditional" type="{http://karaf.apache.org/xmlns/features/v1.0.0}conditional" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="capability" type="{http://karaf.apache.org/xmlns/features/v1.0.0}capability" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="requirement" type="{http://karaf.apache.org/xmlns/features/v1.0.0}requirement" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="name" use="required" type="{http://karaf.apache.org/xmlns/features/v1.0.0}featureName" />
- * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
- * <attribute name="description" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="resolver" type="{http://karaf.apache.org/xmlns/features/v1.0.0}resolver" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "feature", propOrder = {
- "details",
- "config",
- "configfile",
- "feature",
- "bundle",
- "conditional",
- "capability",
- "requirement"
-})
-public class Feature extends Content implements org.apache.karaf.features.Feature {
- public static String SPLIT_FOR_NAME_AND_VERSION = "/";
- public static String DEFAULT_VERSION = "0.0.0";
-
-
- protected String details;
- @XmlAttribute(required = true)
- protected String name;
- @XmlAttribute
- protected String version;
- @XmlAttribute
- protected String description;
- @XmlAttribute
- protected String resolver;
- @XmlAttribute
- protected String install;
- @XmlAttribute(name = "start-level")
- protected Integer startLevel;
- @XmlAttribute
- protected String region;
- protected List<Conditional> conditional;
- protected List<Capability> capability;
- protected List<Requirement> requirement;
-
- public Feature() {
- }
-
- public Feature(String name) {
- this.name = name;
- }
-
- public Feature(String name, String version) {
- this.name = name;
- this.version = version;
- }
-
-
- public static org.apache.karaf.features.Feature valueOf(String str) {
- if (str.contains(SPLIT_FOR_NAME_AND_VERSION)) {
- String strName = str.substring(0, str.indexOf(SPLIT_FOR_NAME_AND_VERSION));
- String strVersion = str.substring(str.indexOf(SPLIT_FOR_NAME_AND_VERSION)
- + SPLIT_FOR_NAME_AND_VERSION.length(), str.length());
- return new Feature(strName, strVersion);
- } else {
- return new Feature(str);
- }
-
-
- }
-
-
- public String getId() {
- return getName() + SPLIT_FOR_NAME_AND_VERSION + getVersion();
- }
-
- /**
- * Gets the value of the name property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getName() {
- return name;
- }
-
- /**
- * Sets the value of the name property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setName(String value) {
- this.name = value;
- }
-
- /**
- * Gets the value of the version property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getVersion() {
- if (version == null) {
- return DEFAULT_VERSION;
- } else {
- return version;
- }
- }
-
- /**
- * Sets the value of the version property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setVersion(String value) {
- this.version = value;
- }
-
- /**
- * Since version has a default value ("0.0.0"), returns
- * whether or not the version has been set.
- */
- public boolean hasVersion() {
- return this.version != null;
- }
-
- /**
- * Gets the value of the description property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getDescription() {
- return description;
- }
-
- /**
- * Sets the value of the description property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setDescription(String value) {
- this.description = value;
- }
-
- public String getDetails() {
- return details;
- }
-
- public void setDetails(String details) {
- this.details = details;
- }
-
- /**
- * Gets the value of the resolver property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getResolver() {
- return resolver;
- }
-
- public String getInstall() {
- return install;
- }
-
- public void setInstall(String install) {
- this.install = install;
- }
-
- /**
- * Sets the value of the resolver property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setResolver(String value) {
- this.resolver = value;
- }
-
- /**
- * Gets the value of the startLevel property.
- *
- * @return
- * possible object is
- * {@link Integer }
- *
- */
- public int getStartLevel() {
- return startLevel == null? 0: startLevel;
- }
-
- /**
- * Sets the value of the startLevel property.
- *
- * @param value
- * allowed object is
- * {@link Integer }
- *
- */
- public void setStartLevel(Integer value) {
- this.startLevel = value;
- }
-
-
- public String getRegion() {
- return region;
- }
-
- public void setRegion(String region) {
- this.region = region;
- }
-
- /**
- * Gets the value of the conditional property.
- * <p/>
- * <p/>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the feature property.
- * <p/>
- * <p/>
- * For example, to add a new item, do as follows:
- * <pre>
- * getConditionals().add(newItem);
- * </pre>
- * <p/>
- * <p/>
- * <p/>
- * Objects of the following type(s) are allowed in the list
- * {@link Conditional }
- */
- public List<Conditional> getConditional() {
- if (conditional == null) {
- conditional = new ArrayList<Conditional>();
- }
- return this.conditional;
- }
-
- public List<Capability> getCapabilities() {
- if (capability == null) {
- capability = new ArrayList<Capability>();
- }
- return this.capability;
- }
-
- public List<Requirement> getRequirements() {
- if (requirement == null) {
- requirement = new ArrayList<Requirement>();
- }
- return this.requirement;
- }
-
- public String toString() {
- return getId();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Feature feature = (Feature) o;
-
- if (name != null ? !name.equals(feature.name) : feature.name != null) return false;
- if (version != null ? !version.equals(feature.version) : feature.version != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = name != null ? name.hashCode() : 0;
- result = 31 * result + (version != null ? version.hashCode() : 0);
- return result;
- }
-
- @SuppressWarnings("rawtypes")
- protected void interpolation(Properties properties) {
- for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
- String key = (String) e.nextElement();
- String val = properties.getProperty(key);
- Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
- while (matcher.find()) {
- String rep = System.getProperty(matcher.group(1));
- if (rep != null) {
- val = val.replace(matcher.group(0), rep);
- matcher.reset(val);
- }
- }
- properties.put(key, val);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Features.java b/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
deleted file mode 100644
index e116f31..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-package org.apache.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- *
- * Root element of Feature definition. It contains optional attribute which allow
- * name of repository. This name will be used in shell to display source repository
- * of given feature.
- *
- *
- * <p>Java class for featuresRoot complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="features">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="repository" type="{http://www.w3.org/2001/XMLSchema}anyURI" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}feature" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlRootElement(name = "features")
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "features", propOrder = {
- "repository",
- "feature"
-})
-public class Features {
-
- @XmlSchemaType(name = "anyURI")
- protected List<String> repository;
- protected List<Feature> feature;
- @XmlAttribute
- protected String name;
-
- /**
- * Gets the value of the repository property.
- *
- * <p>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the repository property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getRepository().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link String }
- *
- *
- */
- public List<String> getRepository() {
- if (repository == null) {
- repository = new ArrayList<String>();
- }
- return this.repository;
- }
-
- /**
- * Gets the value of the feature property.
- *
- * <p>
- * This accessor method returns a reference to the live list,
- * not a snapshot. Therefore any modification you make to the
- * returned list will be present inside the JAXB object.
- * This is why there is not a <CODE>set</CODE> method for the feature property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getFeature().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link Feature }
- *
- *
- */
- public List<Feature> getFeature() {
- if (feature == null) {
- feature = new ArrayList<Feature>();
- }
- return this.feature;
- }
-
- /**
- * Gets the value of the name property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getName() {
- return name;
- }
-
- /**
- * Sets the value of the name property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setName(String value) {
- this.name = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
deleted file mode 100644
index 2036452..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.karaf.features.internal.model;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.net.URL;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.xml.XMLConstants;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.namespace.QName;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-
-import org.apache.karaf.features.FeaturesNamespaces;
-import org.apache.karaf.util.XmlUtils;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLFilter;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLFilterImpl;
-
-public class JaxbUtil {
-
- private static final JAXBContext FEATURES_CONTEXT;
- static {
- try {
- FEATURES_CONTEXT = JAXBContext.newInstance(Features.class);
- } catch (JAXBException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static void marshal(Features features, OutputStream out) throws JAXBException {
- Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
-
- marshaller.setProperty("jaxb.formatted.output", true);
-
- marshaller.marshal(features, out);
- }
-
- public static void marshal(Features features, Writer out) throws JAXBException {
- Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
-
- marshaller.setProperty("jaxb.formatted.output", true);
-
- marshaller.marshal(features, out);
- }
-
-
- /**
- * Read in a Features from the input stream.
- *
- * @param uri uri to read
- * @param validate whether to validate the input.
- * @return a Features read from the input stream
- */
- public static Features unmarshal(String uri, boolean validate) {
- if (validate) {
- return unmarshalValidate(uri, null);
- } else {
- return unmarshalNoValidate(uri, null);
- }
- }
-
- public static Features unmarshal(String uri, InputStream stream, boolean validate) {
- if (validate) {
- return unmarshalValidate(uri, stream);
- } else {
- return unmarshalNoValidate(uri, stream);
- }
- }
-
- private static Features unmarshalValidate(String uri, InputStream stream) {
- try {
- Document doc;
- if (stream != null) {
- doc = XmlUtils.parse(stream);
- doc.setDocumentURI(uri);
- } else {
- doc = XmlUtils.parse(uri);
- }
-
- Schema schema = getSchema(doc.getDocumentElement().getNamespaceURI());
- try {
- schema.newValidator().validate(new DOMSource(doc));
- } catch (SAXException e) {
- throw new IllegalArgumentException("Unable to validate " + uri, e);
- }
-
- fixDom(doc, doc.getDocumentElement());
- Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
- return (Features) unmarshaller.unmarshal(new DOMSource(doc));
-
-
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException("Unable to load " + uri, e);
- }
- }
-
- private static Map<String, Schema> schemas = new ConcurrentHashMap<String, Schema>();
- private static Schema getSchema(String namespace) throws SAXException {
- Schema schema = schemas.get(namespace);
- if (schema == null) {
- String schemaLocation;
- if (FeaturesNamespaces.URI_1_0_0.equals(namespace)) {
- schemaLocation = "/org/apache/karaf/features/karaf-features-1.0.0.xsd";
- } else if (FeaturesNamespaces.URI_1_1_0.equals(namespace)) {
- schemaLocation = "/org/apache/karaf/features/karaf-features-1.1.0.xsd";
- } else if (FeaturesNamespaces.URI_1_2_0.equals(namespace)) {
- schemaLocation = "/org/apache/karaf/features/karaf-features-1.2.0.xsd";
- } else if (FeaturesNamespaces.URI_1_3_0.equals(namespace)) {
- schemaLocation = "/org/apache/karaf/features/karaf-features-1.3.0.xsd";
- } else {
- throw new IllegalArgumentException("Unsupported namespace: " + namespace);
- }
-
- SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
- // root element has namespace - we can use schema validation
- URL url = JaxbUtil.class.getResource(schemaLocation);
- if (url == null) {
- throw new IllegalStateException("Could not find resource: " + schemaLocation);
- }
- schema = factory.newSchema(new StreamSource(url.toExternalForm()));
- schemas.put(namespace, schema);
- }
- return schema;
- }
-
-
- private static void fixDom(Document doc, Node node) {
- if (node.getNamespaceURI() != null && !FeaturesNamespaces.URI_CURRENT.equals(node.getNamespaceURI())) {
- doc.renameNode(node, FeaturesNamespaces.URI_CURRENT, node.getLocalName());
- }
- NodeList children = node.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- fixDom(doc, children.item(i));
- }
- }
-
- private static Features unmarshalNoValidate(String uri, InputStream stream) {
- try {
- Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
- XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(XmlUtils.xmlReader());
- xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
-
-
- InputSource is = new InputSource(uri);
- if (stream != null) {
- is.setByteStream(stream);
- }
- SAXSource source = new SAXSource(xmlFilter, new InputSource(uri));
- return (Features) unmarshaller.unmarshal(source);
-
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException("Unable to load " + uri, e);
- }
- }
-
- /**
- * Provides an empty inputsource for the entity resolver.
- * Converts all elements to the features namespace to make old feature files
- * compatible to the new format
- */
- public static class NoSourceAndNamespaceFilter extends XMLFilterImpl {
- private static final InputSource EMPTY_INPUT_SOURCE = new InputSource(new ByteArrayInputStream(new byte[0]));
-
- public NoSourceAndNamespaceFilter(XMLReader xmlReader) {
- super(xmlReader);
- }
-
- @Override
- public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
- return EMPTY_INPUT_SOURCE;
- }
-
- @Override
- public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
- super.startElement(FeaturesNamespaces.URI_CURRENT, localName, qName, atts);
- }
-
- @Override
- public void endElement(String uri, String localName, String qName) throws SAXException {
- super.endElement(FeaturesNamespaces.URI_CURRENT, localName, qName);
- }
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java b/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
deleted file mode 100644
index 96fbb0f..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.annotation.XmlElementDecl;
-import javax.xml.bind.annotation.XmlRegistry;
-import javax.xml.namespace.QName;
-
-
-/**
- * This object contains factory methods for each
- * Java content interface and Java element interface
- * generated in the org.apache.karaf.features.wrapper package.
- * <p>An ObjectFactory allows you to programatically
- * construct new instances of the Java representation
- * for XML content. The Java representation of XML
- * content can consist of schema derived interfaces
- * and classes representing the binding of schema
- * type definitions, element declarations and model
- * groups. Factory methods for each of these are
- * provided in this class.
- *
- */
-@XmlRegistry
-public class ObjectFactory {
-
- private final static QName _Features_QNAME = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
-
- /**
- * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.features.wrapper
- *
- */
- public ObjectFactory() {
- }
-
- /**
- * Create an instance of {@link ConfigFile }
- *
- */
- public ConfigFile createConfigFile() {
- return new ConfigFile();
- }
-
- /**
- * Create an instance of {@link Dependency }
- *
- */
- public Dependency createDependency() {
- return new Dependency();
- }
-
- /**
- * Create an instance of {@link Bundle }
- *
- */
- public Bundle createBundle() {
- return new Bundle();
- }
-
- /**
- * Create an instance of {@link Features }
- *
- */
- public Features createFeaturesRoot() {
- return new Features();
- }
-
- /**
- * Create an instance of {@link Config }
- *
- */
- public Config createConfig() {
- return new Config();
- }
-
- /**
- * Create an instance of {@link Feature }
- *
- */
- public Feature createFeature() {
- return new Feature();
- }
-
- /**
- * Create an instance of {@link JAXBElement }{@code <}{@link Features }{@code >}}
- *
- */
- @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/features/v1.0.0", name = "features")
- public JAXBElement<Features> createFeatures(Features value) {
- return new JAXBElement<Features>(_Features_QNAME, Features.class, null, value);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java b/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
deleted file mode 100644
index f7b5775..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-package org.apache.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- *
- * Additional requirement for a feature.
- *
- *
- * <p>Java class for bundle complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="capability">
- * <simpleContent>
- * <extension base="<http://www.w3.org/2001/XMLSchema>string">
- * </extension>
- * </simpleContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "requirement", propOrder = {
- "value"
-})
-public class Requirement implements org.apache.karaf.features.Requirement {
-
- @XmlValue
- protected String value;
-
-
- public Requirement() {
- }
-
- public Requirement(String value) {
- this.value = value;
- }
-
- public String getValue() {
- return value;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Requirement bundle = (Requirement) o;
-
- if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = value != null ? value.hashCode() : 0;
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java b/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
deleted file mode 100644
index c86a58c..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-@javax.xml.bind.annotation.XmlSchema(namespace = org.apache.karaf.features.FeaturesNamespaces.URI_CURRENT, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
-package org.apache.karaf.features.internal.model;
[20/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
deleted file mode 100644
index e2ff793..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wiring;
-import org.osgi.service.repository.Repository;
-import org.osgi.service.resolver.HostedCapability;
-import org.osgi.service.resolver.ResolveContext;
-
-/**
-*/
-public class ResolveContextImpl extends ResolveContext {
-
- private final Set<Resource> mandatory;
- private final Set<Resource> optional;
- private final Repository repository;
- private final Map<Resource, Wiring> wirings;
- private final boolean resolveOptional;
-
- private final CandidateComparator candidateComparator = new CandidateComparator();
-
- public ResolveContextImpl(Set<Resource> mandatory,
- Set<Resource> optional,
- Repository repository,
- boolean resolveOptional) {
- this.mandatory = mandatory;
- this.optional = optional;
- this.repository = repository;
- this.wirings = new HashMap<Resource, Wiring>();
- this.resolveOptional = resolveOptional;
- }
-
- @Override
- public Collection<Resource> getMandatoryResources() {
- return mandatory;
- }
-
- @Override
- public Collection<Resource> getOptionalResources() {
- return optional;
- }
-
- @Override
- public List<Capability> findProviders(Requirement requirement) {
- List<Capability> caps = new ArrayList<Capability>();
- Map<Requirement, Collection<Capability>> resMap =
- repository.findProviders(Collections.singleton(requirement));
- Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
- if (res != null) {
- caps.addAll(res);
- }
- Collections.sort(caps, candidateComparator);
- return caps;
- }
- @Override
- public int insertHostedCapability(List capabilities, HostedCapability hostedCapability) {
- for (int i=0; i < capabilities.size(); i++) {
- Capability cap = (Capability) capabilities.get(i);
- if (candidateComparator.compare(hostedCapability, cap) <= 0) {
- capabilities.add(i, hostedCapability);
- return i;
- }
- }
- capabilities.add(hostedCapability);
- return capabilities.size() - 1;
- }
- @Override
- public boolean isEffective(Requirement requirement) {
- return resolveOptional ||
- !Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
- }
- @Override
- public Map<Resource, Wiring> getWirings() {
- return wirings;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
deleted file mode 100644
index cb2c36a..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-public class ResourceBuilder {
-
- public static final String RESOLUTION_DYNAMIC = "dynamic";
-
- public static Resource build(String uri, Map<String, String> headerMap)
- throws BundleException {
-
- // Verify that only manifest version 2 is specified.
- String manifestVersion = getManifestVersion(headerMap);
- if (manifestVersion == null || !manifestVersion.equals("2")) {
- throw new BundleException("Unsupported 'Bundle-ManifestVersion' value: " + manifestVersion);
- }
-
- //
- // Parse bundle version.
- //
-
- Version bundleVersion = Version.emptyVersion;
- if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
- bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
- }
-
- //
- // Parse bundle symbolic name.
- //
-
- String bundleSymbolicName = null;
- ParsedHeaderClause bundleCap = parseBundleSymbolicName(headerMap);
- if (bundleCap == null) {
- throw new BundleException("Bundle manifest must include bundle symbolic name");
- }
- bundleSymbolicName = (String) bundleCap.attrs.get(BundleRevision.BUNDLE_NAMESPACE);
-
- // Now that we have symbolic name and version, create the resource
- String type = headerMap.get(Constants.FRAGMENT_HOST) == null ? IdentityNamespace.TYPE_BUNDLE : IdentityNamespace.TYPE_FRAGMENT;
- ResourceImpl resource = new ResourceImpl(bundleSymbolicName, type, bundleVersion);
- if (uri != null) {
- Map<String, Object> attrs = new HashMap<String, Object>();
- attrs.put(UriNamespace.URI_NAMESPACE, uri);
- resource.addCapability(new CapabilityImpl(resource, UriNamespace.URI_NAMESPACE, Collections.<String, String>emptyMap(), attrs));
- }
-
- // Add a bundle and host capability to all
- // non-fragment bundles. A host capability is the same
- // as a require capability, but with a different capability
- // namespace. Bundle capabilities resolve required-bundle
- // dependencies, while host capabilities resolve fragment-host
- // dependencies.
- if (headerMap.get(Constants.FRAGMENT_HOST) == null) {
- // All non-fragment bundles have bundle capability.
- resource.addCapability(new CapabilityImpl(resource, BundleRevision.BUNDLE_NAMESPACE, bundleCap.dirs, bundleCap.attrs));
- // A non-fragment bundle can choose to not have a host capability.
- String attachment = bundleCap.dirs.get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
- attachment = (attachment == null) ? Constants.FRAGMENT_ATTACHMENT_RESOLVETIME : attachment;
- if (!attachment.equalsIgnoreCase(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
- Map<String, Object> hostAttrs = new HashMap<String, Object>(bundleCap.attrs);
- Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE);
- hostAttrs.put(BundleRevision.HOST_NAMESPACE, value);
- resource.addCapability(new CapabilityImpl(
- resource, BundleRevision.HOST_NAMESPACE,
- bundleCap.dirs,
- hostAttrs));
- }
- }
-
- //
- // Parse Fragment-Host.
- //
-
- List<RequirementImpl> hostReqs = parseFragmentHost(resource, headerMap);
-
- //
- // Parse Require-Bundle
- //
-
- List<ParsedHeaderClause> rbClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_BUNDLE));
- rbClauses = normalizeRequireClauses(rbClauses);
- List<Requirement> rbReqs = convertRequires(rbClauses, resource);
-
- //
- // Parse Import-Package.
- //
-
- List<ParsedHeaderClause> importClauses = parseStandardHeader(headerMap.get(Constants.IMPORT_PACKAGE));
- importClauses = normalizeImportClauses(importClauses);
- List<Requirement> importReqs = convertImports(importClauses, resource);
-
- //
- // Parse DynamicImport-Package.
- //
-
- List<ParsedHeaderClause> dynamicClauses = parseStandardHeader(headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
- dynamicClauses = normalizeDynamicImportClauses(dynamicClauses);
- List<Requirement> dynamicReqs = convertImports(dynamicClauses, resource);
-
- //
- // Parse Require-Capability.
- //
-
- List<ParsedHeaderClause> requireClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_CAPABILITY));
- requireClauses = normalizeRequireCapabilityClauses(requireClauses);
- List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
-
- //
- // Parse Export-Package.
- //
-
- List<ParsedHeaderClause> exportClauses = parseStandardHeader(headerMap.get(Constants.EXPORT_PACKAGE));
- exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
- List<Capability> exportCaps = convertExports(exportClauses, resource);
-
- //
- // Parse Provide-Capability.
- //
-
- List<ParsedHeaderClause> provideClauses = parseStandardHeader(headerMap.get(Constants.PROVIDE_CAPABILITY));
- provideClauses = normalizeProvideCapabilityClauses(provideClauses);
- List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
-
- //
- // Parse Import-Service and Export-Service
- // if Require-Capability and Provide-Capability are not set for services
- //
-
- boolean hasServiceReferenceCapability = false;
- for (Capability cap : exportCaps) {
- hasServiceReferenceCapability |= ServiceNamespace.SERVICE_NAMESPACE.equals(cap.getNamespace());
- }
- if (!hasServiceReferenceCapability) {
- List<ParsedHeaderClause> exportServices = parseStandardHeader(headerMap.get(Constants.EXPORT_SERVICE));
- List<Capability> caps = convertExportService(exportServices, resource);
- provideCaps.addAll(caps);
- }
-
- boolean hasServiceReferenceRequirement = false;
- for (Requirement req : requireReqs) {
- hasServiceReferenceRequirement |= ServiceNamespace.SERVICE_NAMESPACE.equals(req.getNamespace());
- }
- if (!hasServiceReferenceRequirement) {
- List<ParsedHeaderClause> importServices = parseStandardHeader(headerMap.get(Constants.IMPORT_SERVICE));
- List<Requirement> reqs = convertImportService(importServices, resource);
- requireReqs.addAll(reqs);
- }
-
- // Combine all capabilities.
- resource.addCapabilities(exportCaps);
- resource.addCapabilities(provideCaps);
-
- // Combine all requirements.
- resource.addRequirements(hostReqs);
- resource.addRequirements(importReqs);
- resource.addRequirements(rbReqs);
- resource.addRequirements(requireReqs);
- resource.addRequirements(dynamicReqs);
-
- return resource;
- }
-
- public static List<Requirement> parseImport(Resource resource, String imports) throws BundleException {
- List<ParsedHeaderClause> importClauses = parseStandardHeader(imports);
- importClauses = normalizeImportClauses(importClauses);
- List<Requirement> importReqs = convertImports(importClauses, resource);
- return importReqs;
- }
-
- public static List<Requirement> parseRequirement(Resource resource, String requirement) throws BundleException {
- List<ParsedHeaderClause> requireClauses = parseStandardHeader(requirement);
- requireClauses = normalizeRequireCapabilityClauses(requireClauses);
- List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
- return requireReqs;
- }
-
- public static List<Capability> parseExport(Resource resource, String bundleSymbolicName, Version bundleVersion, String exports) throws BundleException {
- List<ParsedHeaderClause> exportClauses = parseStandardHeader(exports);
- exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
- List<Capability> exportCaps = convertExports(exportClauses, resource);
- return exportCaps;
- }
-
- public static List<Capability> parseCapability(Resource resource, String capability) throws BundleException {
- List<ParsedHeaderClause> provideClauses = parseStandardHeader(capability);
- provideClauses = normalizeProvideCapabilityClauses(provideClauses);
- List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
- return provideCaps;
- }
-
- @SuppressWarnings( "deprecation" )
- private static List<ParsedHeaderClause> normalizeImportClauses(
- List<ParsedHeaderClause> clauses)
- throws BundleException {
- // Verify that the values are equals if the package specifies
- // both version and specification-version attributes.
- Set<String> dupeSet = new HashSet<String>();
- for (ParsedHeaderClause clause : clauses) {
- // Check for "version" and "specification-version" attributes
- // and verify they are the same if both are specified.
- Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
- Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
- if ((v != null) && (sv != null)) {
- // Verify they are equal.
- if (!((String) v).trim().equals(((String) sv).trim())) {
- throw new IllegalArgumentException(
- "Both version and specification-version are specified, but they are not equal.");
- }
- }
-
- // Ensure that only the "version" attribute is used and convert
- // it to the VersionRange type.
- if ((v != null) || (sv != null)) {
- clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
- v = (v == null) ? sv : v;
- clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
- }
-
- // If bundle version is specified, then convert its type to VersionRange.
- v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- if (v != null) {
- clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
- }
-
- // Verify java.* is not imported, nor any duplicate imports.
- for (String pkgName : clause.paths) {
- if (!dupeSet.contains(pkgName)) {
- // Verify that java.* packages are not imported.
- if (pkgName.startsWith("java.")) {
- throw new BundleException("Importing java.* packages not allowed: " + pkgName);
- }
- // The character "." has no meaning in the OSGi spec except
- // when placed on the bundle class path. Some people, however,
- // mistakenly think it means the default package when imported
- // or exported. This is not correct. It is invalid.
- else if (pkgName.equals(".")) {
- throw new BundleException("Importing '.' is invalid.");
- }
- // Make sure a package name was specified.
- else if (pkgName.length() == 0) {
- throw new BundleException(
- "Imported package names cannot be zero length.");
- }
- dupeSet.add(pkgName);
- } else {
- throw new BundleException("Duplicate import: " + pkgName);
- }
- }
- }
-
- return clauses;
- }
-
- private static List<Capability> convertExportService(List<ParsedHeaderClause> clauses, Resource resource) {
- List<Capability> capList = new ArrayList<Capability>();
- for (ParsedHeaderClause clause : clauses) {
- for (String path : clause.paths) {
- Map<String, String> dirs = new LinkedHashMap<String, String>();
- dirs.put(ServiceNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
- Map<String, Object> attrs = new LinkedHashMap<String, Object>();
- attrs.put(Constants.OBJECTCLASS, path);
- attrs.putAll(clause.attrs);
- capList.add(new CapabilityImpl(
- resource,
- ServiceNamespace.SERVICE_NAMESPACE,
- dirs,
- attrs));
- }
- }
- return capList;
- }
-
- private static List<Requirement> convertImportService(List<ParsedHeaderClause> clauses, Resource resource) throws BundleException {
- try {
- List<Requirement> reqList = new ArrayList<Requirement>();
- for (ParsedHeaderClause clause : clauses) {
- for (String path : clause.paths) {
- String multiple = clause.dirs.get("multiple");
- String avail = clause.dirs.get("availability");
- String filter = (String) clause.attrs.get("filter");
- Map<String, String> dirs = new LinkedHashMap<String, String>();
- dirs.put(ServiceNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
- if ("optional".equals(avail)) {
- dirs.put(ServiceNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, ServiceNamespace.RESOLUTION_OPTIONAL);
- }
- if ("true".equals(multiple)) {
- dirs.put(ServiceNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE, ServiceNamespace.CARDINALITY_MULTIPLE);
- }
- if (filter == null) {
- filter = "(" + Constants.OBJECTCLASS + "=" + path + ")";
- } else if (!filter.startsWith("(") && !filter.endsWith(")")) {
- filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")(" + filter + "))";
- } else {
- filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")" + filter + ")";
- }
- dirs.put(ServiceNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
- reqList.add(new RequirementImpl(
- resource,
- ServiceNamespace.SERVICE_NAMESPACE,
- dirs,
- Collections.<String, Object>emptyMap(),
- SimpleFilter.parse(filter)));
- }
- }
- return reqList;
- } catch (Exception ex) {
- throw new BundleException("Error creating requirement: " + ex, ex);
- }
- }
-
- private static List<Requirement> convertImports(List<ParsedHeaderClause> clauses, Resource resource) {
- // Now convert generic header clauses into requirements.
- List<Requirement> reqList = new ArrayList<Requirement>();
- for (ParsedHeaderClause clause : clauses) {
- for (String path : clause.paths) {
- // Prepend the package name to the array of attributes.
- Map<String, Object> attrs = clause.attrs;
- // Note that we use a linked hash map here to ensure the
- // package attribute is first, which will make indexing
- // more efficient.
- // TODO: OSGi R4.3 - This is ordering is kind of hacky.
- // Prepend the package name to the array of attributes.
- Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
- // We want this first from an indexing perspective.
- newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
- newAttrs.putAll(attrs);
- // But we need to put it again to make sure it wasn't overwritten.
- newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
-
- // Create filter now so we can inject filter directive.
- SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
- // Inject filter directive.
- // TODO: OSGi R4.3 - Can we insert this on demand somehow?
- Map<String, String> dirs = clause.dirs;
- Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
- newDirs.putAll(dirs);
- newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
- // Create package requirement and add to requirement list.
- reqList.add(
- new RequirementImpl(
- resource,
- BundleRevision.PACKAGE_NAMESPACE,
- newDirs,
- Collections.<String, Object>emptyMap(),
- sf));
- }
- }
-
- return reqList;
- }
-
- @SuppressWarnings( "deprecation" )
- private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
- List<ParsedHeaderClause> clauses)
- throws BundleException {
- // Verify that the values are equals if the package specifies
- // both version and specification-version attributes.
- for (ParsedHeaderClause clause : clauses) {
- // Add the resolution directive to indicate that these are
- // dynamic imports.
- clause.dirs.put(Constants.RESOLUTION_DIRECTIVE, RESOLUTION_DYNAMIC);
-
- // Check for "version" and "specification-version" attributes
- // and verify they are the same if both are specified.
- Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
- Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
- if ((v != null) && (sv != null)) {
- // Verify they are equal.
- if (!((String) v).trim().equals(((String) sv).trim())) {
- throw new IllegalArgumentException(
- "Both version and specification-version are specified, but they are not equal.");
- }
- }
-
- // Ensure that only the "version" attribute is used and convert
- // it to the VersionRange type.
- if ((v != null) || (sv != null)) {
- clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
- v = (v == null) ? sv : v;
- clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
- }
-
- // If bundle version is specified, then convert its type to VersionRange.
- v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- if (v != null) {
- clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
- }
-
- // Dynamic imports can have duplicates, so verify that java.*
- // packages are not imported.
- for (String pkgName : clause.paths) {
- if (pkgName.startsWith("java.")) {
- throw new BundleException("Dynamically importing java.* packages not allowed: " + pkgName);
- } else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*")) {
- throw new BundleException("Partial package name wild carding is not allowed: " + pkgName);
- }
- }
- }
-
- return clauses;
- }
-
- private static List<ParsedHeaderClause> normalizeRequireCapabilityClauses(
- List<ParsedHeaderClause> clauses)
- throws BundleException {
-
- return clauses;
- }
-
- private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
- List<ParsedHeaderClause> clauses)
- throws BundleException
- {
-
- // Convert attributes into specified types.
- for (ParsedHeaderClause clause : clauses)
- {
- for (Map.Entry<String, String> entry : clause.types.entrySet())
- {
- String type = entry.getValue();
- if (!type.equals("String"))
- {
- if (type.equals("Double"))
- {
- clause.attrs.put(
- entry.getKey(),
- new Double(clause.attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.equals("Version"))
- {
- clause.attrs.put(
- entry.getKey(),
- new Version(clause.attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.equals("Long"))
- {
- clause.attrs.put(
- entry.getKey(),
- new Long(clause.attrs.get(entry.getKey()).toString().trim()));
- }
- else if (type.startsWith("List"))
- {
- int startIdx = type.indexOf('<');
- int endIdx = type.indexOf('>');
- if (((startIdx > 0) && (endIdx <= startIdx))
- || ((startIdx < 0) && (endIdx > 0)))
- {
- throw new BundleException(
- "Invalid Provide-Capability attribute list type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
-
- String listType = "String";
- if (endIdx > startIdx)
- {
- listType = type.substring(startIdx + 1, endIdx).trim();
- }
-
- List<String> tokens = parseDelimitedString(
- clause.attrs.get(entry.getKey()).toString(), ",", false);
- List<Object> values = new ArrayList<Object>(tokens.size());
- for (String token : tokens)
- {
- if (listType.equals("String"))
- {
- values.add(token);
- }
- else if (listType.equals("Double"))
- {
- values.add(new Double(token.trim()));
- }
- else if (listType.equals("Version"))
- {
- values.add(new Version(token.trim()));
- }
- else if (listType.equals("Long"))
- {
- values.add(new Long(token.trim()));
- }
- else
- {
- throw new BundleException(
- "Unknown Provide-Capability attribute list type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
- }
- clause.attrs.put(
- entry.getKey(),
- values);
- }
- else
- {
- throw new BundleException(
- "Unknown Provide-Capability attribute type for '"
- + entry.getKey()
- + "' : "
- + type);
- }
- }
- }
- }
-
- return clauses;
- }
-
- private static List<Requirement> convertRequireCapabilities(
- List<ParsedHeaderClause> clauses, Resource resource)
- throws BundleException {
- // Now convert generic header clauses into requirements.
- List<Requirement> reqList = new ArrayList<Requirement>();
- for (ParsedHeaderClause clause : clauses) {
- try {
- String filterStr = clause.dirs.get(Constants.FILTER_DIRECTIVE);
- SimpleFilter sf = (filterStr != null)
- ? SimpleFilter.parse(filterStr)
- : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
- for (String path : clause.paths) {
- // Create requirement and add to requirement list.
- reqList.add(new RequirementImpl(
- resource, path, clause.dirs, clause.attrs, sf));
- }
- } catch (Exception ex) {
- throw new BundleException("Error creating requirement: " + ex, ex);
- }
- }
-
- return reqList;
- }
-
- private static List<Capability> convertProvideCapabilities(
- List<ParsedHeaderClause> clauses, Resource resource)
- throws BundleException {
- List<Capability> capList = new ArrayList<Capability>();
- for (ParsedHeaderClause clause : clauses) {
- for (String path : clause.paths) {
- if (path.startsWith("osgi.wiring.")) {
-// throw new BundleException("Manifest cannot use Provide-Capability for '" + path + "' namespace.");
- }
-
- // Create package capability and add to capability list.
- capList.add(new CapabilityImpl(resource, path, clause.dirs, clause.attrs));
- }
- }
-
- return capList;
- }
-
- @SuppressWarnings( "deprecation" )
- private static List<ParsedHeaderClause> normalizeExportClauses(
- List<ParsedHeaderClause> clauses,
- String bsn, Version bv)
- throws BundleException {
- // Verify that "java.*" packages are not exported.
- for (ParsedHeaderClause clause : clauses) {
- // Verify that the named package has not already been declared.
- for (String pkgName : clause.paths) {
- // Verify that java.* packages are not exported.
- if (pkgName.startsWith("java.")) {
- throw new BundleException("Exporting java.* packages not allowed: " + pkgName);
- }
- // The character "." has no meaning in the OSGi spec except
- // when placed on the bundle class path. Some people, however,
- // mistakenly think it means the default package when imported
- // or exported. This is not correct. It is invalid.
- else if (pkgName.equals(".")) {
- throw new BundleException("Exporing '.' is invalid.");
- }
- // Make sure a package name was specified.
- else if (pkgName.length() == 0) {
- throw new BundleException("Exported package names cannot be zero length.");
- }
- }
-
- // Check for "version" and "specification-version" attributes
- // and verify they are the same if both are specified.
- Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
- Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
- if ((v != null) && (sv != null)) {
- // Verify they are equal.
- if (!((String) v).trim().equals(((String) sv).trim())) {
- throw new IllegalArgumentException("Both version and specification-version are specified, but they are not equal.");
- }
- }
-
- // Always add the default version if not specified.
- if ((v == null) && (sv == null)) {
- v = Version.emptyVersion;
- }
-
- // Ensure that only the "version" attribute is used and convert
- // it to the appropriate type.
- if ((v != null) || (sv != null)) {
- // Convert version attribute to type Version.
- clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
- v = (v == null) ? sv : v;
- clause.attrs.put(Constants.VERSION_ATTRIBUTE, Version.parseVersion(v.toString()));
- }
-
- // Find symbolic name and version attribute, if present.
- if (clause.attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)
- || clause.attrs.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)) {
- throw new BundleException("Exports must not specify bundle symbolic name or bundle version.");
- }
-
- // Now that we know that there are no bundle symbolic name and version
- // attributes, add them since the spec says they are there implicitly.
- clause.attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
- clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bv);
- }
-
- return clauses;
- }
-
- private static List<Capability> convertExports(
- List<ParsedHeaderClause> clauses, Resource resource) {
- List<Capability> capList = new ArrayList<Capability>();
- for (ParsedHeaderClause clause : clauses) {
- for (String pkgName : clause.paths) {
- // Prepend the package name to the array of attributes.
- Map<String, Object> attrs = clause.attrs;
- Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
- newAttrs.putAll(attrs);
- newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName);
-
- // Create package capability and add to capability list.
- capList.add(new CapabilityImpl(resource, BundleRevision.PACKAGE_NAMESPACE, clause.dirs, newAttrs));
- }
- }
-
- return capList;
- }
-
- private static String getManifestVersion(Map<String, String> headerMap) {
- String manifestVersion = headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
- return (manifestVersion == null) ? "1" : manifestVersion.trim();
- }
-
- private static List<ParsedHeaderClause> calculateImplicitImports(
- List<BundleCapability> exports, List<ParsedHeaderClause> imports)
- throws BundleException {
- List<ParsedHeaderClause> clauseList = new ArrayList<ParsedHeaderClause>();
-
- // Since all R3 exports imply an import, add a corresponding
- // requirement for each existing export capability. Do not
- // duplicate imports.
- Map<String, String> map = new HashMap<String, String>();
- // Add existing imports.
- for (ParsedHeaderClause anImport : imports) {
- for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
- map.put(anImport.paths.get(pathIdx), anImport.paths.get(pathIdx));
- }
- }
- // Add import requirement for each export capability.
- for (BundleCapability export : exports) {
- if (map.get(export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()) == null) {
- // Convert Version to VersionRange.
- Object version = export.getAttributes().get(Constants.VERSION_ATTRIBUTE);
- ParsedHeaderClause clause = new ParsedHeaderClause();
- if (version != null) {
- clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(version.toString()));
- }
- clause.paths.add((String) export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
- clauseList.add(clause);
- }
- }
-
- return clauseList;
- }
-
- private static List<Capability> calculateImplicitUses(
- List<Capability> exports, List<ParsedHeaderClause> imports)
- throws BundleException {
- // Add a "uses" directive onto each export of R3 bundles
- // that references every other import (which will include
- // exports, since export implies import); this is
- // necessary since R3 bundles assumed a single class space,
- // but R4 allows for multiple class spaces.
- String usesValue = "";
- for (ParsedHeaderClause anImport : imports) {
- for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
- usesValue = usesValue
- + ((usesValue.length() > 0) ? "," : "")
- + anImport.paths.get(pathIdx);
- }
- }
- for (int i = 0; i < exports.size(); i++) {
- Map<String, String> dirs = new HashMap<String, String>(1);
- dirs.put(Constants.USES_DIRECTIVE, usesValue);
- exports.set(i, new CapabilityImpl(
- exports.get(i).getResource(),
- BundleRevision.PACKAGE_NAMESPACE,
- dirs,
- exports.get(i).getAttributes()));
- }
-
- return exports;
- }
-
- private static ParsedHeaderClause parseBundleSymbolicName(Map<String, String> headerMap)
- throws BundleException {
- List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
- if (clauses.size() > 0) {
- if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
- throw new BundleException("Cannot have multiple symbolic names: " + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
- }
-
- // Get bundle version.
- Version bundleVersion = Version.emptyVersion;
- if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
- bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
- }
-
- // Create a require capability and return it.
- ParsedHeaderClause clause = clauses.get(0);
- String symName = clause.paths.get(0);
- clause.attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName);
- clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
- return clause;
- }
-
- return null;
- }
-
- private static List<RequirementImpl> parseFragmentHost(
- Resource resource, Map<String, String> headerMap)
- throws BundleException {
- List<RequirementImpl> reqs = new ArrayList<RequirementImpl>();
-
- List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.FRAGMENT_HOST));
- if (clauses.size() > 0) {
- // Make sure that only one fragment host symbolic name is specified.
- if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
- throw new BundleException("Fragments cannot have multiple hosts: " + headerMap.get(Constants.FRAGMENT_HOST));
- }
-
- // If the bundle-version attribute is specified, then convert
- // it to the proper type.
- Object value = clauses.get(0).attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- value = (value == null) ? "0.0.0" : value;
- clauses.get(0).attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
-
- // Note that we use a linked hash map here to ensure the
- // host symbolic name is first, which will make indexing
- // more efficient.
- // TODO: OSGi R4.3 - This is ordering is kind of hacky.
- // Prepend the host symbolic name to the map of attributes.
- Map<String, Object> attrs = clauses.get(0).attrs;
- Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
- // We want this first from an indexing perspective.
- newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
- newAttrs.putAll(attrs);
- // But we need to put it again to make sure it wasn't overwritten.
- newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
-
- // Create filter now so we can inject filter directive.
- SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
- // Inject filter directive.
- // TODO: OSGi R4.3 - Can we insert this on demand somehow?
- Map<String, String> dirs = clauses.get(0).dirs;
- Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
- newDirs.putAll(dirs);
- newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
- reqs.add(new RequirementImpl(
- resource, BundleRevision.HOST_NAMESPACE,
- newDirs,
- newAttrs));
- }
-
- return reqs;
- }
-
- private static List<ParsedHeaderClause> normalizeRequireClauses(List<ParsedHeaderClause> clauses) {
- // Convert bundle version attribute to VersionRange type.
- for (ParsedHeaderClause clause : clauses) {
- Object value = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
- if (value != null) {
- clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
- }
- }
-
- return clauses;
- }
-
- private static List<Requirement> convertRequires(List<ParsedHeaderClause> clauses, Resource resource) {
- List<Requirement> reqList = new ArrayList<Requirement>();
- for (ParsedHeaderClause clause : clauses) {
- for (String path : clause.paths) {
- // Prepend the bundle symbolic name to the array of attributes.
- Map<String, Object> attrs = clause.attrs;
- // Note that we use a linked hash map here to ensure the
- // symbolic name attribute is first, which will make indexing
- // more efficient.
- // TODO: OSGi R4.3 - This is ordering is kind of hacky.
- // Prepend the symbolic name to the array of attributes.
- Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
- // We want this first from an indexing perspective.
- newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
- newAttrs.putAll(attrs);
- // But we need to put it again to make sure it wasn't overwritten.
- newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
-
- // Create filter now so we can inject filter directive.
- SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
- // Inject filter directive.
- // TODO: OSGi R4.3 - Can we insert this on demand somehow?
- Map<String, String> dirs = clause.dirs;
- Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
- newDirs.putAll(dirs);
- newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
- // Create package requirement and add to requirement list.
- reqList.add(new RequirementImpl(resource, BundleRevision.BUNDLE_NAMESPACE, newDirs, newAttrs));
- }
- }
-
- return reqList;
- }
-
- private static final char EOF = (char) -1;
-
- private static char charAt(int pos, String headers, int length)
- {
- if (pos >= length)
- {
- return EOF;
- }
- return headers.charAt(pos);
- }
-
- private static final int CLAUSE_START = 0;
- private static final int PARAMETER_START = 1;
- private static final int KEY = 2;
- private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
- private static final int ARGUMENT = 8;
- private static final int VALUE = 16;
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- private static List<ParsedHeaderClause> parseStandardHeader(String header)
- {
- List<ParsedHeaderClause> clauses = new ArrayList<ParsedHeaderClause>();
- if (header == null)
- {
- return clauses;
- }
- ParsedHeaderClause clause = null;
- String key = null;
- Map targetMap = null;
- int state = CLAUSE_START;
- int currentPosition = 0;
- int startPosition = 0;
- int length = header.length();
- boolean quoted = false;
- boolean escaped = false;
-
- char currentChar = EOF;
- do
- {
- currentChar = charAt(currentPosition, header, length);
- switch (state)
- {
- case CLAUSE_START:
- clause = new ParsedHeaderClause();
- clauses.add(clause);
- state = PARAMETER_START;
- case PARAMETER_START:
- startPosition = currentPosition;
- state = KEY;
- case KEY:
- switch (currentChar)
- {
- case ':':
- case '=':
- key = header.substring(startPosition, currentPosition).trim();
- startPosition = currentPosition + 1;
- targetMap = clause.attrs;
- state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
- break;
- case EOF:
- case ',':
- case ';':
- clause.paths.add(header.substring(startPosition, currentPosition).trim());
- state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
- break;
- default:
- break;
- }
- currentPosition++;
- break;
- case DIRECTIVE_OR_TYPEDATTRIBUTE:
- switch(currentChar)
- {
- case '=':
- if (startPosition != currentPosition)
- {
- clause.types.put(key, header.substring(startPosition, currentPosition).trim());
- }
- else
- {
- targetMap = clause.dirs;
- }
- state = ARGUMENT;
- startPosition = currentPosition + 1;
- break;
- default:
- break;
- }
- currentPosition++;
- break;
- case ARGUMENT:
- if (currentChar == '\"')
- {
- quoted = true;
- currentPosition++;
- }
- else
- {
- quoted = false;
- }
- if (!Character.isWhitespace(currentChar)) {
- state = VALUE;
- }
- else {
- currentPosition++;
- }
- break;
- case VALUE:
- if (escaped)
- {
- escaped = false;
- }
- else
- {
- if (currentChar == '\\' )
- {
- escaped = true;
- }
- else if (quoted && currentChar == '\"')
- {
- quoted = false;
- }
- else if (!quoted)
- {
- String value = null;
- switch(currentChar)
- {
- case EOF:
- case ';':
- case ',':
- value = header.substring(startPosition, currentPosition).trim();
- if (value.startsWith("\"") && value.endsWith("\""))
- {
- value = value.substring(1, value.length() - 1);
- }
- if (targetMap.put(key, value) != null)
- {
- throw new IllegalArgumentException(
- "Duplicate '" + key + "' in: " + header);
- }
- state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
- break;
- default:
- break;
- }
- }
- }
- currentPosition++;
- break;
- default:
- break;
- }
- } while ( currentChar != EOF);
-
- if (state > PARAMETER_START)
- {
- throw new IllegalArgumentException("Unable to parse header: " + header);
- }
- return clauses;
- }
-
- public static List<String> parseDelimitedString(String value, String delim)
- {
- return parseDelimitedString(value, delim, true);
- }
-
- /**
- * Parses delimited string and returns an array containing the tokens. This
- * parser obeys quotes, so the delimiter character will be ignored if it is
- * inside of a quote. This method assumes that the quote character is not
- * included in the set of delimiter characters.
- * @param value the delimited string to parse.
- * @param delim the characters delimiting the tokens.
- * @return a list of string or an empty list if there are none.
- **/
- public static List<String> parseDelimitedString(String value, String delim, boolean trim)
- {
- if (value == null)
- {
- value = "";
- }
-
- List<String> list = new ArrayList();
-
- int CHAR = 1;
- int DELIMITER = 2;
- int STARTQUOTE = 4;
- int ENDQUOTE = 8;
-
- StringBuffer sb = new StringBuffer();
-
- int expecting = (CHAR | DELIMITER | STARTQUOTE);
-
- boolean isEscaped = false;
- for (int i = 0; i < value.length(); i++)
- {
- char c = value.charAt(i);
-
- boolean isDelimiter = (delim.indexOf(c) >= 0);
-
- if (!isEscaped && (c == '\\'))
- {
- isEscaped = true;
- continue;
- }
-
- if (isEscaped)
- {
- sb.append(c);
- }
- else if (isDelimiter && ((expecting & DELIMITER) > 0))
- {
- if (trim)
- {
- list.add(sb.toString().trim());
- }
- else
- {
- list.add(sb.toString());
- }
- sb.delete(0, sb.length());
- expecting = (CHAR | DELIMITER | STARTQUOTE);
- }
- else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
- {
- sb.append(c);
- expecting = CHAR | ENDQUOTE;
- }
- else if ((c == '"') && ((expecting & ENDQUOTE) > 0))
- {
- sb.append(c);
- expecting = (CHAR | STARTQUOTE | DELIMITER);
- }
- else if ((expecting & CHAR) > 0)
- {
- sb.append(c);
- }
- else
- {
- throw new IllegalArgumentException("Invalid delimited string: " + value);
- }
-
- isEscaped = false;
- }
-
- if (sb.length() > 0)
- {
- if (trim)
- {
- list.add(sb.toString().trim());
- }
- else
- {
- list.add(sb.toString());
- }
- }
-
- return list;
- }
-
-
- static class ParsedHeaderClause {
- public final List<String> paths = new ArrayList<String>();
- public final Map<String, String> dirs = new LinkedHashMap<String, String>();
- public final Map<String, Object> attrs = new LinkedHashMap<String, Object>();
- public final Map<String, String> types = new LinkedHashMap<String, String>();
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
deleted file mode 100644
index 18e0dc3..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-/**
- */
-public class ResourceImpl implements Resource {
-
- private final List<Capability> m_caps;
- private final List<Requirement> m_reqs;
-
- public ResourceImpl(String name, Version version) {
- this(name, IdentityNamespace.TYPE_BUNDLE, version);
- }
-
- public ResourceImpl(String name, String type, Version version)
- {
- m_caps = new ArrayList<Capability>();
- m_caps.add(0, new IdentityCapability(this, name, type, version));
- m_reqs = new ArrayList<Requirement>();
- }
-
- public void addCapability(Capability capability) {
- assert capability.getResource() == this;
- m_caps.add(capability);
- }
-
- public void addCapabilities(Iterable<? extends Capability> capabilities) {
- for (Capability cap : capabilities) {
- addCapability(cap);
- }
- }
-
- public void addRequirement(Requirement requirement) {
- assert requirement.getResource() == this;
- m_reqs.add(requirement);
- }
-
- public void addRequirements(Iterable<? extends Requirement> requirements) {
- for (Requirement req : requirements) {
- addRequirement(req);
- }
- }
-
- public List<Capability> getCapabilities(String namespace)
- {
- List<Capability> result = m_caps;
- if (namespace != null)
- {
- result = new ArrayList<Capability>();
- for (Capability cap : m_caps)
- {
- if (cap.getNamespace().equals(namespace))
- {
- result.add(cap);
- }
- }
- }
- return result;
- }
-
- public List<Requirement> getRequirements(String namespace)
- {
- List<Requirement> result = m_reqs;
- if (namespace != null)
- {
- result = new ArrayList<Requirement>();
- for (Requirement req : m_reqs)
- {
- if (req.getNamespace().equals(namespace))
- {
- result.add(req);
- }
- }
- }
- return result;
- }
-
- @Override
- public String toString()
- {
- Capability cap = getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
- return cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/"
- + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
deleted file mode 100644
index 4fe3bf8..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import org.osgi.resource.Namespace;
-
-/**
- */
-public final class ServiceNamespace extends Namespace {
-
- public static final String SERVICE_NAMESPACE = "service-reference";
-
- private ServiceNamespace() {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
deleted file mode 100644
index ae10441..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.felix.utils.version.VersionRange;
-
-public class SimpleFilter
-{
- public static final int MATCH_ALL = 0;
- public static final int AND = 1;
- public static final int OR = 2;
- public static final int NOT = 3;
- public static final int EQ = 4;
- public static final int LTE = 5;
- public static final int GTE = 6;
- public static final int SUBSTRING = 7;
- public static final int PRESENT = 8;
- public static final int APPROX = 9;
-
- private final String m_name;
- private final Object m_value;
- private final int m_op;
-
- public SimpleFilter(String attr, Object value, int op)
- {
- m_name = attr;
- m_value = value;
- m_op = op;
- }
-
- public String getName()
- {
- return m_name;
- }
-
- public Object getValue()
- {
- return m_value;
- }
-
- public int getOperation()
- {
- return m_op;
- }
-
- public String toString()
- {
- String s = null;
- switch (m_op)
- {
- case AND:
- s = "(&" + toString((List) m_value) + ")";
- break;
- case OR:
- s = "(|" + toString((List) m_value) + ")";
- break;
- case NOT:
- s = "(!" + toString((List) m_value) + ")";
- break;
- case EQ:
- s = "(" + m_name + "=" + toEncodedString(m_value) + ")";
- break;
- case LTE:
- s = "(" + m_name + "<=" + toEncodedString(m_value) + ")";
- break;
- case GTE:
- s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
- break;
- case SUBSTRING:
- s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
- break;
- case PRESENT:
- s = "(" + m_name + "=*)";
- break;
- case APPROX:
- s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
- break;
- case MATCH_ALL:
- s = "(*)";
- break;
- }
- return s;
- }
-
- private static String toString(List list)
- {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < list.size(); i++)
- {
- sb.append(list.get(i).toString());
- }
- return sb.toString();
- }
-
- private static String toDecodedString(String s, int startIdx, int endIdx)
- {
- StringBuffer sb = new StringBuffer(endIdx - startIdx);
- boolean escaped = false;
- for (int i = 0; i < (endIdx - startIdx); i++)
- {
- char c = s.charAt(startIdx + i);
- if (!escaped && (c == '\\'))
- {
- escaped = true;
- }
- else
- {
- escaped = false;
- sb.append(c);
- }
- }
-
- return sb.toString();
- }
-
- private static String toEncodedString(Object o)
- {
- if (o instanceof String)
- {
- String s = (String) o;
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < s.length(); i++)
- {
- char c = s.charAt(i);
- if ((c == '\\') || (c == '(') || (c == ')') || (c == '*'))
- {
- sb.append('\\');
- }
- sb.append(c);
- }
-
- o = sb.toString();
- }
-
- return o.toString();
- }
-
- public static SimpleFilter parse(String filter)
- {
- int idx = skipWhitespace(filter, 0);
-
- if ((filter == null) || (filter.length() == 0) || (idx >= filter.length()))
- {
- throw new IllegalArgumentException("Null or empty filter.");
- }
- else if (filter.charAt(idx) != '(')
- {
- throw new IllegalArgumentException("Missing opening parenthesis: " + filter);
- }
-
- SimpleFilter sf = null;
- List stack = new ArrayList();
- boolean isEscaped = false;
- while (idx < filter.length())
- {
- if (sf != null)
- {
- throw new IllegalArgumentException(
- "Only one top-level operation allowed: " + filter);
- }
-
- if (!isEscaped && (filter.charAt(idx) == '('))
- {
- // Skip paren and following whitespace.
- idx = skipWhitespace(filter, idx + 1);
-
- if (filter.charAt(idx) == '&')
- {
- int peek = skipWhitespace(filter, idx + 1);
- if (filter.charAt(peek) == '(')
- {
- idx = peek - 1;
- stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.AND));
- }
- else
- {
- stack.add(0, new Integer(idx));
- }
- }
- else if (filter.charAt(idx) == '|')
- {
- int peek = skipWhitespace(filter, idx + 1);
- if (filter.charAt(peek) == '(')
- {
- idx = peek - 1;
- stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.OR));
- }
- else
- {
- stack.add(0, new Integer(idx));
- }
- }
- else if (filter.charAt(idx) == '!')
- {
- int peek = skipWhitespace(filter, idx + 1);
- if (filter.charAt(peek) == '(')
- {
- idx = peek - 1;
- stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT));
- }
- else
- {
- stack.add(0, new Integer(idx));
- }
- }
- else
- {
- stack.add(0, new Integer(idx));
- }
- }
- else if (!isEscaped && (filter.charAt(idx) == ')'))
- {
- Object top = stack.remove(0);
- if (top instanceof SimpleFilter)
- {
- if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
- {
- ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
- }
- else
- {
- sf = (SimpleFilter) top;
- }
- }
- else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
- {
- ((List) ((SimpleFilter) stack.get(0)).m_value).add(
- SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx));
- }
- else
- {
- sf = SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx);
- }
- }
- else if (!isEscaped && (filter.charAt(idx) == '\\'))
- {
- isEscaped = true;
- }
- else
- {
- isEscaped = false;
- }
-
- idx = skipWhitespace(filter, idx + 1);
- }
-
- if (sf == null)
- {
- throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
- }
-
- return sf;
- }
-
- private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
- {
- final String opChars = "=<>~";
-
- // Determine the ending index of the attribute name.
- int attrEndIdx = startIdx;
- for (int i = 0; i < (endIdx - startIdx); i++)
- {
- char c = filter.charAt(startIdx + i);
- if (opChars.indexOf(c) >= 0)
- {
- break;
- }
- else if (!Character.isWhitespace(c))
- {
- attrEndIdx = startIdx + i + 1;
- }
- }
- if (attrEndIdx == startIdx)
- {
- throw new IllegalArgumentException(
- "Missing attribute name: " + filter.substring(startIdx, endIdx));
- }
- String attr = filter.substring(startIdx, attrEndIdx);
-
- // Skip the attribute name and any following whitespace.
- startIdx = skipWhitespace(filter, attrEndIdx);
-
- // Determine the operator type.
- int op = -1;
- switch (filter.charAt(startIdx))
- {
- case '=':
- op = EQ;
- startIdx++;
- break;
- case '<':
- if (filter.charAt(startIdx + 1) != '=')
- {
- throw new IllegalArgumentException(
- "Unknown operator: " + filter.substring(startIdx, endIdx));
- }
- op = LTE;
- startIdx += 2;
- break;
- case '>':
- if (filter.charAt(startIdx + 1) != '=')
- {
- throw new IllegalArgumentException(
- "Unknown operator: " + filter.substring(startIdx, endIdx));
- }
- op = GTE;
- startIdx += 2;
- break;
- case '~':
- if (filter.charAt(startIdx + 1) != '=')
- {
- throw new IllegalArgumentException(
- "Unknown operator: " + filter.substring(startIdx, endIdx));
- }
- op = APPROX;
- startIdx += 2;
- break;
- default:
- throw new IllegalArgumentException(
- "Unknown operator: " + filter.substring(startIdx, endIdx));
- }
-
- // Parse value.
- Object value = toDecodedString(filter, startIdx, endIdx);
-
- // Check if the equality comparison is actually a substring
- // or present operation.
- if (op == EQ)
- {
- String valueStr = filter.substring(startIdx, endIdx);
- List<String> values = parseSubstring(valueStr);
- if ((values.size() == 2)
- && (values.get(0).length() == 0)
- && (values.get(1).length() == 0))
- {
- op = PRESENT;
- }
- else if (values.size() > 1)
- {
- op = SUBSTRING;
- value = values;
- }
- }
-
- return new SimpleFilter(attr, value, op);
- }
-
- public static List<String> parseSubstring(String value)
- {
- List<String> pieces = new ArrayList();
- StringBuffer ss = new StringBuffer();
- // int kind = SIMPLE; // assume until proven otherwise
- boolean wasStar = false; // indicates last piece was a star
- boolean leftstar = false; // track if the initial piece is a star
- boolean rightstar = false; // track if the final piece is a star
-
- int idx = 0;
-
- // We assume (sub)strings can contain leading and trailing blanks
- boolean escaped = false;
- loop: for (;;)
- {
- if (idx >= value.length())
- {
- if (wasStar)
- {
- // insert last piece as "" to handle trailing star
- rightstar = true;
- }
- else
- {
- pieces.add(ss.toString());
- // accumulate the last piece
- // note that in the case of
- // (cn=); this might be
- // the string "" (!=null)
- }
- ss.setLength(0);
- break loop;
- }
-
- // Read the next character and account for escapes.
- char c = value.charAt(idx++);
- if (!escaped && (c == '*'))
- {
- // If we have successive '*' characters, then we can
- // effectively collapse them by ignoring succeeding ones.
- if (!wasStar)
- {
- if (ss.length() > 0)
- {
- pieces.add(ss.toString()); // accumulate the pieces
- // between '*' occurrences
- }
- ss.setLength(0);
- // if this is a leading star, then track it
- if (pieces.isEmpty())
- {
- leftstar = true;
- }
- wasStar = true;
- }
- }
- else if (!escaped && (c == '\\'))
- {
- escaped = true;
- }
- else
- {
- escaped = false;
- wasStar = false;
- ss.append(c);
- }
- }
- if (leftstar || rightstar || pieces.size() > 1)
- {
- // insert leading and/or trailing "" to anchor ends
- if (rightstar)
- {
- pieces.add("");
- }
- if (leftstar)
- {
- pieces.add(0, "");
- }
- }
- return pieces;
- }
-
- public static String unparseSubstring(List<String> pieces)
- {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < pieces.size(); i++)
- {
- if (i > 0)
- {
- sb.append("*");
- }
- sb.append(toEncodedString(pieces.get(i)));
- }
- return sb.toString();
- }
-
- public static boolean compareSubstring(List<String> pieces, String s)
- {
- // Walk the pieces to match the string
- // There are implicit stars between each piece,
- // and the first and last pieces might be "" to anchor the match.
- // assert (pieces.length > 1)
- // minimal case is <string>*<string>
-
- boolean result = true;
- int len = pieces.size();
-
- // Special case, if there is only one piece, then
- // we must perform an equality test.
- if (len == 1)
- {
- return s.equals(pieces.get(0));
- }
-
- // Otherwise, check whether the pieces match
- // the specified string.
-
- int index = 0;
-
- loop: for (int i = 0; i < len; i++)
- {
- String piece = pieces.get(i);
-
- // If this is the first piece, then make sure the
- // string starts with it.
- if (i == 0)
- {
- if (!s.startsWith(piece))
- {
- result = false;
- break loop;
- }
- }
-
- // If this is the last piece, then make sure the
- // string ends with it.
- if (i == (len - 1))
- {
- if (s.endsWith(piece) && (s.length() >= (index + piece.length())))
- {
- result = true;
- }
- else
- {
- result = false;
- }
- break loop;
- }
-
- // If this is neither the first or last piece, then
- // make sure the string contains it.
- if ((i > 0) && (i < (len - 1)))
- {
- index = s.indexOf(piece, index);
- if (index < 0)
- {
- result = false;
- break loop;
- }
- }
-
- // Move string index beyond the matching piece.
- index += piece.length();
- }
-
- return result;
- }
-
- private static int skipWhitespace(String s, int startIdx)
- {
- int len = s.length();
- while ((startIdx < len) && Character.isWhitespace(s.charAt(startIdx)))
- {
- startIdx++;
- }
- return startIdx;
- }
-
- /**
- * Converts a attribute map to a filter. The filter is created by iterating
- * over the map's entry set. If ordering of attributes is important (e.g.,
- * for hitting attribute indices), then the map's entry set should iterate
- * in the desired order. Equality testing is assumed for all attribute types
- * other than version ranges, which are handled appropriated. If the attribute
- * map is empty, then a filter that matches anything is returned.
- * @param attrs Map of attributes to convert to a filter.
- * @return A filter corresponding to the attributes.
- */
- public static SimpleFilter convert(Map<String, Object> attrs)
- {
- // Rather than building a filter string to be parsed into a SimpleFilter,
- // we will just create the parsed SimpleFilter directly.
-
- List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
-
- for (Entry<String, Object> entry : attrs.entrySet())
- {
- if (entry.getValue() instanceof VersionRange)
- {
- VersionRange vr = (VersionRange) entry.getValue();
- if (!vr.isOpenFloor())
- {
- filters.add(
- new SimpleFilter(
- entry.getKey(),
- vr.getFloor().toString(),
- SimpleFilter.GTE));
- }
- else
- {
- SimpleFilter not =
- new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
- ((List) not.getValue()).add(
- new SimpleFilter(
- entry.getKey(),
- vr.getFloor().toString(),
- SimpleFilter.LTE));
- filters.add(not);
- }
-
- if (vr.getCeiling() != null)
- {
- if (!vr.isOpenCeiling())
- {
- filters.add(
- new SimpleFilter(
- entry.getKey(),
- vr.getCeiling().toString(),
- SimpleFilter.LTE));
- }
- else
- {
- SimpleFilter not =
- new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
- ((List) not.getValue()).add(
- new SimpleFilter(
- entry.getKey(),
- vr.getCeiling().toString(),
- SimpleFilter.GTE));
- filters.add(not);
- }
- }
- }
- else
- {
- List<String> values = SimpleFilter.parseSubstring(entry.getValue().toString());
- if (values.size() > 1)
- {
- filters.add(
- new SimpleFilter(
- entry.getKey(),
- values,
- SimpleFilter.SUBSTRING));
- }
- else
- {
- filters.add(
- new SimpleFilter(
- entry.getKey(),
- values.get(0),
- SimpleFilter.EQ));
- }
- }
- }
-
- SimpleFilter sf = null;
-
- if (filters.size() == 1)
- {
- sf = filters.get(0);
- }
- else if (attrs.size() > 1)
- {
- sf = new SimpleFilter(null, filters, SimpleFilter.AND);
- }
- else if (filters.isEmpty())
- {
- sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
- }
-
- return sf;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
deleted file mode 100644
index 2f4a1f3..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import org.slf4j.Logger;
-
-/**
- */
-public class Slf4jResolverLog extends org.apache.felix.resolver.Logger {
-
- private final Logger logger;
-
- public Slf4jResolverLog(Logger logger) {
- super(LOG_DEBUG);
- this.logger = logger;
- }
-
- @Override
- protected void doLog(int level, String msg, Throwable throwable) {
- switch (level) {
- case LOG_ERROR:
- logger.error(msg, throwable);
- break;
- case LOG_WARNING:
- logger.warn(msg, throwable);
- break;
- case LOG_INFO:
- logger.info(msg, throwable);
- break;
- case LOG_DEBUG:
- logger.debug(msg, throwable);
- break;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
deleted file mode 100644
index b5158bf..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.List;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Namespace;
-import org.osgi.resource.Resource;
-
-/**
- */
-public final class UriNamespace extends Namespace {
-
- public static final String URI_NAMESPACE = "karaf.uri";
-
- public static String getUri(Resource resource)
- {
- List<Capability> caps = resource.getCapabilities(null);
- for (Capability cap : caps)
- {
- if (cap.getNamespace().equals(UriNamespace.URI_NAMESPACE))
- {
- return cap.getAttributes().get(UriNamespace.URI_NAMESPACE).toString();
- }
- }
- return null;
- }
-
-
- private UriNamespace() {
- }
-}
[13/33] git commit: [KARAF-2888] Refactor repository validation so
that we use a single pass, cache the created Schema
Posted by gn...@apache.org.
[KARAF-2888] Refactor repository validation so that we use a single pass, cache the created Schema
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/1306af5f
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/1306af5f
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/1306af5f
Branch: refs/heads/master
Commit: 1306af5f222e8bf8925d0e42b0062ec3d367c1d3
Parents: a9b763f
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 11:14:16 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:03 2014 +0200
----------------------------------------------------------------------
features/pom.xml | 4 +
.../org/apache/karaf/features/Repository.java | 3 +-
.../karaf/features/internal/model/JaxbUtil.java | 149 ++++++++++++++-----
.../internal/service/BootFeaturesInstaller.java | 2 +-
.../internal/service/FeatureValidationUtil.java | 80 +---------
.../internal/service/FeaturesServiceImpl.java | 4 +-
.../internal/service/RepositoryImpl.java | 15 +-
.../service/FeaturesValidationTest.java | 49 +++++-
.../karaf/tooling/features/CreateKarMojo.java | 23 ++-
.../features/GenerateDescriptorMojo.java | 9 +-
.../karaf/tooling/features/InstallKarsMojo.java | 9 +-
.../features/GenerateDescriptorMojoTest.java | 9 +-
.../java/org/apache/karaf/util/XmlUtils.java | 64 +++++---
13 files changed, 231 insertions(+), 189 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/pom.xml
----------------------------------------------------------------------
diff --git a/features/pom.xml b/features/pom.xml
index 5013057..d722ada 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -129,12 +129,16 @@
org.apache.felix.resolver,
org.apache.felix.utils.version,
org.apache.felix.utils.manifest,
+ org.apache.karaf.util,
org.apache.karaf.util.collections,
org.apache.karaf.util.json,
org.apache.karaf.util.tracker,
org.osgi.service.resolver,
org.osgi.service.repository
</Private-Package>
+ <Embed-Dependency>
+ org.apache.karaf.util;inline="org/apache/karaf/util/XmlUtils*.class"
+ </Embed-Dependency>
<Bundle-Activator>
org.apache.karaf.features.internal.osgi.Activator
</Bundle-Activator>
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/Repository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Repository.java b/features/src/main/java/org/apache/karaf/features/Repository.java
index 6ee96da..3ea12ec 100644
--- a/features/src/main/java/org/apache/karaf/features/Repository.java
+++ b/features/src/main/java/org/apache/karaf/features/Repository.java
@@ -16,6 +16,7 @@
*/
package org.apache.karaf.features;
+import java.io.IOException;
import java.net.URI;
/**
@@ -23,7 +24,7 @@ import java.net.URI;
*/
public interface Repository {
- String getName();
+ String getName() throws IOException;
URI getURI();
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
index 39c057a..2036452 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
@@ -23,19 +23,27 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
+import java.net.URL;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.ValidationEvent;
-import javax.xml.bind.ValidationEventHandler;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.stream.XMLInputFactory;
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
import org.apache.karaf.features.FeaturesNamespaces;
+import org.apache.karaf.util.XmlUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -45,7 +53,6 @@ import org.xml.sax.helpers.XMLFilterImpl;
public class JaxbUtil {
- public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
private static final JAXBContext FEATURES_CONTEXT;
static {
try {
@@ -75,45 +82,113 @@ public class JaxbUtil {
/**
* Read in a Features from the input stream.
*
- * @param in input stream to read
+ * @param uri uri to read
* @param validate whether to validate the input.
* @return a Features read from the input stream
- * @throws ParserConfigurationException is the SAX parser can not be configured
- * @throws SAXException if there is an xml problem
- * @throws JAXBException if the xml cannot be marshalled into a T.
*/
- public static Features unmarshal(InputStream in, boolean validate) {
- InputSource inputSource = new InputSource(in);
+ public static Features unmarshal(String uri, boolean validate) {
+ if (validate) {
+ return unmarshalValidate(uri, null);
+ } else {
+ return unmarshalNoValidate(uri, null);
+ }
+ }
+
+ public static Features unmarshal(String uri, InputStream stream, boolean validate) {
+ if (validate) {
+ return unmarshalValidate(uri, stream);
+ } else {
+ return unmarshalNoValidate(uri, stream);
+ }
+ }
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setNamespaceAware(true);
- factory.setValidating(validate);
- SAXParser parser;
+ private static Features unmarshalValidate(String uri, InputStream stream) {
try {
- parser = factory.newSAXParser();
-
-
- Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
- unmarshaller.setEventHandler(new ValidationEventHandler() {
- public boolean handleEvent(ValidationEvent validationEvent) {
- System.out.println(validationEvent);
- return false;
+ Document doc;
+ if (stream != null) {
+ doc = XmlUtils.parse(stream);
+ doc.setDocumentURI(uri);
+ } else {
+ doc = XmlUtils.parse(uri);
}
- });
- XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(parser.getXMLReader());
- xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
+ Schema schema = getSchema(doc.getDocumentElement().getNamespaceURI());
+ try {
+ schema.newValidator().validate(new DOMSource(doc));
+ } catch (SAXException e) {
+ throw new IllegalArgumentException("Unable to validate " + uri, e);
+ }
- SAXSource source = new SAXSource(xmlFilter, inputSource);
+ fixDom(doc, doc.getDocumentElement());
+ Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
+ return (Features) unmarshaller.unmarshal(new DOMSource(doc));
- return (Features)unmarshaller.unmarshal(source);
-
- } catch (ParserConfigurationException e) {
- throw new RuntimeException(e);
- } catch (JAXBException e) {
- throw new RuntimeException(e);
- } catch (SAXException e) {
- throw new RuntimeException(e);
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load " + uri, e);
+ }
+ }
+
+ private static Map<String, Schema> schemas = new ConcurrentHashMap<String, Schema>();
+ private static Schema getSchema(String namespace) throws SAXException {
+ Schema schema = schemas.get(namespace);
+ if (schema == null) {
+ String schemaLocation;
+ if (FeaturesNamespaces.URI_1_0_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.0.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_1_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.1.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_2_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.2.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_3_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.3.0.xsd";
+ } else {
+ throw new IllegalArgumentException("Unsupported namespace: " + namespace);
+ }
+
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ // root element has namespace - we can use schema validation
+ URL url = JaxbUtil.class.getResource(schemaLocation);
+ if (url == null) {
+ throw new IllegalStateException("Could not find resource: " + schemaLocation);
+ }
+ schema = factory.newSchema(new StreamSource(url.toExternalForm()));
+ schemas.put(namespace, schema);
+ }
+ return schema;
+ }
+
+
+ private static void fixDom(Document doc, Node node) {
+ if (node.getNamespaceURI() != null && !FeaturesNamespaces.URI_CURRENT.equals(node.getNamespaceURI())) {
+ doc.renameNode(node, FeaturesNamespaces.URI_CURRENT, node.getLocalName());
+ }
+ NodeList children = node.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ fixDom(doc, children.item(i));
+ }
+ }
+
+ private static Features unmarshalNoValidate(String uri, InputStream stream) {
+ try {
+ Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
+ XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(XmlUtils.xmlReader());
+ xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
+
+
+ InputSource is = new InputSource(uri);
+ if (stream != null) {
+ is.setByteStream(stream);
+ }
+ SAXSource source = new SAXSource(xmlFilter, new InputSource(uri));
+ return (Features) unmarshaller.unmarshal(source);
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load " + uri, e);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
index eaa9ba0..5b362b8 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
@@ -89,7 +89,7 @@ public class BootFeaturesInstaller {
try {
featuresService.addRepository(URI.create(repo));
} catch (Exception e) {
- LOGGER.error("Error installing boot feature repository " + repo);
+ LOGGER.error("Error installing boot feature repository " + repo, e);
}
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
index 8fb161e..6903dc0 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
@@ -15,38 +15,15 @@
*/
package org.apache.karaf.features.internal.service;
-import java.io.IOException;
-import java.io.InputStream;
import java.net.URI;
-import java.net.URLConnection;
-import javax.xml.XMLConstants;
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
-import org.apache.karaf.features.FeaturesNamespaces;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
+import org.apache.karaf.features.internal.model.JaxbUtil;
/**
* Utility class which fires XML Schema validation.
*/
public class FeatureValidationUtil {
- public static final QName FEATURES_0_0 = new QName("features");
- public static final QName FEATURES_1_0 = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
- public static final QName FEATURES_1_1 = new QName("http://karaf.apache.org/xmlns/features/v1.1.0", "features");
- public static final QName FEATURES_1_2 = new QName("http://karaf.apache.org/xmlns/features/v1.2.0", "features");
- private static final Logger LOGGER = LoggerFactory.getLogger(FeatureValidationUtil.class);
-
/**
* Runs schema validation.
*
@@ -54,60 +31,7 @@ public class FeatureValidationUtil {
* @throws Exception When validation fails.
*/
public static void validate(URI uri) throws Exception {
- Document doc = load(uri);
-
- QName name = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName());
-
- if (FeaturesNamespaces.FEATURES_0_0_0.equals(name)) {
- LOGGER.warn("Old style feature file without namespace found (URI: {}). This format is deprecated and support for it will soon be removed", uri);
- return;
- } else if (FeaturesNamespaces.FEATURES_1_0_0.equals(name)) {
- validate(doc, "/org/apache/karaf/features/karaf-features-1.0.0.xsd");
- } else if (FeaturesNamespaces.FEATURES_1_1_0.equals(name)) {
- validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd");
- } else if (FeaturesNamespaces.FEATURES_1_2_0.equals(name)) {
- validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd");
- } else if (FeaturesNamespaces.FEATURES_1_3_0.equals(name)) {
- validate(doc, "/org/apache/karaf/features/karaf-features-1.3.0.xsd");
- }
- else {
- throw new IllegalArgumentException("Unrecognized root element: " + name);
- }
- }
-
- private static Document load(URI uri) throws IOException, SAXException, ParserConfigurationException {
- InputStream stream = null;
- try {
- URLConnection conn;
- try {
- conn = uri.toURL().openConnection();
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("invalid URI: " + uri, e);
- }
- conn.setDefaultUseCaches(false);
- stream = conn.getInputStream();
- // load document and check the root element for namespace declaration
- DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
- dFactory.setNamespaceAware(true);
- return dFactory.newDocumentBuilder().parse(stream);
- } finally {
- if (stream != null) {
- stream.close();
- }
- }
- }
-
- private static void validate(Document doc, String schemaLocation) throws SAXException {
- SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
- // root element has namespace - we can use schema validation
- Schema schema = factory.newSchema(new StreamSource(FeatureValidationUtil.class.getResourceAsStream(schemaLocation)));
- // create schema by reading it from an XSD file:
- Validator validator = schema.newValidator();
- try {
- validator.validate(new DOMSource(doc));
- } catch (Exception e) {
- throw new IllegalArgumentException("Unable to validate " + doc.getDocumentURI(), e);
- }
+ JaxbUtil.unmarshal(uri.toASCIIString(), true);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 0bd1e67..65223d5 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -281,10 +281,8 @@ public class FeaturesServiceImpl implements FeaturesService {
//
public Repository loadRepository(URI uri) throws Exception {
- // TODO: merge validation and loading by loading the DOM, validating, unmarshalling
- FeatureValidationUtil.validate(uri);
RepositoryImpl repo = new RepositoryImpl(uri);
- repo.load();
+ repo.load(true);
return repo;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
index 4bf1502..56e5102 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
@@ -42,13 +42,8 @@ public class RepositoryImpl implements Repository {
return uri;
}
- public String getName() {
- // TODO: catching this exception is ugly
- try {
- load();
- } catch (IOException e) {
- throw new RuntimeException("Unable to load repository", e);
- }
+ public String getName() throws IOException {
+ load();
return features.getName();
}
@@ -70,6 +65,10 @@ public class RepositoryImpl implements Repository {
public void load() throws IOException {
+ load(false);
+ }
+
+ public void load(boolean validate) throws IOException {
if (features == null) {
try {
InputStream inputStream = uri.toURL().openStream();
@@ -83,7 +82,7 @@ public class RepositoryImpl implements Repository {
}
};
try {
- features = JaxbUtil.unmarshal(inputStream, false);
+ features = JaxbUtil.unmarshal(uri.toASCIIString(), inputStream, validate);
} finally {
inputStream.close();
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
index f3ca2e6..9e33ee3 100644
--- a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
@@ -16,20 +16,29 @@
*/
package org.apache.karaf.features.internal.service;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
public class FeaturesValidationTest {
@Test
- public void testNoNs() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f01.xml").toURI());
+ public void testNs10() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
}
@Test
- public void testNs10() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
+ public void testNs10Unmarshall() throws Exception {
+ URL url = getClass().getResource("f02.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
}
@Test
@@ -38,13 +47,22 @@ public class FeaturesValidationTest {
}
@Test
+ public void testNs10NoNameUnmarshall() throws Exception {
+ URL url = getClass().getResource("f03.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
public void testNs11() throws Exception {
FeatureValidationUtil.validate(getClass().getResource("f04.xml").toURI());
}
@Test
- public void testNs12() throws Exception {
- FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
+ public void testNs11Unmarshall() throws Exception {
+ URL url = getClass().getResource("f04.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
}
@Test
@@ -58,8 +76,27 @@ public class FeaturesValidationTest {
}
@Test
+ public void testNs12() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
+ }
+
+ @Test
+ public void testNs12Unmarshall() throws Exception {
+ URL url = getClass().getResource("f06.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
public void testNs13() throws Exception {
FeatureValidationUtil.validate(getClass().getResource("f07.xml").toURI());
}
+ @Test
+ public void testNs13Unmarshall() throws Exception {
+ URL url = getClass().getResource("f07.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/CreateKarMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/CreateKarMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/CreateKarMojo.java
index c30f7c0..71ff485 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/CreateKarMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/CreateKarMojo.java
@@ -212,23 +212,18 @@ public class CreateKarMojo extends MojoSupport {
private List<Artifact> readResources(File featuresFile) throws MojoExecutionException {
List<Artifact> resources = new ArrayList<Artifact>();
try {
- InputStream in = new FileInputStream(featuresFile);
- try {
- Features features = JaxbUtil.unmarshal(in, false);
- for (Feature feature : features.getFeature()) {
- for (BundleInfo bundle : feature.getBundles()) {
- if (ignoreDependencyFlag || (!ignoreDependencyFlag && !bundle.isDependency())) {
- resources.add(resourceToArtifact(bundle.getLocation(), false));
- }
- }
- for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
- resources.add(resourceToArtifact(configFile.getLocation(), false));
+ Features features = JaxbUtil.unmarshal(featuresFile.toURI().toASCIIString(), false);
+ for (Feature feature : features.getFeature()) {
+ for (BundleInfo bundle : feature.getBundles()) {
+ if (ignoreDependencyFlag || (!ignoreDependencyFlag && !bundle.isDependency())) {
+ resources.add(resourceToArtifact(bundle.getLocation(), false));
}
}
- return resources;
- } finally {
- in.close();
+ for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
+ resources.add(resourceToArtifact(configFile.getLocation(), false));
+ }
}
+ return resources;
} catch (MojoExecutionException e) {
throw e;
} catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
index 1aff2c6..3cdae4a 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java
@@ -401,14 +401,7 @@ public class GenerateDescriptorMojo extends AbstractLogEnabled implements Mojo {
}
private Features readFeaturesFile(File featuresFile) throws XMLStreamException, JAXBException, IOException {
- Features features;
- InputStream in = new FileInputStream(featuresFile);
- try {
- features = JaxbUtil.unmarshal(in, false);
- } finally {
- in.close();
- }
- return features;
+ return JaxbUtil.unmarshal(featuresFile.toURI().toASCIIString(), false);
}
public void setLog(Log log) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
index c1a6c5f..f58ca37 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
@@ -425,14 +425,7 @@ public class InstallKarsMojo extends MojoSupport {
} else {
repoFile = new File(uri);
}
- InputStream in = new FileInputStream(repoFile);
- Features features;
- try {
- features = JaxbUtil.unmarshal(in, false);
- } finally {
- in.close();
- }
- return features;
+ return JaxbUtil.unmarshal(repoFile.toURI().toASCIIString(), false);
}
public void installFeature(org.apache.karaf.features.Feature feature) throws Exception {
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/features/GenerateDescriptorMojoTest.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/features/GenerateDescriptorMojoTest.java b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/features/GenerateDescriptorMojoTest.java
index 4b12fda..0eecbd0 100644
--- a/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/features/GenerateDescriptorMojoTest.java
+++ b/tooling/karaf-maven-plugin/src/test/java/org/apache/karaf/tooling/features/GenerateDescriptorMojoTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.*;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import java.net.URL;
import java.util.List;
import javax.xml.bind.JAXBException;
@@ -41,9 +42,9 @@ public class GenerateDescriptorMojoTest {
@Test
public void testReadXml100() throws JAXBException, SAXException, ParserConfigurationException, XMLStreamException {
- InputStream in = getClass().getClassLoader().getResourceAsStream("input-features-1.0.0.xml");
+ URL url = getClass().getClassLoader().getResource("input-features-1.0.0.xml");
- Features featuresRoot = JaxbUtil.unmarshal(in, false);
+ Features featuresRoot = JaxbUtil.unmarshal(url.toExternalForm(), false);
assertEquals(featuresRoot.getRepository().size(), 1);
@@ -61,9 +62,9 @@ public class GenerateDescriptorMojoTest {
@Test
public void testReadXml1() throws Exception {
- InputStream in = getClass().getClassLoader().getResourceAsStream("input-features-1.1.0.xml");
+ URL url = getClass().getClassLoader().getResource("input-features-1.1.0.xml");
- Features featuresRoot = JaxbUtil.unmarshal(in, false);
+ Features featuresRoot = JaxbUtil.unmarshal(url.toExternalForm(), false);
List<Feature> featuresList = featuresRoot.getFeature();
http://git-wip-us.apache.org/repos/asf/karaf/blob/1306af5f/util/src/main/java/org/apache/karaf/util/XmlUtils.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/XmlUtils.java b/util/src/main/java/org/apache/karaf/util/XmlUtils.java
index cbcb593..adfc2e6 100644
--- a/util/src/main/java/org/apache/karaf/util/XmlUtils.java
+++ b/util/src/main/java/org/apache/karaf/util/XmlUtils.java
@@ -16,17 +16,25 @@
*/
package org.apache.karaf.util;
-import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
-import org.w3c.dom.Document;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.*;
-import java.io.File;
-import java.io.IOException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
/**
* Utils class to manipulate XML document in a thread safe way.
@@ -35,6 +43,7 @@ public class XmlUtils {
private static final ThreadLocal<DocumentBuilderFactory> DOCUMENT_BUILDER_FACTORY = new ThreadLocal<DocumentBuilderFactory>();
private static final ThreadLocal<TransformerFactory> TRANSFORMER_FACTORY = new ThreadLocal<TransformerFactory>();
+ private static final ThreadLocal<SAXParserFactory> SAX_PARSER_FACTORY = new ThreadLocal<SAXParserFactory>();
public static Document parse(String uri) throws TransformerException, IOException, SAXException, ParserConfigurationException {
DocumentBuilder db = documentBuilder();
@@ -45,6 +54,15 @@ public class XmlUtils {
}
}
+ public static Document parse(InputStream stream) throws TransformerException, IOException, SAXException, ParserConfigurationException {
+ DocumentBuilder db = documentBuilder();
+ try {
+ return db.parse(stream);
+ } finally {
+ db.reset();
+ }
+ }
+
public static Document parse(File f) throws TransformerException, IOException, SAXException, ParserConfigurationException {
DocumentBuilder db = documentBuilder();
try {
@@ -82,36 +100,40 @@ public class XmlUtils {
}
}
- private static DocumentBuilder documentBuilder() throws ParserConfigurationException {
- DocumentBuilderFactory dbf;
- if (DOCUMENT_BUILDER_FACTORY.get() == null) {
+ public static XMLReader xmlReader() throws ParserConfigurationException, SAXException {
+ SAXParserFactory spf = SAX_PARSER_FACTORY.get();
+ if (spf == null) {
+ spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ SAX_PARSER_FACTORY.set(spf);
+ }
+ return spf.newSAXParser().getXMLReader();
+ }
+
+ public static DocumentBuilder documentBuilder() throws ParserConfigurationException {
+ DocumentBuilderFactory dbf = DOCUMENT_BUILDER_FACTORY.get();
+ if (dbf == null) {
dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DOCUMENT_BUILDER_FACTORY.set(dbf);
- } else {
- dbf = DOCUMENT_BUILDER_FACTORY.get();
}
return dbf.newDocumentBuilder();
}
- private static Transformer transformer() throws TransformerConfigurationException {
- TransformerFactory tf;
- if (TRANSFORMER_FACTORY.get() == null) {
+ public static Transformer transformer() throws TransformerConfigurationException {
+ TransformerFactory tf = TRANSFORMER_FACTORY.get();
+ if (tf == null) {
tf = TransformerFactory.newInstance();
TRANSFORMER_FACTORY.set(tf);
- } else {
- tf = TRANSFORMER_FACTORY.get();
}
return tf.newTransformer();
}
private static Transformer transformer(Source xsltSource) throws TransformerConfigurationException {
- TransformerFactory tf;
- if (TRANSFORMER_FACTORY.get() == null) {
+ TransformerFactory tf = TRANSFORMER_FACTORY.get();
+ if (tf == null) {
tf = TransformerFactory.newInstance();
TRANSFORMER_FACTORY.set(tf);
- } else {
- tf = TRANSFORMER_FACTORY.get();
}
return tf.newTransformer(xsltSource);
}
[15/33] git commit: [KARAF-2901] Add an option to show bundle version
in bundle:tree-show
Posted by gn...@apache.org.
[KARAF-2901] Add an option to show bundle version in bundle:tree-show
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/6727c1b7
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/6727c1b7
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/6727c1b7
Branch: refs/heads/master
Commit: 6727c1b74a83006c9c2aac98ecfb6daf5d4be928
Parents: edd82fd
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 19:17:49 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:04 2014 +0200
----------------------------------------------------------------------
.../karaf/bundle/command/ShowBundleTree.java | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/6727c1b7/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
index a83ce39..f6f3d48 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
@@ -30,6 +30,7 @@ import org.apache.felix.utils.version.VersionTable;
import org.apache.karaf.bundle.command.bundletree.Node;
import org.apache.karaf.bundle.command.bundletree.Tree;
import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@@ -52,6 +53,10 @@ import static java.lang.String.format;
public class ShowBundleTree extends BundleCommand {
private static final Logger LOGGER = LoggerFactory.getLogger(ShowBundleTree.class);
+
+ @Option(name = "-v", aliases = { "--version" }, description = "Show bundle versions")
+ private boolean versions;
+
private Tree<Bundle> tree;
public ShowBundleTree() {
@@ -104,9 +109,16 @@ public class ShowBundleTree extends BundleCommand {
tree.write(System.out, new Tree.Converter<Bundle>() {
public String toString(Node<Bundle> node) {
- return String.format("%s [%s]",
- node.getValue().getSymbolicName(),
- node.getValue().getBundleId());
+ if (versions) {
+ return String.format("%s / [%s] [%s]",
+ node.getValue().getSymbolicName(),
+ node.getValue().getVersion().toString(),
+ node.getValue().getBundleId());
+ } else {
+ return String.format("%s [%s]",
+ node.getValue().getSymbolicName(),
+ node.getValue().getBundleId());
+ }
}
});
}
[06/33] [KARAF-2852] Merge jms/core and jms/command
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java b/jms/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
new file mode 100644
index 0000000..cc46434
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/internal/JmsMBeanImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.internal;
+
+import org.apache.karaf.jms.JmsMBean;
+import org.apache.karaf.jms.JmsMessage;
+import org.apache.karaf.jms.JmsService;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.*;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Default implementation of the JMS MBean.
+ */
+public class JmsMBeanImpl implements JmsMBean {
+
+ private JmsService jmsService;
+
+ @Override
+ public List<String> getConnectionfactories() throws MBeanException {
+ try {
+ return jmsService.connectionFactories();
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public void create(String name, String type, String url) throws MBeanException {
+ try {
+ jmsService.create(name, type, url);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public void delete(String name) throws MBeanException {
+ try {
+ jmsService.delete(name);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException {
+ try {
+ return jmsService.info(connectionFactory, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public int count(String connectionFactory, String queue, String username, String password) throws MBeanException {
+ try {
+ return jmsService.count(connectionFactory, queue, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public List<String> queues(String connectionFactory, String username, String password) throws MBeanException {
+ try {
+ return jmsService.queues(connectionFactory, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public List<String> topics(String connectionFactory, String username, String password) throws MBeanException {
+ try {
+ return jmsService.topics(connectionFactory, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException {
+ try {
+ jmsService.send(connectionFactory, queue, content, replyTo, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
+ try {
+ return jmsService.consume(connectionFactory, queue, selector, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException {
+ try {
+ return jmsService.move(connectionFactory, source, destination, selector, username, password);
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ @Override
+ public TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException {
+ try {
+ CompositeType type = new CompositeType("message", "JMS Message",
+ new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
+ new String[]{ "Message ID", "Content", "Charset", "Type", "Correlation ID", "Delivery Mode", "Destination", "Expiration Date", "Priority", "Redelivered", "Reply-To", "Timestamp" },
+ new OpenType[]{ SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.STRING });
+ TabularType tableType = new TabularType("messages", "JMS Messages", type, new String[]{ "id" });
+ TabularData table = new TabularDataSupport(tableType);
+ for (JmsMessage message : getJmsService().browse(connectionFactory, queue, selector, username, password)) {
+ CompositeData data = new CompositeDataSupport(type,
+ new String[]{ "id", "content", "charset", "type", "correlation", "delivery", "destination", "expiration", "priority", "redelivered", "replyto", "timestamp" },
+ new Object[]{ message.getMessageId(), message.getContent(), message.getCharset(), message.getType(), message.getCorrelationID(), message.getDeliveryMode(), message.getDestination(), message.getExpiration(), message.getPriority(), message.isRedelivered(), message.getReplyTo(), message.getTimestamp() }
+ );
+ table.put(data);
+ }
+ return table;
+ } catch (Throwable t) {
+ throw new MBeanException(null, t.getMessage());
+ }
+ }
+
+ public JmsService getJmsService() {
+ return jmsService;
+ }
+
+ public void setJmsService(JmsService jmsService) {
+ this.jmsService = jmsService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java b/jms/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
new file mode 100644
index 0000000..fe4b43d
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.internal;
+
+import org.apache.activemq.ActiveMQConnection;
+import org.apache.activemq.advisory.DestinationSource;
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.activemq.command.ActiveMQTopic;
+import org.apache.activemq.pool.PooledConnection;
+import org.apache.karaf.jms.JmsMessage;
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.util.TemplateUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import javax.jms.*;
+
+import java.io.*;
+import java.lang.IllegalStateException;
+import java.util.*;
+
+/**
+ * Default implementation of the JMS Service.
+ */
+public class JmsServiceImpl implements JmsService {
+
+ private BundleContext bundleContext;
+ private File deployFolder;
+
+ public JmsServiceImpl() {
+ File karafBase = new File(System.getProperty("karaf.base"));
+ deployFolder = new File(karafBase, "deploy");
+ }
+
+ @Override
+ public void create(String name, String type, String url) throws Exception {
+ if (!type.equalsIgnoreCase("activemq") && !type.equalsIgnoreCase("webspheremq")) {
+ throw new IllegalArgumentException("JMS connection factory type not known");
+ }
+
+ File outFile = getConnectionFactoryFile(name);
+ String template;
+ HashMap<String, String> properties = new HashMap<String, String>();
+ properties.put("name", name);
+
+ if (type.equalsIgnoreCase("activemq")) {
+ // activemq
+ properties.put("url", url);
+ template = "connectionfactory-activemq.xml";
+ } else {
+ // webspheremq
+ String[] splitted = url.split("/");
+ if (splitted.length != 4) {
+ throw new IllegalStateException("WebsphereMQ URI should be in the following format: host/port/queuemanager/channel");
+ }
+
+ properties.put("host", splitted[0]);
+ properties.put("port", splitted[1]);
+ properties.put("queuemanager", splitted[2]);
+ properties.put("channel", splitted[3]);
+ template = "connectionfactory-webspheremq.xml";
+ }
+ InputStream is = this.getClass().getResourceAsStream(template);
+ if (is == null) {
+ throw new IllegalArgumentException("Template resource " + template + " doesn't exist");
+ }
+ TemplateUtils.createFromTemplate(outFile, is, properties);
+ }
+
+ private File getConnectionFactoryFile(String name) {
+ return new File(deployFolder, "connectionfactory-" + name + ".xml");
+ }
+
+ @Override
+ public void delete(String name) throws Exception {
+ File connectionFactoryFile = getConnectionFactoryFile(name);
+ if (!connectionFactoryFile.exists()) {
+ throw new IllegalStateException("The JMS connection factory file " + connectionFactoryFile.getPath() + " doesn't exist");
+ }
+ connectionFactoryFile.delete();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public List<String> connectionFactories() throws Exception {
+ List<String> connectionFactories = new ArrayList<String>();
+ ServiceReference[] references = bundleContext.getServiceReferences(ConnectionFactory.class.getName(), null);
+ if (references != null) {
+ for (ServiceReference reference : references) {
+ if (reference.getProperty("osgi.jndi.service.name") != null) {
+ connectionFactories.add((String) reference.getProperty("osgi.jndi.service.name"));
+ } else if (reference.getProperty("name") != null) {
+ connectionFactories.add((String) reference.getProperty("name"));
+ } else {
+ connectionFactories.add(reference.getProperty(Constants.SERVICE_ID).toString());
+ }
+ }
+ }
+ return connectionFactories;
+ }
+
+ @Override
+ public List<String> connectionFactoryFileNames() throws Exception {
+ String[] connectionFactoryFileNames = deployFolder.list(new FilenameFilter() {
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.startsWith("connectionfactory-") && name.endsWith(".xml");
+ }
+ });
+
+ return Arrays.asList(connectionFactoryFileNames);
+ }
+
+ @Override
+ public Map<String, String> info(String connectionFactory, String username, String password) throws IOException, JMSException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ ConnectionMetaData metaData = connector.connect().getMetaData();
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("product", metaData.getJMSProviderName());
+ map.put("version", metaData.getProviderVersion());
+ return map;
+ } finally {
+ connector.close();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int count(String connectionFactory, final String destination, String username, String password) throws IOException, JMSException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ Session session = connector.createSession();
+ QueueBrowser browser = session.createBrowser(session.createQueue(destination));
+ Enumeration<Message> enumeration = browser.getEnumeration();
+ int count = 0;
+ while (enumeration.hasMoreElements()) {
+ enumeration.nextElement();
+ count++;
+ }
+ browser.close();
+ return count;
+ } finally {
+ connector.close();
+ }
+ }
+
+ private DestinationSource getDestinationSource(Connection connection) throws JMSException {
+ if (connection instanceof PooledConnection) {
+ connection = ((PooledConnection) connection).getConnection();
+ }
+ if (connection instanceof ActiveMQConnection) {
+ return ((ActiveMQConnection) connection).getDestinationSource();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public List<String> queues(String connectionFactory, String username, String password) throws JMSException, IOException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ List<String> queues = new ArrayList<String>();
+ DestinationSource destinationSource = getDestinationSource(connector.connect());
+ if (destinationSource != null) {
+ Set<ActiveMQQueue> activeMQQueues = destinationSource.getQueues();
+ for (ActiveMQQueue activeMQQueue : activeMQQueues) {
+ queues.add(activeMQQueue.getQueueName());
+ }
+ }
+ return queues;
+ } finally {
+ connector.close();
+ }
+ }
+
+ @Override
+ public List<String> topics(String connectionFactory, String username, String password) throws IOException, JMSException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ DestinationSource destinationSource = getDestinationSource(connector.connect());
+ List<String> topics = new ArrayList<String>();
+ if (destinationSource != null) {
+ Set<ActiveMQTopic> activeMQTopics = destinationSource.getTopics();
+ for (ActiveMQTopic activeMQTopic : activeMQTopics) {
+ topics.add(activeMQTopic.getTopicName());
+ }
+ }
+ return topics;
+ } finally {
+ connector.close();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<JmsMessage> browse(String connectionFactory, final String queue, final String filter,
+ String username, String password) throws JMSException, IOException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ List<JmsMessage> messages = new ArrayList<JmsMessage>();
+ Session session = connector.createSession();
+ QueueBrowser browser = session.createBrowser(session.createQueue(queue), filter);
+ Enumeration<Message> enumeration = browser.getEnumeration();
+ while (enumeration.hasMoreElements()) {
+ Message message = enumeration.nextElement();
+
+ messages.add(new JmsMessage(message));
+ }
+ browser.close();
+ return messages;
+ } finally {
+ connector.close();
+ }
+ }
+
+ @Override
+ public void send(String connectionFactory, final String queue, final String body, final String replyTo,
+ String username, String password) throws IOException, JMSException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ Session session = connector.createSession();
+ Message message = session.createTextMessage(body);
+ if (replyTo != null) {
+ message.setJMSReplyTo(session.createQueue(replyTo));
+ }
+ MessageProducer producer = session.createProducer(session.createQueue(queue));
+ producer.send(message);
+ producer.close();
+ } finally {
+ connector.close();
+ }
+ }
+
+ @Override
+ public int consume(String connectionFactory, final String queue, final String selector, String username,
+ String password) throws Exception {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ int count = 0;
+ Session session = connector.createSession();
+ MessageConsumer consumer = session.createConsumer(session.createQueue(queue), selector);
+ Message message;
+ do {
+ message = consumer.receive(5000L);
+ if (message != null) {
+ count++;
+ }
+ } while (message != null);
+ return count;
+ } finally {
+ connector.close();
+ }
+ }
+
+ @Override
+ public int move(String connectionFactory, final String sourceQueue, final String targetQueue,
+ final String selector, String username, String password) throws IOException, JMSException {
+ JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
+ try {
+ int count = 0;
+ Session session = connector.createSession();
+ MessageConsumer consumer = session.createConsumer(session.createQueue(sourceQueue), selector);
+ Message message;
+ do {
+ message = consumer.receive(5000L);
+ if (message != null) {
+ MessageProducer producer = session.createProducer(session.createQueue(targetQueue));
+ producer.send(message);
+ count++;
+ }
+ } while (message != null);
+ consumer.close();
+ return count;
+ } finally {
+ connector.close();
+ }
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/resources/OSGI-INF/blueprint/jms-core.xml
----------------------------------------------------------------------
diff --git a/jms/src/main/resources/OSGI-INF/blueprint/jms-core.xml b/jms/src/main/resources/OSGI-INF/blueprint/jms-core.xml
new file mode 100644
index 0000000..7dd8070
--- /dev/null
+++ b/jms/src/main/resources/OSGI-INF/blueprint/jms-core.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ default-activation="lazy">
+
+ <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
+
+ <bean id="jmsService" class="org.apache.karaf.jms.internal.JmsServiceImpl">
+ <property name="bundleContext" ref="blueprintBundleContext"/>
+ </bean>
+
+ <service ref="jmsService" interface="org.apache.karaf.jms.JmsService" />
+
+ <!-- Management -->
+ <bean id="jmsMBeanImpl" class="org.apache.karaf.jms.internal.JmsMBeanImpl">
+ <property name="jmsService" ref="jmsService"/>
+ </bean>
+
+ <service ref="jmsMBeanImpl" auto-export="interfaces">
+ <service-properties>
+ <entry key="jmx.objectname" value="org.apache.karaf:type=jms,name=$[karaf.name]"/>
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jms/src/main/resources/OSGI-INF/bundle.info b/jms/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..1aeb646
--- /dev/null
+++ b/jms/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,18 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the JMS service support.
+
+The JMS service allows you to create connection factories, and send/browse/consume messages.
+
+h1. See also
+
+JMS - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
----------------------------------------------------------------------
diff --git a/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml b/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
new file mode 100644
index 0000000..f0aabbd
--- /dev/null
+++ b/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
+ <property name="brokerURL" value="${url}" />
+ </bean>
+
+ <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
+ <property name="maxConnections" value="8" />
+ <property name="connectionFactory" ref="activemqConnectionFactory" />
+ </bean>
+
+ <bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
+ <property name="transactionManager" ref="transactionManager" />
+ <property name="connectionFactory" ref="activemqConnectionFactory" />
+ <property name="resourceName" value="activemq.localhost" />
+ </bean>
+
+ <reference id="transactionManager" interface="javax.transaction.TransactionManager" />
+
+ <service ref="pooledConnectionFactory" interface="javax.jms.ConnectionFactory">
+ <service-properties>
+ <entry key="name" value="${name}" />
+ <entry key="osgi.jndi.service.name" value="jms/${name}" />
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
----------------------------------------------------------------------
diff --git a/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml b/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
new file mode 100644
index 0000000..3123f49
--- /dev/null
+++ b/jms/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="wmqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
+ <property name="transportType" value="1" />
+ <property name="hostName" value="${hostname}" />
+ <property name="port" value="${port}" />
+ <property name="queueManager" value="${queuemanager}" />
+ <property name="channel" value="${channel}" />
+ <property name="useConnectionPooling" value="true" />
+ </bean>
+
+ <service ref="wmqConnectionFactory" interface="javax.jms.ConnectionFactory">
+ <service-properties>
+ <entry key="name" value="${name}"/>
+ <entry key="osgi.jndi.service.name" value="jms/${name}"/>
+ </service-properties>
+ </service>
+
+</blueprint>
\ No newline at end of file
[11/33] git commit: [KARAF-2900] Allow generic requirements as
condition to features
Posted by gn...@apache.org.
[KARAF-2900] Allow generic requirements as condition to features
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/f2669e1d
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/f2669e1d
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/f2669e1d
Branch: refs/heads/master
Commit: f2669e1d709da292b679307f523a771769129e8b
Parents: fc37f55
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 17:04:09 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:03 2014 +0200
----------------------------------------------------------------------
.../standard/src/main/feature/feature.xml | 5 +++-
.../org/apache/karaf/features/Conditional.java | 2 +-
.../features/command/InfoFeatureCommand.java | 10 +++----
.../internal/deployment/DeploymentBuilder.java | 30 ++++++++++++++++----
.../features/internal/model/Conditional.java | 14 ++++-----
.../internal/resolver/FeatureResource.java | 16 +++++++++--
.../internal/service/FeaturesServiceImpl.java | 2 +-
.../apache/karaf/features/ConditionalTest.java | 13 +++++++--
.../karaf/features/internal/service/f06.xml | 4 +++
9 files changed, 69 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 4d06455..86f8270 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -222,7 +222,10 @@
</config>
<feature>shell</feature>
<feature>jaas</feature>
- <bundle start="true" start-level="30">mvn:org.apache.mina/mina-core/${mina.version}</bundle>
+ <conditional>
+ <condition>req:osgi.ee;filter:="(&(osgi.ee=JavaSE)(!(version>=1.7)))"</condition>
+ <bundle start="true" start-level="30">mvn:org.apache.mina/mina-core/${mina.version}</bundle>
+ </conditional>
<bundle start="true" start-level="30">mvn:org.apache.sshd/sshd-core/${sshd.version}</bundle>
<bundle start="true" start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/${project.version}</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Conditional.java b/features/src/main/java/org/apache/karaf/features/Conditional.java
index c0e4d59..fdc9261 100644
--- a/features/src/main/java/org/apache/karaf/features/Conditional.java
+++ b/features/src/main/java/org/apache/karaf/features/Conditional.java
@@ -21,7 +21,7 @@ import java.util.Map;
public interface Conditional {
- List<? extends Dependency> getCondition();
+ List<String> getCondition();
List<Dependency> getDependencies();
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
index 7084a6e..5ad855c 100644
--- a/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
+++ b/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
@@ -219,7 +219,7 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
if (conditional) {
for (Conditional cond : resolved.getConditional()) {
- List<? extends Dependency> condition = cond.getCondition();
+ List<String> condition = cond.getCondition();
List<BundleInfo> conditionalBundles = cond.getBundles();
for (BundleInfo bundleInfo : conditionalBundles) {
bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
@@ -278,13 +278,11 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
private String getConditionDescription(Conditional cond) {
StringBuffer sb = new StringBuffer();
- Iterator<? extends Dependency> di = cond.getCondition().iterator();
- while (di.hasNext()) {
- Dependency dep = di.next();
- sb.append(dep.getName()).append("/").append(dep.getVersion());
- if (di.hasNext()) {
+ for (String dep : cond.getCondition()) {
+ if (sb.length() > 0) {
sb.append(" ");
}
+ sb.append(dep);
}
return sb.toString();
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
index 00a91c4..c3ac2b7 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
@@ -158,8 +158,7 @@ public class DeploymentBuilder {
return resources;
}
- public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles,
- boolean resolveOptionalImports) throws ResolutionException {
+ public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles) throws ResolutionException {
// Resolve
for (int i = 0; i < systemBundles.size(); i++) {
resources.put("system-bundle-" + i, systemBundles.get(i));
@@ -172,11 +171,32 @@ public class DeploymentBuilder {
ResolverImpl resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
ResolveContext context = new ResolveContextImpl(
Collections.<Resource>singleton(requirements),
- this.optionals,
+ Collections.<Resource>emptySet(),
new AggregateRepository(repos),
- resolveOptionalImports);
+ false);
+ Map<Resource, List<Wire>> best = resolver.resolve(context);
- return resolver.resolve(context);
+ // TODO: we actually need to use multiple passes for conditionals
+ // TODO: but it may be optimized by passing the old wiring instead
+ // TODO: of computing everything again
+ Set<Resource> resources = new HashSet<Resource>();
+ resources.add(requirements);
+ for (Resource optional : optionals) {
+ try {
+ Set<Resource> newSet = new HashSet<Resource>(resources);
+ newSet.add(optional);
+ context = new ResolveContextImpl(
+ newSet,
+ Collections.<Resource>emptySet(),
+ new AggregateRepository(repos),
+ false);
+ best = resolver.resolve(context);
+ resources = newSet;
+ } catch (ResolutionException e) {
+ // Ignore this resource
+ }
+ }
+ return best;
}
public void requireFeature(String feature) throws IOException {
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java b/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
index 5bc0b95..ed0e8ff 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
@@ -36,11 +36,11 @@ import org.apache.karaf.features.Feature;
public class Conditional extends Content implements org.apache.karaf.features.Conditional {
@XmlElement(name = "condition")
- protected List<Dependency> condition;
+ protected List<String> condition;
- public List<Dependency> getCondition() {
+ public List<String> getCondition() {
if (condition == null) {
- this.condition = new ArrayList<Dependency>();
+ this.condition = new ArrayList<String>();
}
return condition;
}
@@ -58,13 +58,11 @@ public class Conditional extends Content implements org.apache.karaf.features.Co
private String getConditionId() {
StringBuffer sb = new StringBuffer();
- Iterator<Dependency> di = getCondition().iterator();
- while (di.hasNext()) {
- Dependency dependency = di.next();
- sb.append(dependency.getName() + "_" + dependency.getVersion());
- if (di.hasNext()) {
+ for (String cond : getCondition()) {
+ if (sb.length() > 0) {
sb.append("_");
}
+ sb.append(cond);
}
return sb.toString();
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
index 88f08ae..e3b0101 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
@@ -44,8 +44,20 @@ public class FeatureResource extends ResourceImpl {
public static Resource build(Feature feature, Conditional conditional, String featureRange, Map<String, Resource> locToRes) throws BundleException {
Feature fcond = conditional.asFeature(feature.getName(), feature.getVersion());
FeatureResource resource = (FeatureResource) build(fcond, featureRange, locToRes);
- for (Dependency dep : conditional.getCondition()) {
- addDependency(resource, dep, featureRange);
+ for (String cond : conditional.getCondition()) {
+ if (cond.startsWith("req:")) {
+ cond = cond.substring("req:".length());
+ List<Requirement> reqs = ResourceBuilder.parseRequirement(resource, cond);
+ resource.addRequirements(reqs);
+ } else {
+ org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
+ String[] p = cond.split("/");
+ dep.setName(p[0]);
+ if (p.length > 1) {
+ dep.setVersion(p[1]);
+ }
+ addDependency(resource, dep, featureRange);
+ }
}
org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
dep.setName(feature.getName());
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index 7008ef6..0243dc0 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -790,7 +790,7 @@ public class FeaturesServiceImpl implements FeaturesService {
Collections.<String>emptySet(),
overrides,
Collections.<String>emptySet());
- Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, true);
+ Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles);
Collection<Resource> allResources = resolution.keySet();
Map<String, StreamProvider> providers = builder.getProviders();
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/ConditionalTest.java b/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
index d5e7e46..b103683 100644
--- a/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
+++ b/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
@@ -31,17 +31,24 @@ public class ConditionalTest extends TestCase {
Feature feature = features[0];
assertNotNull(feature.getConditional());
- assertEquals(1,feature.getConditional().size());
+ assertEquals(2,feature.getConditional().size());
Conditional conditional = feature.getConditional().get(0);
assertNotNull(conditional.getCondition());
assertEquals(1,conditional.getCondition().size());
- Dependency dependency = conditional.getCondition().get(0);
+ String dependency = conditional.getCondition().get(0);
assertNotNull(dependency);
- assertEquals(dependency.getName(),"http");
+ assertEquals("http", dependency);
assertNotNull(conditional.getBundles());
assertEquals(1, feature.getConditional().get(0).getBundles().size());
+ conditional = feature.getConditional().get(1);
+ assertNotNull(conditional.getCondition());
+ assertEquals(1,conditional.getCondition().size());
+ dependency = conditional.getCondition().get(0);
+ assertNotNull(dependency);
+ assertEquals("req:osgi.ee;filter:=\"(&(osgi.ee=JavaSE)(!(version>=1.7)))\"", dependency);
+
String wrapperName = "my6/1.5.3-beta-3".replaceAll("[^A-Za-z0-9 ]", "_");
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/f2669e1d/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
index 496cbdb..51e78f1 100644
--- a/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
@@ -27,6 +27,10 @@
<condition>http</condition>
<bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
</conditional>
+ <conditional>
+ <condition>req:osgi.ee;filter:="(&(osgi.ee=JavaSE)(!(version>=1.7)))"</condition>
+ <bundle start="true" start-level="30">mvn:org.apache.mina/mina-core/${mina.version}</bundle>
+ </conditional>
</feature>
</features>
[27/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
new file mode 100644
index 0000000..93827bf
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.features.BootFinished;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BootFeaturesInstaller {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BootFeaturesInstaller.class);
+
+ public static String VERSION_PREFIX = "version=";
+
+ private final FeaturesServiceImpl featuresService;
+ private final BundleContext bundleContext;
+ private final String repositories;
+ private final String features;
+ private final boolean asynchronous;
+
+ /**
+ *
+ * @param features list of boot features separated by comma. Optionally contains ;version=x.x.x to specify a specific feature version
+ */
+ public BootFeaturesInstaller(BundleContext bundleContext,
+ FeaturesServiceImpl featuresService,
+ String repositories,
+ String features,
+ boolean asynchronous) {
+ this.bundleContext = bundleContext;
+ this.featuresService = featuresService;
+ this.repositories = repositories;
+ this.features = features;
+ this.asynchronous = asynchronous;
+ }
+
+ /**
+ * Install boot features
+ */
+ public void start() {
+ if (featuresService.isBootDone()) {
+ publishBootFinished();
+ return;
+ }
+ if (asynchronous) {
+ new Thread("Initial Features Provisioning") {
+ public void run() {
+ installBootFeatures();
+ }
+ }.start();
+ } else {
+ installBootFeatures();
+ }
+ }
+
+ protected void installBootFeatures() {
+ try {
+ for (String repo : repositories.split(",")) {
+ repo = repo.trim();
+ if (!repo.isEmpty()) {
+ try {
+ featuresService.addRepository(URI.create(repo));
+ } catch (Exception e) {
+ LOGGER.error("Error installing boot feature repository " + repo, e);
+ }
+ }
+ }
+
+ List<Set<String>> stagedFeatures = parseBootFeatures(features);
+ for (Set<String> features : stagedFeatures) {
+ featuresService.installFeatures(features, EnumSet.of(FeaturesService.Option.NoFailOnFeatureNotFound));
+ }
+ featuresService.bootDone();
+ publishBootFinished();
+ } catch (Exception e) {
+ // Special handling in case the bundle has been refreshed.
+ // In such a case, simply exits without logging any exception
+ // as the restart should cause the feature service to finish
+ // the work.
+ if (e instanceof IllegalStateException) {
+ try {
+ bundleContext.getBundle();
+ } catch (IllegalStateException ies) {
+ return;
+ }
+ }
+ LOGGER.error("Error installing boot features", e);
+ }
+ }
+
+ /**
+ *
+ * @param featureSt either feature name or <featurename>;version=<version>
+ * @return feature matching the feature string
+ * @throws Exception
+ */
+ private Feature getFeature(String featureSt) throws Exception {
+ String[] parts = featureSt.trim().split(";");
+ String featureName = parts[0];
+ String featureVersion = null;
+ for (String part : parts) {
+ // if the part starts with "version=" it contains the version info
+ if (part.startsWith(VERSION_PREFIX)) {
+ featureVersion = part.substring(VERSION_PREFIX.length());
+ }
+ }
+ if (featureVersion == null) {
+ // no version specified - use default version
+ featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
+ }
+ return featuresService.getFeature(featureName, featureVersion);
+ }
+
+ protected List<Set<String>> parseBootFeatures(String bootFeatures) {
+ Pattern pattern = Pattern.compile("(\\((.+))\\),|.+");
+ Matcher matcher = pattern.matcher(bootFeatures);
+ List<Set<String>> result = new ArrayList<Set<String>>();
+ while (matcher.find()) {
+ String group = matcher.group(2) != null ? matcher.group(2) : matcher.group();
+ result.add(parseFeatureList(group));
+ }
+ return result;
+ }
+
+ protected Set<String> parseFeatureList(String group) {
+ HashSet<String> features = new HashSet<String>();
+ for (String feature : Arrays.asList(group.trim().split("\\s*,\\s*"))) {
+ if (feature.length() > 0) {
+ features.add(feature);
+ }
+ }
+ return features;
+ }
+
+ private void publishBootFinished() {
+ if (bundleContext != null) {
+ BootFinished bootFinished = new BootFinished() {};
+ bundleContext.registerService(BootFinished.class, bootFinished, new Hashtable<String, String>());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
new file mode 100644
index 0000000..b6eaae5
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.features.EventConstants;
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.RepositoryEvent;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * A listener to publish events to EventAdmin
+ */
+public class EventAdminListener implements FeaturesListener {
+
+ private final ServiceTracker<EventAdmin, EventAdmin> tracker;
+
+ public EventAdminListener(BundleContext context) {
+ tracker = new ServiceTracker<EventAdmin, EventAdmin>(context, EventAdmin.class.getName(), null);
+ tracker.open();
+ }
+
+ public void featureEvent(FeatureEvent event) {
+ EventAdmin eventAdmin = tracker.getService();
+ if (eventAdmin == null) {
+ return;
+ }
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(EventConstants.TYPE, event.getType());
+ props.put(EventConstants.EVENT, event);
+ props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
+ props.put(EventConstants.FEATURE_NAME, event.getFeature().getName());
+ props.put(EventConstants.FEATURE_VERSION, event.getFeature().getVersion());
+ String topic;
+ switch (event.getType()) {
+ case FeatureInstalled:
+ topic = EventConstants.TOPIC_FEATURES_INSTALLED;
+ break;
+ case FeatureUninstalled:
+ topic = EventConstants.TOPIC_FEATURES_UNINSTALLED;
+ break;
+ default:
+ throw new IllegalStateException("Unknown features event type: " + event.getType());
+ }
+ eventAdmin.postEvent(new Event(topic, props));
+ }
+
+ public void repositoryEvent(RepositoryEvent event) {
+ EventAdmin eventAdmin = tracker.getService();
+ if (eventAdmin == null) {
+ return;
+ }
+ Dictionary<String, Object> props = new Hashtable<String, Object>();
+ props.put(EventConstants.TYPE, event.getType());
+ props.put(EventConstants.EVENT, event);
+ props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
+ props.put(EventConstants.REPOSITORY_URI, event.getRepository().getURI().toString());
+ String topic;
+ switch (event.getType()) {
+ case RepositoryAdded:
+ topic = EventConstants.TOPIC_REPOSITORY_ADDED;
+ break;
+ case RepositoryRemoved:
+ topic = EventConstants.TOPIC_REPOSITORY_REMOVED;
+ break;
+ default:
+ throw new IllegalStateException("Unknown repository event type: " + event.getType());
+ }
+ eventAdmin.postEvent(new Event(topic, props));
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
new file mode 100644
index 0000000..0e9038d
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Feature;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FeatureConfigInstaller {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
+ private static final String CONFIG_KEY = "org.apache.karaf.features.configKey";
+
+ private final ConfigurationAdmin configAdmin;
+
+ public FeatureConfigInstaller(ConfigurationAdmin configAdmin) {
+ this.configAdmin = configAdmin;
+ }
+
+ private String[] parsePid(String pid) {
+ int n = pid.indexOf('-');
+ if (n > 0) {
+ String factoryPid = pid.substring(n + 1);
+ pid = pid.substring(0, n);
+ return new String[]{pid, factoryPid};
+ } else {
+ return new String[]{pid, null};
+ }
+ }
+
+ private Configuration createConfiguration(ConfigurationAdmin configurationAdmin,
+ String pid, String factoryPid) throws IOException, InvalidSyntaxException {
+ if (factoryPid != null) {
+ return configurationAdmin.createFactoryConfiguration(factoryPid, null);
+ } else {
+ return configurationAdmin.getConfiguration(pid, null);
+ }
+ }
+
+ private Configuration findExistingConfiguration(ConfigurationAdmin configurationAdmin,
+ String pid, String factoryPid) throws IOException, InvalidSyntaxException {
+ String filter;
+ if (factoryPid == null) {
+ filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
+ } else {
+ String key = createConfigurationKey(pid, factoryPid);
+ filter = "(" + CONFIG_KEY + "=" + key + ")";
+ }
+ Configuration[] configurations = configurationAdmin.listConfigurations(filter);
+ if (configurations != null && configurations.length > 0) {
+ return configurations[0];
+ }
+ return null;
+ }
+
+ void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
+ for (String config : feature.getConfigurations().keySet()) {
+ Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config));
+ String[] pid = parsePid(config);
+ Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
+ if (cfg == null) {
+ cfg = createConfiguration(configAdmin, pid[0], pid[1]);
+ String key = createConfigurationKey(pid[0], pid[1]);
+ props.put(CONFIG_KEY, key);
+ if (cfg.getBundleLocation() != null) {
+ cfg.setBundleLocation(null);
+ }
+ cfg.update(props);
+ }
+ }
+ for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
+ installConfigurationFile(configFile.getLocation(), configFile.getFinalname(), configFile.isOverride());
+ }
+ }
+
+ private String createConfigurationKey(String pid, String factoryPid) {
+ return factoryPid == null ? pid : pid + "-" + factoryPid;
+ }
+
+ private void installConfigurationFile(String fileLocation, String finalname, boolean override) throws IOException {
+ String basePath = System.getProperty("karaf.base");
+
+ if (finalname.contains("${")) {
+ //remove any placeholder or variable part, this is not valid.
+ int marker = finalname.indexOf("}");
+ finalname = finalname.substring(marker+1);
+ }
+
+ finalname = basePath + File.separator + finalname;
+
+ File file = new File(finalname);
+ if (file.exists()) {
+ if (!override) {
+ LOGGER.debug("Configuration file {} already exist, don't override it", finalname);
+ return;
+ } else {
+ LOGGER.info("Configuration file {} already exist, overriding it", finalname);
+ }
+ } else {
+ LOGGER.info("Creating configuration file {}", finalname);
+ }
+
+ InputStream is = null;
+ FileOutputStream fop = null;
+ try {
+ is = new BufferedInputStream(new URL(fileLocation).openStream());
+
+ if (!file.exists()) {
+ File parentFile = file.getParentFile();
+ if (parentFile != null)
+ parentFile.mkdirs();
+ file.createNewFile();
+ }
+
+ fop = new FileOutputStream(file);
+
+ int bytesRead;
+ byte[] buffer = new byte[1024];
+
+ while ((bytesRead = is.read(buffer)) != -1) {
+ fop.write(buffer, 0, bytesRead);
+ }
+ } catch (RuntimeException e) {
+ LOGGER.error(e.getMessage());
+ throw e;
+ } catch (MalformedURLException e) {
+ LOGGER.error(e.getMessage());
+ throw e;
+ } finally {
+ if (is != null)
+ is.close();
+ if (fop != null) {
+ fop.flush();
+ fop.close();
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
new file mode 100644
index 0000000..d6defe0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.net.URI;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+public class FeatureFinder implements ManagedService {
+
+ final Map<String, String> nameToArtifactMap = new HashMap<String, String>();
+
+ public String[] getNames() {
+ synchronized (nameToArtifactMap) {
+ Set<String> strings = nameToArtifactMap.keySet();
+ return strings.toArray(new String[strings.size()]);
+ }
+ }
+
+ public URI getUriFor(String name, String version) {
+ String coords;
+ synchronized (nameToArtifactMap) {
+ coords = nameToArtifactMap.get(name);
+ }
+ if (coords == null) {
+ return null;
+ }
+ Artifact artifact = new Artifact(coords);
+ return artifact.getMavenUrl(version);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void updated(Dictionary properties) throws ConfigurationException {
+ synchronized (nameToArtifactMap) {
+ if (properties != null) {
+ nameToArtifactMap.clear();
+ Enumeration keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ if (!"felix.fileinstall.filename".equals(key) && !"service.pid".equals(key)) {
+ nameToArtifactMap.put(key, (String) properties.get(key));
+ }
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
new file mode 100644
index 0000000..6903dc0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.net.URI;
+
+import org.apache.karaf.features.internal.model.JaxbUtil;
+
+/**
+ * Utility class which fires XML Schema validation.
+ */
+public class FeatureValidationUtil {
+
+ /**
+ * Runs schema validation.
+ *
+ * @param uri Uri to validate.
+ * @throws Exception When validation fails.
+ */
+ public static void validate(URI uri) throws Exception {
+ JaxbUtil.unmarshal(uri.toASCIIString(), true);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
new file mode 100644
index 0000000..0243dc0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -0,0 +1,1416 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.RepositoryEvent;
+import org.apache.karaf.features.internal.deployment.DeploymentBuilder;
+import org.apache.karaf.features.internal.deployment.StreamProvider;
+import org.apache.karaf.features.internal.resolver.FeatureNamespace;
+import org.apache.karaf.features.internal.resolver.UriNamespace;
+import org.apache.karaf.features.internal.util.ChecksumUtils;
+import org.apache.karaf.features.internal.util.Macro;
+import org.apache.karaf.features.internal.util.MultiException;
+import org.apache.karaf.util.collections.CopyOnWriteArrayIdentityList;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.felix.resolver.Util.getSymbolicName;
+import static org.apache.felix.resolver.Util.getVersion;
+
+/**
+ *
+ */
+public class FeaturesServiceImpl implements FeaturesService {
+
+ public static final String UPDATE_SNAPSHOTS_NONE = "none";
+ public static final String UPDATE_SNAPSHOTS_CRC = "crc";
+ public static final String UPDATE_SNAPSHOTS_ALWAYS = "always";
+ public static final String DEFAULT_UPDATE_SNAPSHOTS = UPDATE_SNAPSHOTS_CRC;
+
+ public static final String DEFAULT_FEATURE_RESOLUTION_RANGE = "${range;[====,====]}";
+ public static final String DEFAULT_BUNDLE_UPDATE_RANGE = "${range;[==,=+)}";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
+ private static final String SNAPSHOT = "SNAPSHOT";
+ private static final String MAVEN = "mvn:";
+
+ /**
+ * Our bundle.
+ * We use it to check bundle operations affecting our own bundle.
+ */
+ private final Bundle bundle;
+
+ /**
+ * The system bundle context.
+ * For all bundles related operations, we use the system bundle context
+ * to allow this bundle to be stopped and still allow the deployment to
+ * take place.
+ */
+ private final BundleContext systemBundleContext;
+ /**
+ * Used to load and save the {@link State} of this service.
+ */
+ private final StateStorage storage;
+ private final FeatureFinder featureFinder;
+ private final EventAdminListener eventAdminListener;
+ private final FeatureConfigInstaller configInstaller;
+ private final String overrides;
+ /**
+ * Range to use when a version is specified on a feature dependency.
+ * The default is {@link FeaturesServiceImpl#DEFAULT_FEATURE_RESOLUTION_RANGE}
+ */
+ private final String featureResolutionRange;
+ /**
+ * Range to use when verifying if a bundle should be updated or
+ * new bundle installed.
+ * The default is {@link FeaturesServiceImpl#DEFAULT_BUNDLE_UPDATE_RANGE}
+ */
+ private final String bundleUpdateRange;
+ /**
+ * Use CRC to check snapshot bundles and update them if changed.
+ * Either:
+ * - none : never update snapshots
+ * - always : always update snapshots
+ * - crc : use CRC to detect changes
+ */
+ private final String updateSnaphots;
+
+ private final List<FeaturesListener> listeners = new CopyOnWriteArrayIdentityList<FeaturesListener>();
+
+ // Synchronized on lock
+ private final Object lock = new Object();
+ private final State state = new State();
+ private final Map<String, Repository> repositoryCache = new HashMap<String, Repository>();
+ private Map<String, Map<String, Feature>> featureCache;
+
+
+ public FeaturesServiceImpl(Bundle bundle,
+ BundleContext systemBundleContext,
+ StateStorage storage,
+ FeatureFinder featureFinder,
+ EventAdminListener eventAdminListener,
+ FeatureConfigInstaller configInstaller,
+ String overrides,
+ String featureResolutionRange,
+ String bundleUpdateRange,
+ String updateSnaphots) {
+ this.bundle = bundle;
+ this.systemBundleContext = systemBundleContext;
+ this.storage = storage;
+ this.featureFinder = featureFinder;
+ this.eventAdminListener = eventAdminListener;
+ this.configInstaller = configInstaller;
+ this.overrides = overrides;
+ this.featureResolutionRange = featureResolutionRange;
+ this.bundleUpdateRange = bundleUpdateRange;
+ this.updateSnaphots = updateSnaphots;
+ loadState();
+ }
+
+ //
+ // State support
+ //
+
+ protected void loadState() {
+ try {
+ synchronized (lock) {
+ storage.load(state);
+ }
+ } catch (IOException e) {
+ LOGGER.warn("Error loading FeaturesService state", e);
+ }
+ }
+
+ protected void saveState() {
+ try {
+ synchronized (lock) {
+ // Make sure we don't store bundle checksums if
+ // it has been disabled through configadmin
+ // so that we don't keep out-of-date checksums.
+ if (!UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
+ state.bundleChecksums.clear();
+ }
+ storage.save(state);
+ }
+ } catch (IOException e) {
+ LOGGER.warn("Error saving FeaturesService state", e);
+ }
+ }
+
+ boolean isBootDone() {
+ synchronized (lock) {
+ return state.bootDone.get();
+ }
+ }
+
+ void bootDone() {
+ synchronized (lock) {
+ state.bootDone.set(true);
+ saveState();
+ }
+ }
+
+ //
+ // Listeners support
+ //
+
+ public void registerListener(FeaturesListener listener) {
+ listeners.add(listener);
+ try {
+ Set<String> repositories = new TreeSet<String>();
+ Set<String> installedFeatures = new TreeSet<String>();
+ synchronized (lock) {
+ repositories.addAll(state.repositories);
+ installedFeatures.addAll(state.installedFeatures);
+ }
+ for (String uri : repositories) {
+ Repository repository = new RepositoryImpl(URI.create(uri));
+ listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
+ }
+ for (String id : installedFeatures) {
+ Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf(id);
+ listener.featureEvent(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, true));
+ }
+ } catch (Exception e) {
+ LOGGER.error("Error notifying listener about the current state", e);
+ }
+ }
+
+ public void unregisterListener(FeaturesListener listener) {
+ listeners.remove(listener);
+ }
+
+ protected void callListeners(FeatureEvent event) {
+ if (eventAdminListener != null) {
+ eventAdminListener.featureEvent(event);
+ }
+ for (FeaturesListener listener : listeners) {
+ listener.featureEvent(event);
+ }
+ }
+
+ protected void callListeners(RepositoryEvent event) {
+ if (eventAdminListener != null) {
+ eventAdminListener.repositoryEvent(event);
+ }
+ for (FeaturesListener listener : listeners) {
+ listener.repositoryEvent(event);
+ }
+ }
+
+ //
+ // Feature Finder support
+ //
+
+ @Override
+ public URI getRepositoryUriFor(String name, String version) {
+ return featureFinder.getUriFor(name, version);
+ }
+
+ @Override
+ public String[] getRepositoryNames() {
+ return featureFinder.getNames();
+ }
+
+
+ //
+ // Repositories support
+ //
+
+ public Repository loadRepository(URI uri) throws Exception {
+ RepositoryImpl repo = new RepositoryImpl(uri);
+ repo.load(true);
+ return repo;
+ }
+
+ @Override
+ public void validateRepository(URI uri) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void addRepository(URI uri) throws Exception {
+ addRepository(uri, false);
+ }
+
+ @Override
+ public void addRepository(URI uri, boolean install) throws Exception {
+ if (install) {
+ // TODO: implement
+ throw new UnsupportedOperationException();
+ }
+ Repository repository = loadRepository(uri);
+ synchronized (lock) {
+ // Clean cache
+ repositoryCache.put(uri.toString(), repository);
+ featureCache = null;
+ // Add repo
+ if (!state.repositories.add(uri.toString())) {
+ return;
+ }
+ saveState();
+ }
+ callListeners(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, false));
+ }
+
+ @Override
+ public void removeRepository(URI uri) throws Exception {
+ removeRepository(uri, true);
+ }
+
+ @Override
+ public void removeRepository(URI uri, boolean uninstall) throws Exception {
+ // TODO: check we don't have any feature installed from this repository
+ Repository repo;
+ synchronized (lock) {
+ // Remove repo
+ if (!state.repositories.remove(uri.toString())) {
+ return;
+ }
+ // Clean cache
+ featureCache = null;
+ repo = repositoryCache.get(uri.toString());
+ List<String> toRemove = new ArrayList<String>();
+ toRemove.add(uri.toString());
+ while (!toRemove.isEmpty()) {
+ Repository rep = repositoryCache.remove(toRemove.remove(0));
+ if (rep != null) {
+ for (URI u : rep.getRepositories()) {
+ toRemove.add(u.toString());
+ }
+ }
+ }
+ saveState();
+ }
+ if (repo == null) {
+ repo = new RepositoryImpl(uri);
+ }
+ callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryRemoved, false));
+ }
+
+ @Override
+ public void restoreRepository(URI uri) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void refreshRepository(URI uri) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Repository[] listRepositories() throws Exception {
+ // Make sure the cache is loaded
+ getFeatures();
+ synchronized (lock) {
+ return repositoryCache.values().toArray(new Repository[repositoryCache.size()]);
+ }
+ }
+
+ @Override
+ public Repository[] listRequiredRepositories() throws Exception {
+ // Make sure the cache is loaded
+ getFeatures();
+ synchronized (lock) {
+ List<Repository> repos = new ArrayList<Repository>();
+ for (Map.Entry<String, Repository> entry : repositoryCache.entrySet()) {
+ if (state.repositories.contains(entry.getKey())) {
+ repos.add(entry.getValue());
+ }
+ }
+ return repos.toArray(new Repository[repos.size()]);
+ }
+ }
+
+ @Override
+ public Repository getRepository(String name) throws Exception {
+ // Make sure the cache is loaded
+ getFeatures();
+ synchronized (lock) {
+ for (Repository repo : this.repositoryCache.values()) {
+ if (name.equals(repo.getName())) {
+ return repo;
+ }
+ }
+ return null;
+ }
+ }
+
+ //
+ // Features support
+ //
+
+ public Feature getFeature(String name) throws Exception {
+ return getFeature(name, null);
+ }
+
+ public Feature getFeature(String name, String version) throws Exception {
+ Map<String, Feature> versions = getFeatures().get(name);
+ return getFeatureMatching(versions, version);
+ }
+
+ protected Feature getFeatureMatching(Map<String, Feature> versions, String version) {
+ if (version != null) {
+ version = version.trim();
+ if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
+ version = "";
+ }
+ } else {
+ version = "";
+ }
+ if (versions == null || versions.isEmpty()) {
+ return null;
+ } else {
+ Feature feature = version.isEmpty() ? null : versions.get(version);
+ if (feature == null) {
+ // Compute version range. If an version has been given, assume exact range
+ VersionRange versionRange = version.isEmpty() ?
+ new VersionRange(Version.emptyVersion) :
+ new VersionRange(version, true, true);
+ Version latest = Version.emptyVersion;
+ for (String available : versions.keySet()) {
+ Version availableVersion = VersionTable.getVersion(available);
+ if (availableVersion.compareTo(latest) >= 0 && versionRange.contains(availableVersion)) {
+ feature = versions.get(available);
+ latest = availableVersion;
+ }
+ }
+ }
+ return feature;
+ }
+ }
+
+ public Feature[] listFeatures() throws Exception {
+ Set<Feature> features = new HashSet<Feature>();
+ for (Map<String, Feature> featureWithDifferentVersion : getFeatures().values()) {
+ for (Feature f : featureWithDifferentVersion.values()) {
+ features.add(f);
+ }
+ }
+ return features.toArray(new Feature[features.size()]);
+ }
+
+ protected Map<String, Map<String, Feature>> getFeatures() throws Exception {
+ List<String> uris;
+ synchronized (lock) {
+ if (featureCache != null) {
+ return featureCache;
+ }
+ uris = new ArrayList<String>(state.repositories);
+ }
+ //the outer map's key is feature name, the inner map's key is feature version
+ Map<String, Map<String, Feature>> map = new HashMap<String, Map<String, Feature>>();
+ // Two phase load:
+ // * first load dependent repositories
+ List<String> toLoad = new ArrayList<String>(uris);
+ while (!toLoad.isEmpty()) {
+ String uri = toLoad.remove(0);
+ Repository repo;
+ synchronized (lock) {
+ repo = repositoryCache.get(uri);
+ }
+ if (repo == null) {
+ RepositoryImpl rep = new RepositoryImpl(URI.create(uri));
+ rep.load();
+ repo = rep;
+ synchronized (lock) {
+ repositoryCache.put(uri, repo);
+ }
+ }
+ for (URI u : repo.getRepositories()) {
+ toLoad.add(u.toString());
+ }
+ }
+ List<Repository> repos;
+ synchronized (lock) {
+ repos = new ArrayList<Repository>(repositoryCache.values());
+ }
+ // * then load all features
+ for (Repository repo : repos) {
+ for (Feature f : repo.getFeatures()) {
+ if (map.get(f.getName()) == null) {
+ Map<String, Feature> versionMap = new HashMap<String, Feature>();
+ versionMap.put(f.getVersion(), f);
+ map.put(f.getName(), versionMap);
+ } else {
+ map.get(f.getName()).put(f.getVersion(), f);
+ }
+ }
+ }
+ synchronized (lock) {
+ if (uris.size() == state.repositories.size() &&
+ state.repositories.containsAll(uris)) {
+ featureCache = map;
+ }
+ }
+ return map;
+ }
+
+ //
+ // Installed features
+ //
+
+ @Override
+ public Feature[] listInstalledFeatures() throws Exception {
+ Set<Feature> features = new HashSet<Feature>();
+ Map<String, Map<String, Feature>> allFeatures = getFeatures();
+ synchronized (lock) {
+ for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
+ for (Feature f : featureWithDifferentVersion.values()) {
+ if (isInstalled(f)) {
+ features.add(f);
+ }
+ }
+ }
+ }
+ return features.toArray(new Feature[features.size()]);
+ }
+
+ @Override
+ public Feature[] listRequiredFeatures() throws Exception {
+ Set<Feature> features = new HashSet<Feature>();
+ Map<String, Map<String, Feature>> allFeatures = getFeatures();
+ synchronized (lock) {
+ for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
+ for (Feature f : featureWithDifferentVersion.values()) {
+ if (isRequired(f)) {
+ features.add(f);
+ }
+ }
+ }
+ }
+ return features.toArray(new Feature[features.size()]);
+ }
+
+
+ @Override
+ public boolean isInstalled(Feature f) {
+ String id = normalize(f.getId());
+ synchronized (lock) {
+ return state.installedFeatures.contains(id);
+ }
+ }
+
+ @Override
+ public boolean isRequired(Feature f) {
+ String id = normalize(f.getId());
+ synchronized (lock) {
+ return state.features.contains(id);
+ }
+ }
+
+ //
+ // Installation and uninstallation of features
+ //
+
+ public void installFeature(String name) throws Exception {
+ installFeature(name, EnumSet.noneOf(Option.class));
+ }
+
+ public void installFeature(String name, String version) throws Exception {
+ installFeature(version != null ? name + "/" + version : name, EnumSet.noneOf(Option.class));
+ }
+
+ public void installFeature(String name, EnumSet<Option> options) throws Exception {
+ installFeatures(Collections.singleton(name), options);
+ }
+
+ public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
+ installFeature(version != null ? name + "/" + version : name, options);
+ }
+
+ public void installFeature(Feature feature, EnumSet<Option> options) throws Exception {
+ installFeature(feature.getId());
+ }
+
+ @Override
+ public void uninstallFeature(String name, String version) throws Exception {
+ uninstallFeature(version != null ? name + "/" + version : name);
+ }
+
+ @Override
+ public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
+ uninstallFeature(version != null ? name + "/" + version : name, options);
+ }
+
+ @Override
+ public void uninstallFeature(String name) throws Exception {
+ uninstallFeature(name, EnumSet.noneOf(Option.class));
+ }
+
+ @Override
+ public void uninstallFeature(String name, EnumSet<Option> options) throws Exception {
+ uninstallFeatures(Collections.singleton(name), options);
+ }
+
+
+ //
+ //
+ //
+ // RESOLUTION
+ //
+ //
+ //
+
+
+
+
+
+
+ public void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+ Set<String> required;
+ Set<String> installed;
+ Set<Long> managed;
+ synchronized (lock) {
+ required = new HashSet<String>(state.features);
+ installed = new HashSet<String>(state.installedFeatures);
+ managed = new HashSet<Long>(state.managedBundles);
+ }
+ List<String> featuresToAdd = new ArrayList<String>();
+ Map<String, Map<String, Feature>> featuresMap = getFeatures();
+ for (String feature : features) {
+ feature = normalize(feature);
+ String name = feature.substring(0, feature.indexOf("/"));
+ String version = feature.substring(feature.indexOf("/") + 1);
+ Feature f = getFeatureMatching(featuresMap.get(name), version);
+ if (f == null) {
+ if (!options.contains(Option.NoFailOnFeatureNotFound)) {
+ throw new IllegalArgumentException("No matching features for " + feature);
+ }
+ } else {
+ featuresToAdd.add(normalize(f.getId()));
+ }
+ }
+ featuresToAdd = new ArrayList<String>(new LinkedHashSet<String>(featuresToAdd));
+ StringBuilder sb = new StringBuilder();
+ sb.append("Adding features: ");
+ for (int i = 0; i < featuresToAdd.size(); i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(featuresToAdd.get(i));
+ }
+ print(sb.toString(), options.contains(Option.Verbose));
+ required.addAll(featuresToAdd);
+ doInstallFeaturesInThread(required, installed, managed, options);
+ }
+
+ public void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+ Set<String> required;
+ Set<String> installed;
+ Set<Long> managed;
+ synchronized (lock) {
+ required = new HashSet<String>(state.features);
+ installed = new HashSet<String>(state.installedFeatures);
+ managed = new HashSet<Long>(state.managedBundles);
+ }
+ List<String> featuresToRemove = new ArrayList<String>();
+ for (String feature : new HashSet<String>(features)) {
+ List<String> toRemove = new ArrayList<String>();
+ feature = normalize(feature);
+ if (feature.endsWith("/0.0.0")) {
+ String nameSep = feature.substring(0, feature.indexOf("/") + 1);
+ for (String f : required) {
+ if (normalize(f).startsWith(nameSep)) {
+ toRemove.add(f);
+ }
+ }
+ } else {
+ toRemove.add(feature);
+ }
+ toRemove.retainAll(required);
+ if (toRemove.isEmpty()) {
+ throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
+ } else if (toRemove.size() > 1) {
+ String name = feature.substring(0, feature.indexOf("/"));
+ StringBuilder sb = new StringBuilder();
+ sb.append("Feature named '").append(name).append("' has multiple versions installed (");
+ for (int i = 0; i < toRemove.size(); i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(toRemove.get(i));
+ }
+ sb.append("). Please specify the version to uninstall.");
+ throw new IllegalArgumentException(sb.toString());
+ }
+ featuresToRemove.addAll(toRemove);
+ }
+ featuresToRemove = new ArrayList<String>(new LinkedHashSet<String>(featuresToRemove));
+ StringBuilder sb = new StringBuilder();
+ sb.append("Removing features: ");
+ for (int i = 0; i < featuresToRemove.size(); i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(featuresToRemove.get(i));
+ }
+ print(sb.toString(), options.contains(Option.Verbose));
+ required.removeAll(featuresToRemove);
+ doInstallFeaturesInThread(required, installed, managed, options);
+ }
+
+ protected String normalize(String feature) {
+ if (!feature.contains("/")) {
+ feature += "/0.0.0";
+ }
+ int idx = feature.indexOf("/");
+ String name = feature.substring(0, idx);
+ String version = feature.substring(idx + 1);
+ return name + "/" + VersionTable.getVersion(version).toString();
+ }
+
+ /**
+ * Actual deployment needs to be done in a separate thread.
+ * The reason is that if the console is refreshed, the current thread which is running
+ * the command may be interrupted while waiting for the refresh to be done, leading
+ * to bundles not being started after the refresh.
+ */
+ public void doInstallFeaturesInThread(final Set<String> features,
+ final Set<String> installed,
+ final Set<Long> managed,
+ final EnumSet<Option> options) throws Exception {
+ ExecutorService executor = Executors.newCachedThreadPool();
+ try {
+ executor.submit(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ doInstallFeatures(features, installed, managed, options);
+ return null;
+ }
+ }).get();
+ } catch (ExecutionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw ((RuntimeException) t);
+ } else if (t instanceof Error) {
+ throw ((Error) t);
+ } else if (t instanceof Exception) {
+ throw (Exception) t;
+ } else {
+ throw e;
+ }
+ } finally {
+ executor.shutdown();
+ }
+ }
+
+ public void doInstallFeatures(Set<String> features, // all request features
+ Set<String> installed, // installed features
+ Set<Long> managed, // currently managed bundles
+ EnumSet<Option> options // installation options
+ ) throws Exception {
+
+ boolean noRefreshUnmanaged = options.contains(Option.NoAutoRefreshUnmanagedBundles);
+ boolean noRefreshManaged = options.contains(Option.NoAutoRefreshManagedBundles);
+ boolean noRefresh = options.contains(Option.NoAutoRefreshBundles);
+ boolean noStart = options.contains(Option.NoAutoStartBundles);
+ boolean verbose = options.contains(Option.Verbose);
+ boolean simulate = options.contains(Option.Simulate);
+
+ // Get a list of resolved and unmanaged bundles to use as capabilities during resolution
+ List<Resource> systemBundles = new ArrayList<Resource>();
+ Bundle[] bundles = systemBundleContext.getBundles();
+ for (Bundle bundle : bundles) {
+ if (bundle.getState() >= Bundle.RESOLVED && !managed.contains(bundle.getBundleId())) {
+ Resource res = bundle.adapt(BundleRevision.class);
+ systemBundles.add(res);
+ }
+ }
+ // Resolve
+ // TODO: requirements
+ // TODO: bundles
+ // TODO: regions: on isolated regions, we may need different resolution for each region
+ Set<String> overrides = Overrides.loadOverrides(this.overrides);
+ Repository[] repositories = listRepositories();
+ DeploymentBuilder builder = createDeploymentBuilder(repositories);
+ builder.setFeatureRange(featureResolutionRange);
+ builder.download(features,
+ Collections.<String>emptySet(),
+ Collections.<String>emptySet(),
+ overrides,
+ Collections.<String>emptySet());
+ Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles);
+ Collection<Resource> allResources = resolution.keySet();
+ Map<String, StreamProvider> providers = builder.getProviders();
+
+ // Install conditionals
+ List<String> installedFeatureIds = getFeatureIds(allResources);
+ List<String> newFeatures = new ArrayList<String>(installedFeatureIds);
+ newFeatures.removeAll(installed);
+ List<String> delFeatures = new ArrayList<String>(installed);
+ delFeatures.removeAll(installedFeatureIds);
+
+ //
+ // Compute list of installable resources (those with uris)
+ //
+ List<Resource> resources = getBundles(allResources);
+
+ // Compute information for each bundle
+ Map<String, BundleInfo> bundleInfos = new HashMap<String, BundleInfo>();
+ for (Feature feature : getFeatures(repositories, getFeatureIds(allResources))) {
+ for (BundleInfo bi : feature.getBundles()) {
+ BundleInfo oldBi = bundleInfos.get(bi.getLocation());
+ if (oldBi != null) {
+ bi = mergeBundleInfo(bi, oldBi);
+ }
+ bundleInfos.put(bi.getLocation(), bi);
+ }
+ }
+
+ // TODO: handle bundleInfo.isStart()
+
+ // Get all resources that will be used to satisfy the old features set
+ Set<Resource> resourceLinkedToOldFeatures = new HashSet<Resource>();
+ if (noStart) {
+ for (Resource resource : resolution.keySet()) {
+ String name = FeatureNamespace.getName(resource);
+ if (name != null) {
+ Version version = FeatureNamespace.getVersion(resource);
+ String id = version != null ? name + "/" + version : name;
+ if (installed.contains(id)) {
+ addTransitive(resource, resourceLinkedToOldFeatures, resolution);
+ }
+ }
+ }
+ }
+
+ //
+ // Compute deployment
+ //
+ Map<String, Long> bundleChecksums = new HashMap<String, Long>();
+ synchronized (lock) {
+ bundleChecksums.putAll(state.bundleChecksums);
+ }
+ Deployment deployment = computeDeployment(managed, bundles, providers, resources, bundleChecksums);
+
+ if (deployment.toDelete.isEmpty() &&
+ deployment.toUpdate.isEmpty() &&
+ deployment.toInstall.isEmpty()) {
+ print("No deployment change.", verbose);
+ return;
+ }
+ //
+ // Log deployment
+ //
+ logDeployment(deployment, verbose);
+
+ //
+ // Compute the set of bundles to refresh
+ //
+ Set<Bundle> toRefresh = new HashSet<Bundle>();
+ toRefresh.addAll(deployment.toDelete);
+ toRefresh.addAll(deployment.toUpdate.keySet());
+
+ if (!noRefreshManaged) {
+ int size;
+ do {
+ size = toRefresh.size();
+ for (Bundle bundle : bundles) {
+ // Continue if we already know about this bundle
+ if (toRefresh.contains(bundle)) {
+ continue;
+ }
+ // Ignore non resolved bundle
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ if (wiring == null) {
+ continue;
+ }
+ // Get through the old resolution and flag this bundle
+ // if it was wired to a bundle to be refreshed
+ for (BundleWire wire : wiring.getRequiredWires(null)) {
+ if (toRefresh.contains(wire.getProvider().getBundle())) {
+ toRefresh.add(bundle);
+ break;
+ }
+ }
+ // Get through the new resolution and flag this bundle
+ // if it's wired to any new bundle
+ List<Wire> newWires = resolution.get(wiring.getRevision());
+ if (newWires != null) {
+ for (Wire wire : newWires) {
+ Bundle b = null;
+ if (wire.getProvider() instanceof BundleRevision) {
+ b = ((BundleRevision) wire.getProvider()).getBundle();
+ } else {
+ b = deployment.resToBnd.get(wire.getProvider());
+ }
+ if (b == null || toRefresh.contains(b)) {
+ toRefresh.add(bundle);
+ break;
+ }
+ }
+ }
+ }
+ } while (toRefresh.size() > size);
+ }
+ if (noRefreshUnmanaged) {
+ Set<Bundle> newSet = new HashSet<Bundle>();
+ for (Bundle bundle : toRefresh) {
+ if (managed.contains(bundle.getBundleId())) {
+ newSet.add(bundle);
+ }
+ }
+ toRefresh = newSet;
+ }
+
+
+ if (simulate) {
+ if (!toRefresh.isEmpty()) {
+ print(" Bundles to refresh:", verbose);
+ for (Bundle bundle : toRefresh) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ }
+ }
+ return;
+ }
+
+ Set<Bundle> toStart = new HashSet<Bundle>();
+
+ //
+ // Execute deployment
+ //
+
+ // TODO: handle update on the features service itself
+ if (deployment.toUpdate.containsKey(bundle) ||
+ deployment.toDelete.contains(bundle)) {
+
+ LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
+ deployment.toUpdate.remove(bundle);
+ deployment.toDelete.remove(bundle);
+
+ }
+
+ //
+ // Perform bundle operations
+ //
+
+ // Stop bundles by chunks
+ Set<Bundle> toStop = new HashSet<Bundle>();
+ toStop.addAll(deployment.toUpdate.keySet());
+ toStop.addAll(deployment.toDelete);
+ removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
+ if (!toStop.isEmpty()) {
+ print("Stopping bundles:", verbose);
+ while (!toStop.isEmpty()) {
+ List<Bundle> bs = getBundlesToStop(toStop);
+ for (Bundle bundle : bs) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ bundle.stop(Bundle.STOP_TRANSIENT);
+ toStop.remove(bundle);
+ }
+ }
+ }
+ if (!deployment.toDelete.isEmpty()) {
+ print("Uninstalling bundles:", verbose);
+ for (Bundle bundle : deployment.toDelete) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ bundle.uninstall();
+ managed.remove(bundle.getBundleId());
+ }
+ }
+ if (!deployment.toUpdate.isEmpty()) {
+ print("Updating bundles:", verbose);
+ for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
+ Bundle bundle = entry.getKey();
+ Resource resource = entry.getValue();
+ String uri = UriNamespace.getUri(resource);
+ print(" " + uri, verbose);
+ InputStream is = getBundleInputStream(resource, providers);
+ bundle.update(is);
+ toStart.add(bundle);
+ BundleInfo bi = bundleInfos.get(uri);
+ if (bi != null && bi.getStartLevel() > 0) {
+ bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
+ }
+ // TODO: handle region
+ }
+ }
+ if (!deployment.toInstall.isEmpty()) {
+ print("Installing bundles:", verbose);
+ for (Resource resource : deployment.toInstall) {
+ String uri = UriNamespace.getUri(resource);
+ print(" " + uri, verbose);
+ InputStream is = getBundleInputStream(resource, providers);
+ Bundle bundle = systemBundleContext.installBundle(uri, is);
+ managed.add(bundle.getBundleId());
+ if (!noStart || resourceLinkedToOldFeatures.contains(resource)) {
+ toStart.add(bundle);
+ }
+ deployment.resToBnd.put(resource, bundle);
+ // save a checksum of installed snapshot bundle
+ if (UPDATE_SNAPSHOTS_CRC.equals(updateSnaphots)
+ && isUpdateable(resource) && !deployment.newCheckums.containsKey(bundle.getLocation())) {
+ deployment.newCheckums.put(bundle.getLocation(), ChecksumUtils.checksum(getBundleInputStream(resource, providers)));
+ }
+ BundleInfo bi = bundleInfos.get(uri);
+ if (bi != null && bi.getStartLevel() > 0) {
+ bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
+ }
+ // TODO: handle region
+ }
+ }
+
+ //
+ // Update and save state
+ //
+ synchronized (lock) {
+ state.bundleChecksums.putAll(deployment.newCheckums);
+ state.features.clear();
+ state.features.addAll(features);
+ state.installedFeatures.clear();
+ state.installedFeatures.addAll(installedFeatureIds);
+ state.managedBundles.clear();
+ state.managedBundles.addAll(managed);
+ saveState();
+ }
+
+ //
+ // Install configurations
+ //
+ if (configInstaller != null && !newFeatures.isEmpty()) {
+ for (Repository repository : repositories) {
+ for (Feature feature : repository.getFeatures()) {
+ if (newFeatures.contains(feature.getId())) {
+ configInstaller.installFeatureConfigs(feature);
+ }
+ }
+ }
+ }
+
+ // TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
+ new CopyOnWriteArrayIdentityList().iterator();
+ RequirementSort.sort(Collections.<Resource>emptyList());
+
+ if (!noRefresh) {
+ toStop = new HashSet<Bundle>();
+ toStop.addAll(toRefresh);
+ removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
+ if (!toStop.isEmpty()) {
+ print("Stopping bundles:", verbose);
+ while (!toStop.isEmpty()) {
+ List<Bundle> bs = getBundlesToStop(toStop);
+ for (Bundle bundle : bs) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ bundle.stop(Bundle.STOP_TRANSIENT);
+ toStop.remove(bundle);
+ toStart.add(bundle);
+ }
+ }
+ }
+
+ if (!toRefresh.isEmpty()) {
+ print("Refreshing bundles:", verbose);
+ for (Bundle bundle : toRefresh) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ }
+ if (!toRefresh.isEmpty()) {
+ refreshPackages(toRefresh);
+ }
+ }
+ }
+
+ // Compute bundles to start
+ removeFragmentsAndBundlesInState(toStart, Bundle.UNINSTALLED | Bundle.ACTIVE | Bundle.STARTING);
+ if (!toStart.isEmpty()) {
+ // Compute correct start order
+ List<Exception> exceptions = new ArrayList<Exception>();
+ print("Starting bundles:", verbose);
+ while (!toStart.isEmpty()) {
+ List<Bundle> bs = getBundlesToStart(toStart);
+ for (Bundle bundle : bs) {
+ LOGGER.info(" " + bundle.getSymbolicName() + " / " + bundle.getVersion());
+ try {
+ bundle.start();
+ } catch (BundleException e) {
+ exceptions.add(e);
+ }
+ toStart.remove(bundle);
+ }
+ }
+ if (!exceptions.isEmpty()) {
+ throw new MultiException("Error restarting bundles", exceptions);
+ }
+ }
+
+ // Call listeners
+ for (Feature feature : getFeatures(repositories, delFeatures)) {
+ callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureUninstalled, false));
+ }
+ for (Feature feature : getFeatures(repositories, newFeatures)) {
+ callListeners(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, false));
+ }
+
+ print("Done.", verbose);
+ }
+
+ private void addTransitive(Resource resource, Set<Resource> resources, Map<Resource, List<Wire>> resolution) {
+ if (resources.add(resource)) {
+ for (Wire wire : resolution.get(resource)) {
+ addTransitive(wire.getProvider(), resources, resolution);
+ }
+ }
+ }
+
+ protected BundleInfo mergeBundleInfo(BundleInfo bi, BundleInfo oldBi) {
+ // TODO: we need a proper merge strategy when a bundle
+ // TODO: comes from different features
+ return bi;
+ }
+
+ private void print(String message, boolean verbose) {
+ LOGGER.info(message);
+ if (verbose) {
+ System.out.println(message);
+ }
+ }
+
+ private void removeFragmentsAndBundlesInState(Collection<Bundle> bundles, int state) {
+ for (Bundle bundle : new ArrayList<Bundle>(bundles)) {
+ if ((bundle.getState() & state) != 0
+ || bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) {
+ bundles.remove(bundle);
+ }
+ }
+ }
+
+ protected void logDeployment(Deployment deployment, boolean verbose) {
+ print("Changes to perform:", verbose);
+ if (!deployment.toDelete.isEmpty()) {
+ print(" Bundles to uninstall:", verbose);
+ for (Bundle bundle : deployment.toDelete) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ }
+ }
+ if (!deployment.toUpdate.isEmpty()) {
+ print(" Bundles to update:", verbose);
+ for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
+ print(" " + entry.getKey().getSymbolicName() + " / " + entry.getKey().getVersion() + " with " + UriNamespace.getUri(entry.getValue()), verbose);
+ }
+ }
+ if (!deployment.toInstall.isEmpty()) {
+ print(" Bundles to install:", verbose);
+ for (Resource resource : deployment.toInstall) {
+ print(" " + UriNamespace.getUri(resource), verbose);
+ }
+ }
+ }
+
+ protected Deployment computeDeployment(
+ Set<Long> managed,
+ Bundle[] bundles,
+ Map<String, StreamProvider> providers,
+ List<Resource> resources,
+ Map<String, Long> bundleChecksums) throws IOException {
+ Deployment deployment = new Deployment();
+
+ // TODO: regions
+ List<Resource> toDeploy = new ArrayList<Resource>(resources);
+
+ // First pass: go through all installed bundles and mark them
+ // as either to ignore or delete
+ for (Bundle bundle : bundles) {
+ if (bundle.getSymbolicName() != null && bundle.getBundleId() != 0) {
+ Resource resource = null;
+ for (Resource res : toDeploy) {
+ if (bundle.getSymbolicName().equals(getSymbolicName(res))) {
+ if (bundle.getVersion().equals(getVersion(res))) {
+ resource = res;
+ break;
+ }
+ }
+ }
+ // We found a matching bundle
+ if (resource != null) {
+ // In case of snapshots, check if the snapshot is out of date
+ // and flag it as to update
+ if (managed.contains(bundle.getBundleId()) && isUpdateable(resource)) {
+ // Always update snapshots
+ if (UPDATE_SNAPSHOTS_ALWAYS.equalsIgnoreCase(updateSnaphots)) {
+ LOGGER.debug("Update snapshot for " + bundle.getLocation());
+ deployment.toUpdate.put(bundle, resource);
+ }
+ else if (UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
+ // if the checksum are different
+ InputStream is = null;
+ try {
+ is = getBundleInputStream(resource, providers);
+ long newCrc = ChecksumUtils.checksum(is);
+ long oldCrc = bundleChecksums.containsKey(bundle.getLocation()) ? bundleChecksums.get(bundle.getLocation()) : 0l;
+ if (newCrc != oldCrc) {
+ LOGGER.debug("New snapshot available for " + bundle.getLocation());
+ deployment.toUpdate.put(bundle, resource);
+ deployment.newCheckums.put(bundle.getLocation(), newCrc);
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
+ }
+ }
+ }
+ // We're done for this resource
+ toDeploy.remove(resource);
+ deployment.resToBnd.put(resource, bundle);
+ // There's no matching resource
+ // If the bundle is managed, we need to delete it
+ } else if (managed.contains(bundle.getBundleId())) {
+ deployment.toDelete.add(bundle);
+ }
+ }
+ }
+
+ // Second pass on remaining resources
+ for (Resource resource : toDeploy) {
+ TreeMap<Version, Bundle> matching = new TreeMap<Version, Bundle>();
+ VersionRange range = new VersionRange(Macro.transform(bundleUpdateRange, getVersion(resource).toString()));
+ for (Bundle bundle : deployment.toDelete) {
+ if (bundle.getSymbolicName().equals(getSymbolicName(resource)) && range.contains(bundle.getVersion())) {
+ matching.put(bundle.getVersion(), bundle);
+ }
+ }
+ if (!matching.isEmpty()) {
+ Bundle bundle = matching.lastEntry().getValue();
+ deployment.toUpdate.put(bundle, resource);
+ deployment.toDelete.remove(bundle);
+ deployment.resToBnd.put(resource, bundle);
+ } else {
+ deployment.toInstall.add(resource);
+ }
+ }
+ return deployment;
+ }
+
+ protected List<Resource> getBundles(Collection<Resource> allResources) {
+ Map<String, Resource> deploy = new TreeMap<String, Resource>();
+ for (Resource res : allResources) {
+ String uri = UriNamespace.getUri(res);
+ if (uri != null) {
+ deploy.put(uri, res);
+ }
+ }
+ return new ArrayList<Resource>(deploy.values());
+ }
+
+ protected List<Feature> getFeatures(Repository[] repositories, List<String> featureIds) throws Exception {
+ List<Feature> installedFeatures = new ArrayList<Feature>();
+ for (Repository repository : repositories) {
+ for (Feature feature : repository.getFeatures()) {
+ String id = feature.getName() + "/" + VersionTable.getVersion(feature.getVersion());
+ if (featureIds.contains(id)) {
+ installedFeatures.add(feature);
+ }
+ }
+ }
+ return installedFeatures;
+ }
+
+ protected List<String> getFeatureIds(Collection<Resource> allResources) {
+ List<String> installedFeatureIds = new ArrayList<String>();
+ for (Resource resource : allResources) {
+ String name = FeatureNamespace.getName(resource);
+ if (name != null) {
+ Version version = FeatureNamespace.getVersion(resource);
+ String id = version != null ? name + "/" + version : name;
+ installedFeatureIds.add(id);
+ }
+ }
+ return installedFeatureIds;
+ }
+
+ protected DeploymentBuilder createDeploymentBuilder(Repository[] repositories) {
+ return new DeploymentBuilder(new SimpleDownloader(), Arrays.asList(repositories));
+ }
+
+
+ protected boolean isUpdateable(Resource resource) {
+ return (getVersion(resource).getQualifier().endsWith(SNAPSHOT) ||
+ UriNamespace.getUri(resource).contains(SNAPSHOT) ||
+ !UriNamespace.getUri(resource).contains(MAVEN));
+ }
+
+ protected List<Bundle> getBundlesToStart(Collection<Bundle> bundles) {
+ // TODO: make this pluggable ?
+ // TODO: honor respectStartLvlDuringFeatureStartup
+
+ // We hit FELIX-2949 if we don't use the correct order as Felix resolver isn't greedy.
+ // In order to minimize that, we make sure we resolve the bundles in the order they
+ // are given back by the resolution, meaning that all root bundles (i.e. those that were
+ // not flagged as dependencies in features) are started before the others. This should
+ // make sure those important bundles are started first and minimize the problem.
+
+ // Restart the features service last, regardless of any other consideration
+ // so that we don't end up with the service trying to do stuff before we're done
+ boolean restart = bundles.remove(bundle);
+
+ List<BundleRevision> revs = new ArrayList<BundleRevision>();
+ for (Bundle bundle : bundles) {
+ revs.add(bundle.adapt(BundleRevision.class));
+ }
+ List<Bundle> sorted = new ArrayList<Bundle>();
+ for (BundleRevision rev : RequirementSort.sort(revs)) {
+ sorted.add(rev.getBundle());
+ }
+ if (restart) {
+ sorted.add(bundle);
+ }
+ return sorted;
+ }
+
+ protected List<Bundle> getBundlesToStop(Collection<Bundle> bundles) {
+ // TODO: make this pluggable ?
+ // TODO: honor respectStartLvlDuringFeatureUninstall
+
+ List<Bundle> bundlesToDestroy = new ArrayList<Bundle>();
+ for (Bundle bundle : bundles) {
+ ServiceReference[] references = bundle.getRegisteredServices();
+ int usage = 0;
+ if (references != null) {
+ for (ServiceReference reference : references) {
+ usage += getServiceUsage(reference, bundles);
+ }
+ }
+ LOGGER.debug("Usage for bundle {} is {}", bundle, usage);
+ if (usage == 0) {
+ bundlesToDestroy.add(bundle);
+ }
+ }
+ if (!bundlesToDestroy.isEmpty()) {
+ Collections.sort(bundlesToDestroy, new Comparator<Bundle>() {
+ public int compare(Bundle b1, Bundle b2) {
+ return (int) (b2.getLastModified() - b1.getLastModified());
+ }
+ });
+ LOGGER.debug("Selected bundles {} for destroy (no services in use)", bundlesToDestroy);
+ } else {
+ ServiceReference ref = null;
+ for (Bundle bundle : bundles) {
+ ServiceReference[] references = bundle.getRegisteredServices();
+ for (ServiceReference reference : references) {
+ if (getServiceUsage(reference, bundles) == 0) {
+ continue;
+ }
+ if (ref == null || reference.compareTo(ref) < 0) {
+ LOGGER.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
+ ref = reference;
+ }
+ }
+ }
+ if (ref != null) {
+ bundlesToDestroy.add(ref.getBundle());
+ }
+ LOGGER.debug("Selected bundle {} for destroy (lowest ranking service)", bundlesToDestroy);
+ }
+ return bundlesToDestroy;
+ }
+
+ private static int getServiceUsage(ServiceReference ref, Collection<Bundle> bundles) {
+ Bundle[] usingBundles = ref.getUsingBundles();
+ int nb = 0;
+ if (usingBundles != null) {
+ for (Bundle bundle : usingBundles) {
+ if (bundles.contains(bundle)) {
+ nb++;
+ }
+ }
+ }
+ return nb;
+ }
+
+ protected InputStream getBundleInputStream(Resource resource, Map<String, StreamProvider> providers) throws IOException {
+ String uri = UriNamespace.getUri(resource);
+ if (uri == null) {
+ throw new IllegalStateException("Resource has no uri");
+ }
+ StreamProvider provider = providers.get(uri);
+ if (provider == null) {
+ throw new IllegalStateException("Resource " + uri + " has no StreamProvider");
+ }
+ return provider.open();
+ }
+
+ protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ FrameworkWiring fw = systemBundleContext.getBundle().adapt(FrameworkWiring.class);
+ fw.refreshBundles(bundles, new FrameworkListener() {
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.ERROR) {
+ LOGGER.error("Framework error", event.getThrowable());
+ }
+ latch.countDown();
+ }
+ });
+ latch.await();
+ }
+
+
+ static class Deployment {
+ Map<String, Long> newCheckums = new HashMap<String, Long>();
+ Map<Resource, Bundle> resToBnd = new HashMap<Resource, Bundle>();
+ List<Resource> toInstall = new ArrayList<Resource>();
+ List<Bundle> toDelete = new ArrayList<Bundle>();
+ Map<Bundle, Resource> toUpdate = new HashMap<Bundle, Resource>();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
new file mode 100644
index 0000000..233a8a2
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.felix.resolver.Util.getSymbolicName;
+import static org.apache.felix.resolver.Util.getVersion;
+
+/**
+ * Helper class to deal with overriden bundles at feature installation time.
+ */
+public class Overrides {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Overrides.class);
+
+ protected static final String OVERRIDE_RANGE = "range";
+
+ /**
+ * Compute a list of bundles to install, taking into account overrides.
+ *
+ * The file containing the overrides will be loaded from the given url.
+ * Blank lines and lines starting with a '#' will be ignored, all other lines
+ * are considered as urls to override bundles.
+ *
+ * The list of resources to resolve will be scanned and for each bundle,
+ * if a bundle override matches that resource, it will be used instead.
+ *
+ * Matching is done on bundle symbolic name (they have to be the same)
+ * and version (the bundle override version needs to be greater than the
+ * resource to be resolved, and less than the next minor version. A range
+ * directive can be added to the override url in which case, the matching
+ * will succeed if the resource to be resolved is within the given range.
+ *
+ * @param resources the list of resources to resolve
+ * @param overrides list of bundle overrides
+ */
+ public static void override(Map<String, Resource> resources, Collection<String> overrides) {
+ // Do override replacement
+ for (Clause override : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
+ String url = override.getName();
+ String vr = override.getAttribute(OVERRIDE_RANGE);
+ Resource over = resources.get(url);
+ if (over == null) {
+ // Ignore invalid overrides
+ continue;
+ }
+ for (String uri : new ArrayList<String>(resources.keySet())) {
+ Resource res = resources.get(uri);
+ if (getSymbolicName(res).equals(getSymbolicName(over))) {
+ VersionRange range;
+ if (vr == null) {
+ // default to micro version compatibility
+ Version v1 = getVersion(res);
+ Version v2 = new Version(v1.getMajor(), v1.getMinor() + 1, 0);
+ range = new VersionRange(false, v1, v2, true);
+ } else {
+ range = VersionRange.parseVersionRange(vr);
+ }
+ // The resource matches, so replace it with the overridden resource
+ // if the override is actually a newer version than what we currently have
+ if (range.contains(getVersion(over)) && getVersion(res).compareTo(getVersion(over)) < 0) {
+ resources.put(uri, over);
+ }
+ }
+ }
+ }
+ }
+
+ public static Set<String> loadOverrides(String overridesUrl) {
+ Set<String> overrides = new HashSet<String>();
+ try {
+ if (overridesUrl != null) {
+ InputStream is = new URL(overridesUrl).openStream();
+ try {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (!line.isEmpty() && !line.startsWith("#")) {
+ overrides.add(line);
+ }
+ }
+ } finally {
+ is.close();
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.debug("Unable to load overrides bundles list", e);
+ }
+ return overrides;
+ }
+
+ public static String extractUrl(String override) {
+ Clause[] cs = Parser.parseClauses(new String[] { override });
+ if (cs.length != 1) {
+ throw new IllegalStateException("Override contains more than one clause: " + override);
+ }
+ return cs[0].getName();
+ }
+
+}
[30/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
new file mode 100644
index 0000000..e5d9d94
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import org.apache.karaf.features.ConfigFileInfo;
+
+
+/**
+ *
+ * Additional configuration files which should be created during feature installation.
+ *
+ *
+ * <p>Java class for configFile complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="configFile">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ * <attribute name="finalname" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="override" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "configFile", propOrder = {
+ "value"
+})
+public class ConfigFile implements ConfigFileInfo {
+
+ @XmlValue
+ protected String value;
+ @XmlAttribute(required = true)
+ protected String finalname;
+ @XmlAttribute
+ protected Boolean override;
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getLocation() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setLocation(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value of the finalname property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getFinalname() {
+ return finalname;
+ }
+
+ /**
+ * Sets the value of the finalname property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setFinalname(String value) {
+ this.finalname = value;
+ }
+
+ /**
+ * Gets the value of the override property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public boolean isOverride() {
+ return override == null? false: override;
+ }
+
+ /**
+ * Sets the value of the override property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setOverride(Boolean value) {
+ this.override = value;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
new file mode 100644
index 0000000..756e4c1
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.model;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.xml.bind.annotation.XmlTransient;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+
+@XmlTransient
+public class Content {
+
+ protected List<Config> config;
+ protected List<ConfigFile> configfile;
+ protected List<Dependency> feature;
+ protected List<Bundle> bundle;
+
+ /**
+ * Gets the value of the config property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the config property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getConfig().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Config }
+ */
+ public List<Config> getConfig() {
+ if (config == null) {
+ config = new ArrayList<Config>();
+ }
+ return this.config;
+ }
+
+ /**
+ * Gets the value of the configfile property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the configfile property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getConfigfile().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link ConfigFile }
+ */
+ public List<ConfigFile> getConfigfile() {
+ if (configfile == null) {
+ configfile = new ArrayList<ConfigFile>();
+ }
+ return this.configfile;
+ }
+
+ /**
+ * Gets the value of the feature property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the feature property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getFeature().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Dependency }
+ */
+ public List<Dependency> getFeature() {
+ if (feature == null) {
+ feature = new ArrayList<Dependency>();
+ }
+ return this.feature;
+ }
+
+ /**
+ * Gets the value of the bundle property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the bundle property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getBundle().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Bundle }
+ */
+ public List<Bundle> getBundle() {
+ if (bundle == null) {
+ bundle = new ArrayList<Bundle>();
+ }
+ return this.bundle;
+ }
+
+ public List<org.apache.karaf.features.Dependency> getDependencies() {
+ return Collections.<org.apache.karaf.features.Dependency>unmodifiableList(getFeature());
+ }
+
+ public List<BundleInfo> getBundles() {
+ return Collections.<BundleInfo>unmodifiableList(getBundle());
+ }
+
+ public Map<String, Map<String, String>> getConfigurations() {
+ Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
+ for (Config config : getConfig()) {
+ String name = config.getName();
+ StringReader propStream = new StringReader(config.getValue());
+ Properties props = new Properties();
+ try {
+ props.load(propStream);
+ } catch (IOException e) {
+ //ignore??
+ }
+ interpolation(props);
+ Map<String, String> propMap = new HashMap<String, String>();
+ for (Map.Entry<Object, Object> entry : props.entrySet()) {
+ propMap.put((String) entry.getKey(), (String) entry.getValue());
+ }
+ result.put(name, propMap);
+ }
+ return result;
+ }
+
+ public List<ConfigFileInfo> getConfigurationFiles() {
+ return Collections.<ConfigFileInfo>unmodifiableList(getConfigfile());
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected void interpolation(Properties properties) {
+ for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
+ String key = (String) e.nextElement();
+ String val = properties.getProperty(key);
+ Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
+ while (matcher.find()) {
+ String rep = System.getProperty(matcher.group(1));
+ if (rep != null) {
+ val = val.replace(matcher.group(0), rep);
+ matcher.reset(val);
+ }
+ }
+ properties.put(key, val);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
new file mode 100644
index 0000000..9c92a93
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ *
+ * Dependency of feature.
+ *
+ *
+ * <p>Java class for dependency complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="dependency">
+ * <simpleContent>
+ * <extension base="<http://karaf.apache.org/xmlns/features/v1.0.0>featureName">
+ * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "dependency", propOrder = {
+ "value"
+})
+public class Dependency implements org.apache.karaf.features.Dependency {
+
+ @XmlValue
+ protected String value;
+ @XmlAttribute
+ protected String version;
+
+ /**
+ *
+ * Feature name should be non empty string.
+ *
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVersion() {
+ if (version == null) {
+ return "0.0.0";
+ } else {
+ return version;
+ }
+ }
+
+ /**
+ * Sets the value of the version property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVersion(String value) {
+ this.version = value;
+ }
+
+ public String toString() {
+ String ret = getName() + Feature.SPLIT_FOR_NAME_AND_VERSION + getVersion();
+ return ret;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
new file mode 100644
index 0000000..46580da
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
@@ -0,0 +1,374 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
+ * Definition of the Feature.
+ *
+ *
+ * <p>Java class for feature complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="feature">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="details" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ * <element name="config" type="{http://karaf.apache.org/xmlns/features/v1.0.0}config" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="configfile" type="{http://karaf.apache.org/xmlns/features/v1.0.0}configFile" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}dependency" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="bundle" type="{http://karaf.apache.org/xmlns/features/v1.0.0}bundle" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="conditional" type="{http://karaf.apache.org/xmlns/features/v1.0.0}conditional" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="capability" type="{http://karaf.apache.org/xmlns/features/v1.0.0}capability" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="requirement" type="{http://karaf.apache.org/xmlns/features/v1.0.0}requirement" maxOccurs="unbounded" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="name" use="required" type="{http://karaf.apache.org/xmlns/features/v1.0.0}featureName" />
+ * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
+ * <attribute name="description" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="resolver" type="{http://karaf.apache.org/xmlns/features/v1.0.0}resolver" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "feature", propOrder = {
+ "details",
+ "config",
+ "configfile",
+ "feature",
+ "bundle",
+ "conditional",
+ "capability",
+ "requirement"
+})
+public class Feature extends Content implements org.apache.karaf.features.Feature {
+ public static String SPLIT_FOR_NAME_AND_VERSION = "/";
+ public static String DEFAULT_VERSION = "0.0.0";
+
+
+ protected String details;
+ @XmlAttribute(required = true)
+ protected String name;
+ @XmlAttribute
+ protected String version;
+ @XmlAttribute
+ protected String description;
+ @XmlAttribute
+ protected String resolver;
+ @XmlAttribute
+ protected String install;
+ @XmlAttribute(name = "start-level")
+ protected Integer startLevel;
+ @XmlAttribute
+ protected String region;
+ protected List<Conditional> conditional;
+ protected List<Capability> capability;
+ protected List<Requirement> requirement;
+
+ public Feature() {
+ }
+
+ public Feature(String name) {
+ this.name = name;
+ }
+
+ public Feature(String name, String version) {
+ this.name = name;
+ this.version = version;
+ }
+
+
+ public static org.apache.karaf.features.Feature valueOf(String str) {
+ if (str.contains(SPLIT_FOR_NAME_AND_VERSION)) {
+ String strName = str.substring(0, str.indexOf(SPLIT_FOR_NAME_AND_VERSION));
+ String strVersion = str.substring(str.indexOf(SPLIT_FOR_NAME_AND_VERSION)
+ + SPLIT_FOR_NAME_AND_VERSION.length(), str.length());
+ return new Feature(strName, strVersion);
+ } else {
+ return new Feature(str);
+ }
+
+
+ }
+
+
+ public String getId() {
+ return getName() + SPLIT_FOR_NAME_AND_VERSION + getVersion();
+ }
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+ /**
+ * Gets the value of the version property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getVersion() {
+ if (version == null) {
+ return DEFAULT_VERSION;
+ } else {
+ return version;
+ }
+ }
+
+ /**
+ * Sets the value of the version property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setVersion(String value) {
+ this.version = value;
+ }
+
+ /**
+ * Since version has a default value ("0.0.0"), returns
+ * whether or not the version has been set.
+ */
+ public boolean hasVersion() {
+ return this.version != null;
+ }
+
+ /**
+ * Gets the value of the description property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Sets the value of the description property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setDescription(String value) {
+ this.description = value;
+ }
+
+ public String getDetails() {
+ return details;
+ }
+
+ public void setDetails(String details) {
+ this.details = details;
+ }
+
+ /**
+ * Gets the value of the resolver property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getResolver() {
+ return resolver;
+ }
+
+ public String getInstall() {
+ return install;
+ }
+
+ public void setInstall(String install) {
+ this.install = install;
+ }
+
+ /**
+ * Sets the value of the resolver property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setResolver(String value) {
+ this.resolver = value;
+ }
+
+ /**
+ * Gets the value of the startLevel property.
+ *
+ * @return
+ * possible object is
+ * {@link Integer }
+ *
+ */
+ public int getStartLevel() {
+ return startLevel == null? 0: startLevel;
+ }
+
+ /**
+ * Sets the value of the startLevel property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Integer }
+ *
+ */
+ public void setStartLevel(Integer value) {
+ this.startLevel = value;
+ }
+
+
+ public String getRegion() {
+ return region;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ /**
+ * Gets the value of the conditional property.
+ * <p/>
+ * <p/>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the feature property.
+ * <p/>
+ * <p/>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getConditionals().add(newItem);
+ * </pre>
+ * <p/>
+ * <p/>
+ * <p/>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Conditional }
+ */
+ public List<Conditional> getConditional() {
+ if (conditional == null) {
+ conditional = new ArrayList<Conditional>();
+ }
+ return this.conditional;
+ }
+
+ public List<Capability> getCapabilities() {
+ if (capability == null) {
+ capability = new ArrayList<Capability>();
+ }
+ return this.capability;
+ }
+
+ public List<Requirement> getRequirements() {
+ if (requirement == null) {
+ requirement = new ArrayList<Requirement>();
+ }
+ return this.requirement;
+ }
+
+ public String toString() {
+ return getId();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Feature feature = (Feature) o;
+
+ if (name != null ? !name.equals(feature.name) : feature.name != null) return false;
+ if (version != null ? !version.equals(feature.version) : feature.version != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ return result;
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected void interpolation(Properties properties) {
+ for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
+ String key = (String) e.nextElement();
+ String val = properties.getProperty(key);
+ Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
+ while (matcher.find()) {
+ String rep = System.getProperty(matcher.group(1));
+ if (rep != null) {
+ val = val.replace(matcher.group(0), rep);
+ matcher.reset(val);
+ }
+ }
+ properties.put(key, val);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
new file mode 100644
index 0000000..e116f31
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
+ * Root element of Feature definition. It contains optional attribute which allow
+ * name of repository. This name will be used in shell to display source repository
+ * of given feature.
+ *
+ *
+ * <p>Java class for featuresRoot complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="features">
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element name="repository" type="{http://www.w3.org/2001/XMLSchema}anyURI" maxOccurs="unbounded" minOccurs="0"/>
+ * <element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}feature" maxOccurs="unbounded" minOccurs="0"/>
+ * </sequence>
+ * <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlRootElement(name = "features")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "features", propOrder = {
+ "repository",
+ "feature"
+})
+public class Features {
+
+ @XmlSchemaType(name = "anyURI")
+ protected List<String> repository;
+ protected List<Feature> feature;
+ @XmlAttribute
+ protected String name;
+
+ /**
+ * Gets the value of the repository property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the repository property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getRepository().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link String }
+ *
+ *
+ */
+ public List<String> getRepository() {
+ if (repository == null) {
+ repository = new ArrayList<String>();
+ }
+ return this.repository;
+ }
+
+ /**
+ * Gets the value of the feature property.
+ *
+ * <p>
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a <CODE>set</CODE> method for the feature property.
+ *
+ * <p>
+ * For example, to add a new item, do as follows:
+ * <pre>
+ * getFeature().add(newItem);
+ * </pre>
+ *
+ *
+ * <p>
+ * Objects of the following type(s) are allowed in the list
+ * {@link Feature }
+ *
+ *
+ */
+ public List<Feature> getFeature() {
+ if (feature == null) {
+ feature = new ArrayList<Feature>();
+ }
+ return this.feature;
+ }
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
new file mode 100644
index 0000000..2036452
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.karaf.features.internal.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URL;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.apache.karaf.features.FeaturesNamespaces;
+import org.apache.karaf.util.XmlUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+public class JaxbUtil {
+
+ private static final JAXBContext FEATURES_CONTEXT;
+ static {
+ try {
+ FEATURES_CONTEXT = JAXBContext.newInstance(Features.class);
+ } catch (JAXBException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void marshal(Features features, OutputStream out) throws JAXBException {
+ Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
+
+ marshaller.setProperty("jaxb.formatted.output", true);
+
+ marshaller.marshal(features, out);
+ }
+
+ public static void marshal(Features features, Writer out) throws JAXBException {
+ Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
+
+ marshaller.setProperty("jaxb.formatted.output", true);
+
+ marshaller.marshal(features, out);
+ }
+
+
+ /**
+ * Read in a Features from the input stream.
+ *
+ * @param uri uri to read
+ * @param validate whether to validate the input.
+ * @return a Features read from the input stream
+ */
+ public static Features unmarshal(String uri, boolean validate) {
+ if (validate) {
+ return unmarshalValidate(uri, null);
+ } else {
+ return unmarshalNoValidate(uri, null);
+ }
+ }
+
+ public static Features unmarshal(String uri, InputStream stream, boolean validate) {
+ if (validate) {
+ return unmarshalValidate(uri, stream);
+ } else {
+ return unmarshalNoValidate(uri, stream);
+ }
+ }
+
+ private static Features unmarshalValidate(String uri, InputStream stream) {
+ try {
+ Document doc;
+ if (stream != null) {
+ doc = XmlUtils.parse(stream);
+ doc.setDocumentURI(uri);
+ } else {
+ doc = XmlUtils.parse(uri);
+ }
+
+ Schema schema = getSchema(doc.getDocumentElement().getNamespaceURI());
+ try {
+ schema.newValidator().validate(new DOMSource(doc));
+ } catch (SAXException e) {
+ throw new IllegalArgumentException("Unable to validate " + uri, e);
+ }
+
+ fixDom(doc, doc.getDocumentElement());
+ Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
+ return (Features) unmarshaller.unmarshal(new DOMSource(doc));
+
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load " + uri, e);
+ }
+ }
+
+ private static Map<String, Schema> schemas = new ConcurrentHashMap<String, Schema>();
+ private static Schema getSchema(String namespace) throws SAXException {
+ Schema schema = schemas.get(namespace);
+ if (schema == null) {
+ String schemaLocation;
+ if (FeaturesNamespaces.URI_1_0_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.0.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_1_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.1.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_2_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.2.0.xsd";
+ } else if (FeaturesNamespaces.URI_1_3_0.equals(namespace)) {
+ schemaLocation = "/org/apache/karaf/features/karaf-features-1.3.0.xsd";
+ } else {
+ throw new IllegalArgumentException("Unsupported namespace: " + namespace);
+ }
+
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ // root element has namespace - we can use schema validation
+ URL url = JaxbUtil.class.getResource(schemaLocation);
+ if (url == null) {
+ throw new IllegalStateException("Could not find resource: " + schemaLocation);
+ }
+ schema = factory.newSchema(new StreamSource(url.toExternalForm()));
+ schemas.put(namespace, schema);
+ }
+ return schema;
+ }
+
+
+ private static void fixDom(Document doc, Node node) {
+ if (node.getNamespaceURI() != null && !FeaturesNamespaces.URI_CURRENT.equals(node.getNamespaceURI())) {
+ doc.renameNode(node, FeaturesNamespaces.URI_CURRENT, node.getLocalName());
+ }
+ NodeList children = node.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ fixDom(doc, children.item(i));
+ }
+ }
+
+ private static Features unmarshalNoValidate(String uri, InputStream stream) {
+ try {
+ Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
+ XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(XmlUtils.xmlReader());
+ xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
+
+
+ InputSource is = new InputSource(uri);
+ if (stream != null) {
+ is.setByteStream(stream);
+ }
+ SAXSource source = new SAXSource(xmlFilter, new InputSource(uri));
+ return (Features) unmarshaller.unmarshal(source);
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load " + uri, e);
+ }
+ }
+
+ /**
+ * Provides an empty inputsource for the entity resolver.
+ * Converts all elements to the features namespace to make old feature files
+ * compatible to the new format
+ */
+ public static class NoSourceAndNamespaceFilter extends XMLFilterImpl {
+ private static final InputSource EMPTY_INPUT_SOURCE = new InputSource(new ByteArrayInputStream(new byte[0]));
+
+ public NoSourceAndNamespaceFilter(XMLReader xmlReader) {
+ super(xmlReader);
+ }
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+ return EMPTY_INPUT_SOURCE;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ super.startElement(FeaturesNamespaces.URI_CURRENT, localName, qName, atts);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(FeaturesNamespaces.URI_CURRENT, localName, qName);
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
new file mode 100644
index 0000000..96fbb0f
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the org.apache.karaf.features.wrapper package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _Features_QNAME = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.features.wrapper
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link ConfigFile }
+ *
+ */
+ public ConfigFile createConfigFile() {
+ return new ConfigFile();
+ }
+
+ /**
+ * Create an instance of {@link Dependency }
+ *
+ */
+ public Dependency createDependency() {
+ return new Dependency();
+ }
+
+ /**
+ * Create an instance of {@link Bundle }
+ *
+ */
+ public Bundle createBundle() {
+ return new Bundle();
+ }
+
+ /**
+ * Create an instance of {@link Features }
+ *
+ */
+ public Features createFeaturesRoot() {
+ return new Features();
+ }
+
+ /**
+ * Create an instance of {@link Config }
+ *
+ */
+ public Config createConfig() {
+ return new Config();
+ }
+
+ /**
+ * Create an instance of {@link Feature }
+ *
+ */
+ public Feature createFeature() {
+ return new Feature();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Features }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/features/v1.0.0", name = "features")
+ public JAXBElement<Features> createFeatures(Features value) {
+ return new JAXBElement<Features>(_Features_QNAME, Features.class, null, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
new file mode 100644
index 0000000..f7b5775
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ *
+ * Additional requirement for a feature.
+ *
+ *
+ * <p>Java class for bundle complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="capability">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "requirement", propOrder = {
+ "value"
+})
+public class Requirement implements org.apache.karaf.features.Requirement {
+
+ @XmlValue
+ protected String value;
+
+
+ public Requirement() {
+ }
+
+ public Requirement(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Requirement bundle = (Requirement) o;
+
+ if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = value != null ? value.hashCode() : 0;
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
new file mode 100644
index 0000000..c86a58c
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+@javax.xml.bind.annotation.XmlSchema(namespace = org.apache.karaf.features.FeaturesNamespaces.URI_CURRENT, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.karaf.features.internal.model;
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
new file mode 100644
index 0000000..be0da05
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.osgi;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.internal.service.EventAdminListener;
+import org.apache.karaf.features.internal.service.FeatureConfigInstaller;
+import org.apache.karaf.features.internal.service.FeatureFinder;
+import org.apache.karaf.features.internal.service.BootFeaturesInstaller;
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.service.StateStorage;
+import org.apache.karaf.features.internal.management.FeaturesServiceMBeanImpl;
+import org.apache.karaf.features.RegionsPersistence;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.url.URLStreamHandlerService;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class Activator extends BaseActivator {
+
+ public static final String FEATURES_REPOS_PID = "org.apache.karaf.features.repos";
+ public static final String FEATURES_SERVICE_CONFIG_FILE = "org.apache.karaf.features.cfg";
+
+ private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
+ private FeaturesServiceImpl featuresService;
+ private SingleServiceTracker<RegionsPersistence> regionsTracker;
+
+ public Activator() {
+ // Special case here, as we don't want the activator to wait for current job to finish,
+ // else it would forbid the features service to refresh itself
+ setSchedulerStopTimeout(0);
+ }
+
+ @Override
+ protected void doOpen() throws Exception {
+ trackService(URLStreamHandlerService.class, "(url.handler.protocol=mvn)");
+ trackService(ConfigurationAdmin.class);
+
+ Properties configuration = new Properties();
+ File configFile = new File(System.getProperty("karaf.etc"), FEATURES_SERVICE_CONFIG_FILE);
+ if (configFile.isFile() && configFile.canRead()) {
+ try {
+ configuration.load(new FileReader(configFile));
+ } catch (IOException e) {
+ logger.warn("Error reading configuration file " + configFile.toString(), e);
+ }
+ }
+ updated((Dictionary) configuration);
+ }
+
+ protected void doStart() throws Exception {
+ ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+ URLStreamHandlerService mvnUrlHandler = getTrackedService(URLStreamHandlerService.class);
+
+ if (configurationAdmin == null || mvnUrlHandler == null) {
+ return;
+ }
+
+ FeatureFinder featureFinder = new FeatureFinder();
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ props.put(Constants.SERVICE_PID, FEATURES_REPOS_PID);
+ register(ManagedService.class, featureFinder, props);
+
+ // TODO: region support
+// final BundleManager bundleManager = new BundleManager(bundleContext);
+// regionsTracker = new SingleServiceTracker<RegionsPersistence>(bundleContext, RegionsPersistence.class,
+// new SingleServiceTracker.SingleServiceListener() {
+// @Override
+// public void serviceFound() {
+// bundleManager.setRegionsPersistence(regionsTracker.getService());
+// }
+// @Override
+// public void serviceLost() {
+// serviceFound();
+// }
+// @Override
+// public void serviceReplaced() {
+// serviceFound();
+// }
+// });
+// regionsTracker.open();
+
+
+ FeatureConfigInstaller configInstaller = new FeatureConfigInstaller(configurationAdmin);
+ // TODO: honor respectStartLvlDuringFeatureStartup and respectStartLvlDuringFeatureUninstall
+// boolean respectStartLvlDuringFeatureStartup = getBoolean("respectStartLvlDuringFeatureStartup", true);
+// boolean respectStartLvlDuringFeatureUninstall = getBoolean("respectStartLvlDuringFeatureUninstall", true);
+ String overrides = getString("overrides", new File(System.getProperty("karaf.etc"), "overrides.properties").toURI().toString());
+ String featureResolutionRange = getString("featureResolutionRange", FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
+ String bundleUpdateRange = getString("bundleUpdateRange", FeaturesServiceImpl.DEFAULT_BUNDLE_UPDATE_RANGE);
+ String updateSnapshots = getString("updateSnapshots", FeaturesServiceImpl.DEFAULT_UPDATE_SNAPSHOTS);
+ StateStorage stateStorage = new StateStorage() {
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+ if (file.exists()) {
+ return new FileInputStream(file);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ protected OutputStream getOutputStream() throws IOException {
+ File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+ return new FileOutputStream(file);
+ }
+ };
+ EventAdminListener eventAdminListener;
+ try {
+ eventAdminListener = new EventAdminListener(bundleContext);
+ } catch (Throwable t) {
+ eventAdminListener = null;
+ }
+ featuresService = new FeaturesServiceImpl(
+ bundleContext.getBundle(),
+ bundleContext.getBundle(0).getBundleContext(),
+ stateStorage,
+ featureFinder,
+ eventAdminListener,
+ configInstaller,
+ overrides,
+ featureResolutionRange,
+ bundleUpdateRange,
+ updateSnapshots);
+ register(FeaturesService.class, featuresService);
+
+ featuresListenerTracker = new ServiceTracker<FeaturesListener, FeaturesListener>(
+ bundleContext, FeaturesListener.class, new ServiceTrackerCustomizer<FeaturesListener, FeaturesListener>() {
+ @Override
+ public FeaturesListener addingService(ServiceReference<FeaturesListener> reference) {
+ FeaturesListener service = bundleContext.getService(reference);
+ featuresService.registerListener(service);
+ return service;
+ }
+ @Override
+ public void modifiedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
+ }
+ @Override
+ public void removedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
+ featuresService.unregisterListener(service);
+ bundleContext.ungetService(reference);
+ }
+ }
+ );
+ featuresListenerTracker.open();
+
+ String featuresRepositories = getString("featuresRepositories", "");
+ String featuresBoot = getString("featuresBoot", "");
+ boolean featuresBootAsynchronous = getBoolean("featuresBootAsynchronous", false);
+ BootFeaturesInstaller bootFeaturesInstaller = new BootFeaturesInstaller(
+ bundleContext, featuresService,
+ featuresRepositories, featuresBoot, featuresBootAsynchronous);
+ bootFeaturesInstaller.start();
+
+ FeaturesServiceMBeanImpl featuresServiceMBean = new FeaturesServiceMBeanImpl();
+ featuresServiceMBean.setBundleContext(bundleContext);
+ featuresServiceMBean.setFeaturesService(featuresService);
+ registerMBean(featuresServiceMBean, "type=feature");
+ }
+
+ protected void doStop() {
+ if (regionsTracker != null) {
+ regionsTracker.close();
+ regionsTracker = null;
+ }
+ if (featuresListenerTracker != null) {
+ featuresListenerTracker.close();
+ featuresListenerTracker = null;
+ }
+ super.doStop();
+ if (featuresService != null) {
+ featuresService = null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
new file mode 100644
index 0000000..0d5e83d
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.service.repository.Repository;
+
+public class AggregateRepository implements Repository {
+
+ private final Collection<Repository> repositories;
+
+ public AggregateRepository(Collection<Repository> repositories) {
+ this.repositories = repositories;
+ }
+
+ @Override
+ public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+ Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+ for (Requirement requirement : requirements) {
+ List<Capability> caps = new ArrayList<Capability>();
+ for (Repository repository : repositories) {
+ Map<Requirement, Collection<Capability>> resMap =
+ repository.findProviders(Collections.singleton(requirement));
+ Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
+ if (res != null) {
+ caps.addAll(res);
+ }
+ }
+ result.put(requirement, caps);
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
new file mode 100644
index 0000000..c4c0d16
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.features.internal.resolver.CapabilitySet;
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.SimpleFilter;
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+/**
+ */
+public class BaseRepository implements Repository {
+
+ protected final List<Resource> resources;
+ protected final Map<String, CapabilitySet> capSets;
+
+ public BaseRepository() {
+ this.resources = new ArrayList<Resource>();
+ this.capSets = new HashMap<String, CapabilitySet>();
+ }
+
+ protected void addResource(Resource resource) {
+ for (Capability cap : resource.getCapabilities(null)) {
+ String ns = cap.getNamespace();
+ CapabilitySet set = capSets.get(ns);
+ if (set == null) {
+ set = new CapabilitySet(Collections.singletonList(ns));
+ capSets.put(ns, set);
+ }
+ set.addCapability(cap);
+ }
+ resources.add(resource);
+ }
+
+ public List<Resource> getResources() {
+ return resources;
+ }
+
+ @Override
+ public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+ Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+ for (Requirement requirement : requirements) {
+ CapabilitySet set = capSets.get(requirement.getNamespace());
+ if (set != null) {
+ SimpleFilter sf;
+ if (requirement instanceof RequirementImpl) {
+ sf = ((RequirementImpl) requirement).getFilter();
+ } else {
+ String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+ sf = (filter != null)
+ ? SimpleFilter.parse(filter)
+ : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+ }
+ result.put(requirement, set.match(sf, true));
+ } else {
+ result.put(requirement, Collections.<Capability>emptyList());
+ }
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
new file mode 100644
index 0000000..7916821
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.service.repository.Repository;
+
+public class CacheRepository implements Repository {
+
+ private final Repository repository;
+ private final Map<Requirement, Collection<Capability>> cache =
+ new ConcurrentHashMap<Requirement, Collection<Capability>>();
+
+ public CacheRepository(Repository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+ List<Requirement> missing = new ArrayList<Requirement>();
+ Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+ for (Requirement requirement : requirements) {
+ Collection<Capability> caps = cache.get(requirement);
+ if (caps == null) {
+ missing.add(requirement);
+ } else {
+ result.put(requirement, caps);
+ }
+ }
+ Map<Requirement, Collection<Capability>> newCache = repository.findProviders(missing);
+ for (Requirement requirement : newCache.keySet()) {
+ cache.put(requirement, newCache.get(requirement));
+ result.put(requirement, newCache.get(requirement));
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
new file mode 100644
index 0000000..1aecef1
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.karaf.features.internal.util.JsonReader;
+
+/**
+ */
+public class HttpMetadataProvider implements MetadataProvider {
+
+ public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
+ public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
+ public static final String GZIP = "gzip";
+
+ private final String url;
+ private long lastModified;
+ private Map<String, Map<String, String>> metadatas;
+
+ public HttpMetadataProvider(String url) {
+ this.url = url;
+ }
+
+ @Override
+ public long getLastModified() {
+ return lastModified;
+ }
+
+ @Override
+ public Map<String, Map<String, String>> getMetadatas() {
+ try {
+ HttpURLConnection.setFollowRedirects(false);
+ HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
+ if (lastModified > 0) {
+ con.setIfModifiedSince(lastModified);
+ }
+ con.setRequestProperty(HEADER_ACCEPT_ENCODING, GZIP);
+ if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
+ lastModified = con.getLastModified();
+ InputStream is = con.getInputStream();
+ if (GZIP.equals(con.getHeaderField(HEADER_CONTENT_ENCODING))) {
+ is = new GZIPInputStream(is);
+ }
+ metadatas = verify(JsonReader.read(is));
+ } else if (con.getResponseCode() != HttpURLConnection.HTTP_NOT_MODIFIED) {
+ throw new IOException("Unexpected http response: "
+ + con.getResponseCode() + " " + con.getResponseMessage());
+ }
+ return metadatas;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Map<String, Map<String, String>> verify(Object value) {
+ Map<?,?> obj = Map.class.cast(value);
+ for (Map.Entry<?,?> entry : obj.entrySet()) {
+ String.class.cast(entry.getKey());
+ Map<?,?> child = Map.class.cast(entry.getValue());
+ for (Map.Entry<?,?> ce : child.entrySet()) {
+ String.class.cast(ce.getKey());
+ String.class.cast(ce.getValue());
+ }
+ }
+ return (Map<String, Map<String, String>>) obj;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
new file mode 100644
index 0000000..9ac54a1
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.Map;
+
+/**
+ */
+public interface MetadataProvider {
+
+ long getLastModified();
+
+ Map<String, Map<String, String>> getMetadatas();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
new file mode 100644
index 0000000..2d4fbba
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.Map;
+
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.osgi.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class MetadataRepository extends BaseRepository {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MetadataRepository.class);
+
+ public MetadataRepository(MetadataProvider provider) {
+ Map<String, Map<String, String>> metadatas = provider.getMetadatas();
+ for (Map.Entry<String, Map<String, String>> metadata : metadatas.entrySet()) {
+ try {
+ Resource resource = ResourceBuilder.build(metadata.getKey(), metadata.getValue());
+ addResource(resource);
+ } catch (Exception e) {
+ LOGGER.info("Unable to build resource for " + metadata.getKey(), e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
new file mode 100644
index 0000000..f289c8d
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.repository;
+
+import java.util.Collection;
+
+import org.osgi.resource.Resource;
+
+/**
+ */
+public class StaticRepository extends BaseRepository {
+
+ public StaticRepository(Collection<Resource> resources) {
+ for (Resource resource : resources) {
+ addResource(resource);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
new file mode 100644
index 0000000..0653398
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.resolver;
+
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public abstract class BaseClause {
+
+ public abstract Resource getResource();
+
+ public abstract String getNamespace();
+
+ public abstract Map<String, String> getDirectives();
+
+ public abstract Map<String, Object> getAttributes();
+
+ @Override
+ public String toString() {
+ return toString(getResource(), getNamespace(), getAttributes(), getDirectives());
+ }
+
+ public static String toString(Resource res, String namespace, Map<String, Object> attrs, Map<String, String> dirs) {
+ StringBuilder sb = new StringBuilder();
+ if (res != null) {
+ sb.append("[").append(res).append("] ");
+ }
+ sb.append(namespace);
+ for (String key : attrs.keySet()) {
+ sb.append("; ");
+ append(sb, key, attrs.get(key), true);
+ }
+ for (String key : dirs.keySet()) {
+ sb.append("; ");
+ append(sb, key, dirs.get(key), false);
+ }
+ return sb.toString();
+ }
+
+ private static void append(StringBuilder sb, String key, Object val, boolean attribute) {
+ sb.append(key);
+ if (val instanceof Version) {
+ sb.append(":Version=");
+ sb.append(val);
+ } else if (val instanceof Long) {
+ sb.append(":Long=");
+ sb.append(val);
+ } else if (val instanceof Double) {
+ sb.append(":Double=");
+ sb.append(val);
+ } else if (val instanceof Iterable) {
+ Iterable it = (Iterable) val;
+ String scalar = null;
+ for (Object o : it) {
+ String ts;
+ if (o instanceof String) {
+ ts = "String";
+ } else if (o instanceof Long) {
+ ts = "Long";
+ } else if (o instanceof Double) {
+ ts = "Double";
+ } else if (o instanceof Version) {
+ ts = "Version";
+ } else {
+ throw new IllegalArgumentException("Unsupported scalar type: " + o);
+ }
+ if (scalar == null) {
+ scalar = ts;
+ } else if (!scalar.equals(ts)) {
+ throw new IllegalArgumentException("Unconsistent list type for attribute " + key);
+ }
+ }
+ sb.append(":List<").append(scalar).append(">=");
+ sb.append("\"");
+ boolean first = true;
+ for (Object o : it) {
+ if (first) {
+ first = false;
+ } else {
+ sb.append(",");
+ }
+ sb.append(o.toString().replace("\"", "\\\"").replace(",", "\\,"));
+ }
+ sb.append("\"");
+ } else {
+ sb.append(attribute ? "=" : ":=");
+ String s = val.toString();
+ if (s.matches("[0-9a-zA-Z_\\-.]*")) {
+ sb.append(s);
+ } else {
+ sb.append("\"").append(s.replace("\"", "\\\\")).append("\"");
+ }
+ }
+ }
+
+}
[23/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesService.java b/features/src/main/java/org/apache/karaf/features/FeaturesService.java
deleted file mode 100644
index ef3dbcf..0000000
--- a/features/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.net.URI;
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * The service managing features repositories.
- */
-public interface FeaturesService {
-
- enum Option {
- NoFailOnFeatureNotFound,
- NoAutoRefreshManagedBundles,
- NoAutoRefreshUnmanagedBundles,
- NoAutoRefreshBundles,
- NoAutoStartBundles,
- Simulate,
- Verbose
- }
-
- /**
- * Validate repository contents.
- *
- * @param uri Repository uri.
- * @throws Exception When validation fails.
- */
- void validateRepository(URI uri) throws Exception;
-
- void addRepository(URI uri) throws Exception;
-
- void addRepository(URI uri, boolean install) throws Exception;
-
- void removeRepository(URI uri) throws Exception;
-
- void removeRepository(URI uri, boolean uninstall) throws Exception;
-
- void restoreRepository(URI uri) throws Exception;
-
- Repository[] listRequiredRepositories() throws Exception;
-
- Repository[] listRepositories() throws Exception;
-
- Repository getRepository(String repoName) throws Exception;
-
- void installFeature(String name) throws Exception;
-
- void installFeature(String name, EnumSet<Option> options) throws Exception;
-
- void installFeature(String name, String version) throws Exception;
-
- void installFeature(String name, String version, EnumSet<Option> options) throws Exception;
-
- void installFeature(Feature f, EnumSet<Option> options) throws Exception;
-
- void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
-
- void uninstallFeature(String name, EnumSet<Option> options) throws Exception;
-
- void uninstallFeature(String name) throws Exception;
-
- void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception;
-
- void uninstallFeature(String name, String version) throws Exception;
-
- void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
-
- Feature[] listFeatures() throws Exception;
-
- Feature[] listRequiredFeatures() throws Exception;
-
- Feature[] listInstalledFeatures() throws Exception;
-
- boolean isRequired(Feature f);
-
- boolean isInstalled(Feature f);
-
- Feature getFeature(String name, String version) throws Exception;
-
- Feature getFeature(String name) throws Exception;
-
- void refreshRepository(URI uri) throws Exception;
-
- public URI getRepositoryUriFor(String name, String version);
-
- public String[] getRepositoryNames();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java b/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
deleted file mode 100644
index 96ca7da..0000000
--- a/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.karaf.features;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-
-public interface RegionsPersistence {
- void install(Bundle b, String regionName) throws BundleException;
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Repository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Repository.java b/features/src/main/java/org/apache/karaf/features/Repository.java
deleted file mode 100644
index 3ea12ec..0000000
--- a/features/src/main/java/org/apache/karaf/features/Repository.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.io.IOException;
-import java.net.URI;
-
-/**
- * A repository of features.
- */
-public interface Repository {
-
- String getName() throws IOException;
-
- URI getURI();
-
- URI[] getRepositories() throws Exception;
-
- Feature[] getFeatures() throws Exception;
-
- boolean isValid();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java b/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
deleted file mode 100644
index 68f287b..0000000
--- a/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.EventObject;
-
-public class RepositoryEvent extends EventObject {
-
- public static enum EventType {
- RepositoryAdded,
- RepositoryRemoved,
- }
-
- private final EventType type;
- private final Repository repository;
- private final boolean replay;
-
- public RepositoryEvent(Repository repository, EventType type, boolean replay) {
- super(repository);
- this.type = type;
- this.repository = repository;
- this.replay = replay;
- }
-
- public EventType getType() {
- return type;
- }
-
- public Repository getRepository() {
- return repository;
- }
-
- public boolean isReplay() {
- return replay;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Requirement.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Requirement.java b/features/src/main/java/org/apache/karaf/features/Requirement.java
deleted file mode 100644
index 4446335..0000000
--- a/features/src/main/java/org/apache/karaf/features/Requirement.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-public interface Requirement {
-
- String getValue();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Resolver.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Resolver.java b/features/src/main/java/org/apache/karaf/features/Resolver.java
deleted file mode 100644
index d2fa941..0000000
--- a/features/src/main/java/org/apache/karaf/features/Resolver.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.List;
-
-public interface Resolver {
-
- List<BundleInfo> resolve(Feature feature) throws Exception;
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java b/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
deleted file mode 100644
index 076650d..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-
-public abstract class FeaturesCommandSupport implements Action {
-
- @Reference
- private FeaturesService featuresService;
-
- @Override
- public Object execute() throws Exception {
- if (featuresService == null) {
- throw new IllegalStateException("FeaturesService not found");
- }
- doExecute(featuresService);
- return null;
- }
-
- protected abstract void doExecute(FeaturesService admin) throws Exception;
-
- public void setFeaturesService(FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
deleted file mode 100644
index 5ad855c..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AllFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
-@Service
-public class InfoFeatureCommand extends FeaturesCommandSupport {
-
- private static final String INDENT = " ";
- private static final String FEATURE_CONTENT = "Feature";
- private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
-
- @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
- @Completion(AllFeatureCompleter.class)
- private String name;
-
- @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
- private String version;
-
- @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false)
- private boolean config;
-
- @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false)
- private boolean dependency;
-
- @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
- private boolean bundle;
-
- @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
- private boolean conditional;
-
- @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
- private boolean tree;
-
- protected void doExecute(FeaturesService admin) throws Exception {
- Feature feature = null;
-
- if (version != null && version.length() > 0) {
- feature = admin.getFeature(name, version);
- } else {
- feature = admin.getFeature(name);
- }
-
- if (feature == null) {
- System.out.println("Feature not found");
- return;
- }
-
- // default behavior
- if (!config && !dependency && !bundle && !conditional) {
- config = true;
- dependency = true;
- bundle = true;
- conditional = true;
- }
-
- System.out.println("Feature " + feature.getName() + " " + feature.getVersion());
- if (feature.getDescription() != null) {
- System.out.println("Description:");
- System.out.println(INDENT + feature.getDescription());
- }
-
- if(feature.getDetails() != null) {
- System.out.println("Details:");
- printWithIndent(feature.getDetails());
- }
-
- if (config) {
- displayConfigInformation(feature, FEATURE_CONTENT);
- displayConfigFileInformation(feature, FEATURE_CONTENT);
- }
-
- if (dependency) {
- displayDependencyInformation(feature, FEATURE_CONTENT);
- }
-
- if (bundle) {
- displayBundleInformation(feature, FEATURE_CONTENT);
- }
-
- if(conditional) {
- displayConditionalInfo(feature);
- }
-
- if (tree) {
- if (config || dependency || bundle) {
- System.out.println("\nFeature tree");
- }
-
- int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
- if (unresolved > 0) {
- System.out.println("Tree contains " + unresolved + " unresolved dependencies");
- System.out.println(" * means that node declares dependency but the dependent feature is not available.");
- }
- }
- }
-
- private void printWithIndent(String details) {
- String[] lines = details.split("\r?\n");
- for (String line : lines) {
- System.out.println(INDENT + line);
- }
- }
-
- private void displayBundleInformation(Feature feature, String contentType) {
- List<BundleInfo> bundleInfos = feature.getBundles();
- if (bundleInfos.isEmpty()) {
- System.out.println(contentType + " has no bundles.");
- } else {
- System.out.println(contentType + " contains followed bundles:");
- for (BundleInfo featureBundle : bundleInfos) {
- int startLevel = featureBundle.getStartLevel();
- StringBuilder sb = new StringBuilder();
- sb.append(INDENT).append(featureBundle.getLocation());
- if(startLevel > 0) {
- sb.append(" start-level=").append(startLevel);
- }
- System.out.println(sb.toString());
- }
- }
- }
-
- private void displayDependencyInformation(Feature feature, String contentType) {
- List<Dependency> dependencies = feature.getDependencies();
- if (dependencies.isEmpty()) {
- System.out.println(contentType + " has no dependencies.");
- } else {
- System.out.println(contentType + " depends on:");
- for (Dependency featureDependency : dependencies) {
- System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
- }
- }
- }
-
- private void displayConfigInformation(Feature feature, String contentType) {
- Map<String, Map<String, String>> configurations = feature.getConfigurations();
- if (configurations.isEmpty()) {
- System.out.println(contentType + " has no configuration");
- } else {
- System.out.println(contentType + " configuration:");
- for (String name : configurations.keySet()) {
- System.out.println(INDENT + name);
- }
- }
- }
-
- private void displayConfigFileInformation(Feature feature, String contentType) {
- List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
- if (configurationFiles.isEmpty()) {
- System.out.println(contentType + " has no configuration files");
- } else {
- System.out.println(contentType + " configuration files: ");
- for (ConfigFileInfo configFileInfo : configurationFiles) {
- System.out.println(INDENT + configFileInfo.getFinalname());
- }
- }
- }
-
- /**
- * Called originally with featureName and featureVersion that have already been resolved successfully.
- *
- * @param admin
- * @param featureName
- * @param featureVersion
- * @param prefix
- * @return
- * @throws Exception
- */
- private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
- int unresolved = 0;
-
- Feature resolved = admin.getFeature(featureName, featureVersion);
- if (resolved != null) {
- System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
- } else {
- System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
- unresolved++;
- }
-
- if (resolved != null) {
- if (bundle) {
- List<String> bundleLocation = new LinkedList<String>();
- List<BundleInfo> bundles = resolved.getBundles();
- for (BundleInfo bundleInfo : bundles) {
- bundleLocation.add(bundleInfo.getLocation());
- }
-
- if (conditional) {
- for (Conditional cond : resolved.getConditional()) {
- List<String> condition = cond.getCondition();
- List<BundleInfo> conditionalBundles = cond.getBundles();
- for (BundleInfo bundleInfo : conditionalBundles) {
- bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
- }
- }
- }
- for (int i = 0, j = bundleLocation.size(); i < j; i++) {
- System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
- }
- }
- prefix += " ";
- List<Dependency> dependencies = resolved.getDependencies();
- for (int i = 0, j = dependencies.size(); i < j; i++) {
- Dependency toDisplay = dependencies.get(i);
- unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
- }
-
- if (conditional) {
- for (Conditional cond : resolved.getConditional()) {
- List<Dependency> conditionDependencies = cond.getDependencies();
- for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
- Dependency toDisplay = dependencies.get(i);
- unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
- }
- }
- }
- }
-
- return unresolved;
- }
-
- private void displayConditionalInfo(Feature feature) {
- List<? extends Conditional> conditionals = feature.getConditional();
- if (conditionals.isEmpty()) {
- System.out.println("Feature has no conditionals.");
- } else {
- System.out.println("Feature contains followed conditionals:");
- for (Conditional featureConditional : conditionals) {
- String conditionDescription = getConditionDescription(featureConditional);
- Feature wrappedConditional = featureConditional.asFeature(feature.getName(), feature.getVersion());
- if (config) {
- displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
- displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
- }
-
- if (dependency) {
- displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
- }
-
- if (bundle) {
- displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
- }
- }
- }
- }
-
- private String getConditionDescription(Conditional cond) {
- StringBuffer sb = new StringBuffer();
- for (String dep : cond.getCondition()) {
- if (sb.length() > 0) {
- sb.append(" ");
- }
- sb.append(dep);
- }
- return sb.toString();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
deleted file mode 100644
index b7f8184..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AvailableFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "install", description = "Installs a feature with the specified name and version.")
-@Service
-public class InstallFeatureCommand extends FeaturesCommandSupport {
-
- private static String DEFAULT_VERSION = "0.0.0";
-
- @Argument(index = 0, name = "feature", description = "The name and version of the features to install. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
- @Completion(AvailableFeatureCompleter.class)
- List<String> features;
-
- @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
- boolean noRefresh;
-
- @Option(name = "-s", aliases = "--no-auto-start", description = "Do not start the bundles", required = false, multiValued = false)
- boolean noStart;
-
- @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
- boolean verbose;
-
- @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
- boolean simulate;
-
- protected void doExecute(FeaturesService admin) throws Exception {
- EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
- if (simulate) {
- options.add(FeaturesService.Option.Simulate);
- }
- if (noStart) {
- options.add(FeaturesService.Option.NoAutoStartBundles);
- }
- if (noRefresh) {
- options.add(FeaturesService.Option.NoAutoRefreshBundles);
- }
- if (verbose) {
- options.add(FeaturesService.Option.Verbose);
- }
- admin.installFeatures(new HashSet<String>(features), options);
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java b/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
deleted file mode 100644
index b2c5e42..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.Arrays;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.AllFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "version-list", description = "Lists all versions of a feature available from the currently available repositories.")
-@Service
-public class ListFeatureVersionsCommand extends FeaturesCommandSupport {
-
- @Argument(index = 0, name = "feature", description = "Name of feature.", required = true, multiValued = false)
- @Completion(AllFeatureCompleter.class)
- String feature;
-
- @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
- boolean noFormat;
-
- protected void doExecute(FeaturesService admin) throws Exception {
- ShellTable table = new ShellTable();
- table.column("Version");
- table.column("Repository");
- table.column("Repository URL");
- table.emptyTableText("No versions available for features '" + feature + "'");
-
- for (Repository r : Arrays.asList(admin.listRepositories())) {
- for (Feature f : r.getFeatures()) {
-
- if (f.getName().equals(feature)) {
- table.addRow().addContent(f.getVersion(), r.getName(), r.getURI());
- }
- }
- }
-
- table.print(System.out, !noFormat);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java b/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
deleted file mode 100644
index e86ff64..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "list", description = "Lists all existing features available from the defined repositories.")
-@Service
-public class ListFeaturesCommand extends FeaturesCommandSupport {
-
- @Option(name = "-i", aliases = {"--installed"}, description = "Display a list of all installed features only", required = false, multiValued = false)
- boolean onlyInstalled;
-
- @Option(name = "-r", aliases = {"--required"}, description = "Display a list of all required features only", required = false, multiValued = false)
- boolean onlyRequired;
-
- @Option(name = "-o", aliases = {"--ordered"}, description = "Display a list using alphabetical order ", required = false, multiValued = false)
- boolean ordered;
-
- @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
- boolean noFormat;
-
- protected void doExecute(FeaturesService featuresService) throws Exception {
- boolean needsLegend = false;
-
- ShellTable table = new ShellTable();
- table.column("Name");
- table.column("Version");
- table.column("Required");
- table.column("Installed");
- table.column("Repository");
- table.column("Description").maxSize(50);
- table.emptyTableText(onlyInstalled ? "No features installed" : "No features available");
-
- List<Repository> repos = Arrays.asList(featuresService.listRepositories());
- for (Repository r : repos) {
- List<Feature> features = Arrays.asList(r.getFeatures());
- if (ordered) {
- Collections.sort(features, new FeatureComparator());
- }
- for (Feature f : features) {
- if (onlyInstalled && !featuresService.isInstalled(f)) {
- // Filter out not installed features if we only want to see the installed ones
- continue;
- }
- if (onlyRequired && !featuresService.isRequired(f)) {
- // Filter out not installed features if we only want to see the installed ones
- continue;
- }
- table.addRow().addContent(
- f.getName(),
- f.getVersion(),
- featuresService.isRequired(f) ? "x" : "",
- featuresService.isInstalled(f) ? "x" : "",
- r.getName(),
- f.getDescription());
- if (isInstalledViaDeployDir(r.getName())) {
- needsLegend = true;
- }
- }
- }
-
- table.print(System.out, !noFormat);
-
- if (needsLegend) {
- System.out.println("* Installed via deploy directory");
- }
-
- }
-
- private boolean isInstalledViaDeployDir(String st) {
- return (st == null || st.length() <= 1) ? false : (st.charAt(st.length() - 1) == '*');
- }
-
- class FeatureComparator implements Comparator<Feature> {
- public int compare(Feature o1, Feature o2) {
- return o1.getName().toLowerCase().compareTo( o2.getName().toLowerCase() );
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
deleted file mode 100644
index 16faf42..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.net.URI;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AvailableRepoNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "repo-add", description = "Add a features repository")
-@Service
-public class RepoAddCommand extends FeaturesCommandSupport {
-
- @Argument(index = 0, name = "name/url", description = "Shortcut name of the features repository or the full URL", required = true, multiValued = false)
- @Completion(AvailableRepoNameCompleter.class)
- private String nameOrUrl;
-
- @Argument(index = 1, name = "version", description = "The version of the features repository if using features repository name as first argument. It should be empty if using the URL", required = false, multiValued = false)
- private String version;
-
- @Option(name = "-i", aliases = { "--install" }, description = "Install all features contained in the features repository", required = false, multiValued = false)
- private boolean install;
-
- @Override
- protected void doExecute(FeaturesService featuresService) throws Exception {
- String effectiveVersion = (version == null) ? "LATEST" : version;
- URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
- if (uri == null) {
- uri = new URI(nameOrUrl);
- }
- System.out.println("Adding feature url " + uri);
- featuresService.addRepository(uri, install);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
deleted file mode 100644
index 55acf79..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.MultiException;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "repo-list", description = "Displays a list of all defined repositories.")
-@Service
-public class RepoListCommand extends FeaturesCommandSupport {
-
- @Option(name="-r", description="Reload all feature urls", required = false, multiValued = false)
- boolean reload;
-
- @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
- boolean noFormat;
-
- protected void doExecute(FeaturesService featuresService) throws Exception {
- if (reload) {
- reloadAllRepos(featuresService);
- }
-
- ShellTable table = new ShellTable();
- table.column("Repository");
- table.column("URL");
- table.emptyTableText("No repositories available");
-
- Repository[] repos = featuresService.listRepositories();
- for (Repository repo : repos) {
- if (repo != null) {
- table.addRow().addContent(repo.getName(), repo.getURI().toString());
- }
- }
- table.print(System.out, !noFormat);
- }
-
- private void reloadAllRepos(FeaturesService featuresService) throws Exception {
- System.out.println("Reloading all repositories from their urls");
- System.out.println();
- List<Exception> exceptions = new ArrayList<Exception>();
- for (Repository repo : featuresService.listRepositories()) {
- try {
- featuresService.addRepository(repo.getURI());
- } catch (Exception e) {
- exceptions.add(e);
- }
- }
- MultiException.throwIf("Unable to reload repositories", exceptions);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
deleted file mode 100644
index 8c7ed79..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-
-@Command(scope = "feature", name = "repo-refresh", description = "Refresh a features repository")
-public class RepoRefreshCommand extends FeaturesCommandSupport {
- @Argument(index = 0, name = "Feature name or uri", description = "Shortcut name of the feature repository or the full URI", required = false, multiValued = false)
- @Completion(InstalledRepoUriCompleter.class)
- private String nameOrUrl;
-
- @Argument(index = 1, name = "Feature version", description = "The version of the feature if using the feature name. Should be empty if using the uri", required = false, multiValued = false)
- private String version;
-
- @Override
- protected void doExecute(FeaturesService featuresService) throws Exception {
- List<URI> uris = new ArrayList<URI>();
- if (nameOrUrl != null) {
- String effectiveVersion = (version == null) ? "LATEST" : version;
- URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
- if (uri == null) {
- uri = new URI(nameOrUrl);
- }
- uris.add(uri);
- } else {
- Repository[] repos = featuresService.listRepositories();
- for (Repository repo : repos) {
- uris.add(repo.getURI());
- }
- }
- for (URI uri : uris) {
- try {
- System.out.println("Refreshing feature url " + uri);
- featuresService.refreshRepository(uri);
- } catch (Exception e) {
- System.err.println("Error refreshing " + uri.toString() + ": " + e.getMessage());
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
deleted file mode 100644
index 0710b72..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.net.URI;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "repo-remove", description = "Removes the specified repository features service.")
-@Service
-public class RepoRemoveCommand extends FeaturesCommandSupport {
-
- @Argument(index = 0, name = "repository", description = "Name or url of the repository to remove.", required = true, multiValued = false)
- @Completion(InstalledRepoNameCompleter.class)
- private String repository;
-
- @Option(name = "-u", aliases = { "--uninstall-all" }, description = "Uninstall all features from the repository", required = false, multiValued = false)
- private boolean uninstall;
-
- protected void doExecute(FeaturesService featuresService) throws Exception {
- URI uri = null;
- for (Repository r : featuresService.listRepositories()) {
- if (r.getName() != null && r.getName().equals(repository)) {
- uri = r.getURI();
- break;
- }
- }
-
- if (uri == null) {
- uri = new URI(repository);
- }
-
- featuresService.removeRepository(uri, uninstall);
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
deleted file mode 100644
index e62f697..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.RequiredFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "uninstall", description = "Uninstalls a feature with the specified name and version.")
-@Service
-public class UninstallFeatureCommand extends FeaturesCommandSupport {
-
- @Argument(index = 0, name = "features", description = "The name and version of the features to uninstall. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
- @Completion(RequiredFeatureCompleter.class)
- List<String> features;
-
- @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
- boolean noRefresh;
-
- @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
- boolean verbose;
-
- @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
- boolean simulate;
-
- protected void doExecute(FeaturesService admin) throws Exception {
- // iterate in the provided feature
- EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
- if (simulate) {
- options.add(FeaturesService.Option.Simulate);
- }
- if (noRefresh) {
- options.add(FeaturesService.Option.NoAutoRefreshBundles);
- }
- if (verbose) {
- options.add(FeaturesService.Option.Verbose);
- }
- admin.uninstallFeatures(new HashSet<String>(features), options);
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
deleted file mode 100644
index 7444b95..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for available features.
- */
-@Service
-public class AllFeatureCompleter extends FeatureCompleterSupport {
-
- @Override
- protected boolean acceptsFeature(Feature feature) {
- return true;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
deleted file mode 100644
index 79cd280..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for features not installed yet.
- */
-@Service
-public class AvailableFeatureCompleter extends FeatureCompleterSupport {
-
- @Override
- protected boolean acceptsFeature(Feature feature) {
- return !featuresService.isInstalled(feature);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
deleted file mode 100644
index acefe77..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Shows the list of feature repos that can be installed with their short name
- */
-@Service
-public class AvailableRepoNameCompleter implements Completer {
-
- @Reference
- private FeaturesService featuresService;
-
- public void setFeaturesService(FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-
- public int complete(Session session, CommandLine commandLine, final List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter(Arrays.asList(featuresService.getRepositoryNames()));
- return delegate.complete(session, commandLine, candidates);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java b/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
deleted file mode 100644
index d01e5af..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Base completer for feature commands.
- */
-public abstract class FeatureCompleterSupport implements Completer {
-
- /**
- * Feature service.
- */
- @Reference
- protected FeaturesService featuresService;
-
- public void setFeaturesService(FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-
- public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (Feature feature : featuresService.listFeatures()) {
- if (acceptsFeature(feature)) {
- delegate.getStrings().add(feature.getName());
- }
- }
- } catch (Exception e) {
- // Ignore
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
- /**
- * Method for filtering features.
- *
- * @param feature The feature.
- * @return True if feature should be available in completer.
- */
- protected abstract boolean acceptsFeature(Feature feature);
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
deleted file mode 100644
index 94e4cf7..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * {@link Completer} for Feature Repository URLs.
- *
- * Displays a list of currently installed Feature repositories.
- *
- */
-@Service
-public class InstalledRepoNameCompleter implements Completer {
-
- @Reference
- private FeaturesService featuresService;
-
- public void setFeaturesService(FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-
- public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (Repository repository : featuresService.listRepositories()) {
- delegate.getStrings().add(repository.getName());
- }
- } catch (Exception e) {
- // Ignore
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
deleted file mode 100644
index 7a760c2..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * {@link Completer} for Feature Repository URLs.
- *
- * Displays a list of currently installed Feature repositories.
- *
- */
-
-@Service
-public class InstalledRepoUriCompleter implements Completer {
-
- @Reference
- private FeaturesService featuresService;
-
- public void setFeaturesService(FeaturesService featuresService) {
- this.featuresService = featuresService;
- }
-
- public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
- StringsCompleter delegate = new StringsCompleter();
- try {
- for (Repository repository : featuresService.listRepositories()) {
- delegate.getStrings().add(repository.getURI().toString());
- }
- } catch (Exception e) {
- // Ignore
- }
- return delegate.complete(session, commandLine, candidates);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
deleted file mode 100644
index a51f75f..0000000
--- a/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for installed features.
- */
-@Service
-public class RequiredFeatureCompleter extends FeatureCompleterSupport {
-
- @Override
- protected boolean acceptsFeature(Feature feature) {
- return featuresService.isRequired(feature);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
deleted file mode 100644
index c3ac2b7..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.deployment;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.apache.felix.resolver.ResolverImpl;
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.internal.repository.AggregateRepository;
-import org.apache.karaf.features.internal.repository.StaticRepository;
-import org.apache.karaf.features.internal.resolver.FeatureNamespace;
-import org.apache.karaf.features.internal.resolver.FeatureResource;
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
-import org.apache.karaf.features.internal.resolver.ResolveContextImpl;
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.apache.karaf.features.internal.resolver.ResourceImpl;
-import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
-import org.apache.karaf.features.internal.service.Overrides;
-import org.apache.karaf.features.internal.util.Macro;
-import org.apache.karaf.features.internal.util.MultiException;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wire;
-import org.osgi.service.resolver.ResolutionException;
-import org.osgi.service.resolver.ResolveContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class DeploymentBuilder {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentBuilder.class);
-
- public static final String REQ_PROTOCOL = "req:";
-
- private final Collection<Repository> repositories;
-
- private final List<org.osgi.service.repository.Repository> resourceRepos;
-
- String featureRange = "${range;[====,====]}";
-
- Downloader downloader;
- ResourceImpl requirements;
- Map<String, Resource> resources;
- Set<Resource> optionals;
- Map<String, StreamProvider> providers;
-
- Set<Feature> featuresToRegister = new HashSet<Feature>();
-
- public DeploymentBuilder(Downloader downloader,
- Collection<Repository> repositories) {
- this.downloader = downloader;
- this.repositories = repositories;
- this.resourceRepos = new ArrayList<org.osgi.service.repository.Repository>();
- }
-
- public void addResourceRepository(org.osgi.service.repository.Repository repository) {
- resourceRepos.add(repository);
- }
-
- public Map<String, StreamProvider> getProviders() {
- return providers;
- }
-
- public void setFeatureRange(String featureRange) {
- this.featureRange = featureRange;
- }
-
- public Map<String, Resource> download(
- Set<String> features,
- Set<String> bundles,
- Set<String> reqs,
- Set<String> overrides,
- Set<String> optionals)
- throws IOException, MultiException, InterruptedException, ResolutionException, BundleException {
- this.resources = new ConcurrentHashMap<String, Resource>();
- this.optionals = new HashSet<Resource>();
- this.providers = new ConcurrentHashMap<String, StreamProvider>();
- this.requirements = new ResourceImpl("dummy", "dummy", Version.emptyVersion);
- // First, gather all bundle resources
- for (String feature : features) {
- registerMatchingFeatures(feature);
- }
- for (String bundle : bundles) {
- downloadAndBuildResource(bundle);
- }
- for (String req : reqs) {
- buildRequirement(req);
- }
- for (String override : overrides) {
- // TODO: ignore download failures for overrides
- downloadAndBuildResource(Overrides.extractUrl(override));
- }
- for (String optional : optionals) {
- downloadAndBuildResource(optional);
- }
- // Wait for all resources to be created
- downloader.await();
- // Do override replacement
- Overrides.override(resources, overrides);
- // Build features resources
- for (Feature feature : featuresToRegister) {
- Resource resource = FeatureResource.build(feature, featureRange, resources);
- resources.put("feature:" + feature.getName() + "/" + feature.getVersion(), resource);
- for (Conditional cond : feature.getConditional()) {
- this.optionals.add(FeatureResource.build(feature, cond, featureRange, resources));
- }
- }
- // Build requirements
- for (String feature : features) {
- requireFeature(feature);
- }
- for (String bundle : bundles) {
- requireResource(bundle);
- }
- for (String req : reqs) {
- requireResource(REQ_PROTOCOL + req);
- }
- return resources;
- }
-
- public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles) throws ResolutionException {
- // Resolve
- for (int i = 0; i < systemBundles.size(); i++) {
- resources.put("system-bundle-" + i, systemBundles.get(i));
- }
-
- List<org.osgi.service.repository.Repository> repos = new ArrayList<org.osgi.service.repository.Repository>();
- repos.add(new StaticRepository(resources.values()));
- repos.addAll(resourceRepos);
-
- ResolverImpl resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
- ResolveContext context = new ResolveContextImpl(
- Collections.<Resource>singleton(requirements),
- Collections.<Resource>emptySet(),
- new AggregateRepository(repos),
- false);
- Map<Resource, List<Wire>> best = resolver.resolve(context);
-
- // TODO: we actually need to use multiple passes for conditionals
- // TODO: but it may be optimized by passing the old wiring instead
- // TODO: of computing everything again
- Set<Resource> resources = new HashSet<Resource>();
- resources.add(requirements);
- for (Resource optional : optionals) {
- try {
- Set<Resource> newSet = new HashSet<Resource>(resources);
- newSet.add(optional);
- context = new ResolveContextImpl(
- newSet,
- Collections.<Resource>emptySet(),
- new AggregateRepository(repos),
- false);
- best = resolver.resolve(context);
- resources = newSet;
- } catch (ResolutionException e) {
- // Ignore this resource
- }
- }
- return best;
- }
-
- public void requireFeature(String feature) throws IOException {
- // Find name and version range
- String[] split = feature.split("/");
- String name = split[0].trim();
- String version = (split.length > 1) ? split[1].trim() : null;
- if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
- version = Macro.transform(featureRange, version);
- }
- VersionRange range = version != null ? new VersionRange(version) : VersionRange.ANY_VERSION;
- // Add requirement
- Map<String, Object> attrs = new HashMap<String, Object>();
- attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
- attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, FeatureNamespace.TYPE_FEATURE);
- attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, range);
- requirements.addRequirement(
- new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
- Collections.<String, String>emptyMap(), attrs)
- );
- }
-
- public void requireResource(String location) {
- Resource res = resources.get(location);
- if (res == null) {
- throw new IllegalStateException("Could not find resource for " + location);
- }
- List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
- if (caps.size() != 1) {
- throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
- }
- Capability cap = caps.get(0);
- // Add requirement
- Map<String, Object> attrs = new HashMap<String, Object>();
- attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
- attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
- attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
- requirements.addRequirement(
- new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
- Collections.<String, String>emptyMap(), attrs));
-
- }
-
- public void registerMatchingFeatures(String feature) throws IOException {
- // Find name and version range
- String[] split = feature.split("/");
- String name = split[0].trim();
- String version = (split.length > 1)
- ? split[1].trim() : Version.emptyVersion.toString();
- // Register matching features
- registerMatchingFeatures(name, new VersionRange(version));
- }
-
- public void registerMatchingFeatures(String name, String version) throws IOException {
- if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
- version = Macro.transform(featureRange, version);
- }
- registerMatchingFeatures(name, version != null ? new VersionRange(version) : VersionRange.ANY_VERSION);
- }
-
- public void registerMatchingFeatures(String name, VersionRange range) throws IOException {
- for (Repository repo : repositories) {
- Feature[] features;
- try {
- features = repo.getFeatures();
- } catch (Exception e) {
- // This should not happen as the repository has been loaded already
- throw new IllegalStateException(e);
- }
- for (Feature f : features) {
- if (name.equals(f.getName())) {
- Version v = VersionTable.getVersion(f.getVersion());
- if (range.contains(v)) {
- featuresToRegister.add(f);
- for (Dependency dep : f.getDependencies()) {
- registerMatchingFeatures(dep.getName(), dep.getVersion());
- }
- for (BundleInfo bundle : f.getBundles()) {
- downloadAndBuildResource(bundle.getLocation());
- }
- for (Conditional cond : f.getConditional()) {
- Feature c = cond.asFeature(f.getName(), f.getVersion());
- featuresToRegister.add(c);
- for (BundleInfo bundle : c.getBundles()) {
- downloadAndBuildResource(bundle.getLocation());
- }
- }
- }
- }
- }
- }
- }
-
- public void buildRequirement(String requirement) {
- try {
- String location = REQ_PROTOCOL + requirement;
- ResourceImpl resource = new ResourceImpl(location, "dummy", Version.emptyVersion);
- for (Requirement req : ResourceBuilder.parseRequirement(resource, requirement)) {
- resource.addRequirement(req);
- }
- resources.put(location, resource);
- } catch (BundleException e) {
- throw new IllegalArgumentException("Error parsing requirement: " + requirement, e);
- }
- }
-
- public void downloadAndBuildResource(final String location) throws IOException {
- if (!resources.containsKey(location)) {
- downloader.download(location, new Downloader.DownloadCallback() {
- @Override
- public void downloaded(StreamProvider provider) throws Exception {
- manageResource(location, provider);
- }
- });
- }
- }
-
- private void manageResource(String location, StreamProvider provider) throws Exception {
- if (!resources.containsKey(location)) {
- Attributes attributes = getAttributes(location, provider);
- Resource resource = createResource(location, attributes);
- resources.put(location, resource);
- providers.put(location, provider);
- }
- }
-
- private Resource createResource(String uri, Attributes attributes) throws Exception {
- Map<String, String> headers = new HashMap<String, String>();
- for (Map.Entry attr : attributes.entrySet()) {
- headers.put(attr.getKey().toString(), attr.getValue().toString());
- }
- try {
- return ResourceBuilder.build(uri, headers);
- } catch (BundleException e) {
- throw new Exception("Unable to create resource for bundle " + uri, e);
- }
- }
-
- protected Attributes getAttributes(String uri, StreamProvider provider) throws Exception {
- InputStream is = provider.open();
- try {
- ZipInputStream zis = new ZipInputStream(is);
- ZipEntry entry;
- while ( (entry = zis.getNextEntry()) != null ) {
- if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
- return new Manifest(zis).getMainAttributes();
- }
- }
- } finally {
- is.close();
- }
- throw new IllegalArgumentException("Resource " + uri + " does not contain a manifest");
- }
-
-}
[07/33] [KARAF-2852] Merge jms/core and jms/command
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
----------------------------------------------------------------------
diff --git a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java b/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
deleted file mode 100644
index fe4b43d..0000000
--- a/jms/core/src/main/java/org/apache/karaf/jms/internal/JmsServiceImpl.java
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.jms.internal;
-
-import org.apache.activemq.ActiveMQConnection;
-import org.apache.activemq.advisory.DestinationSource;
-import org.apache.activemq.command.ActiveMQQueue;
-import org.apache.activemq.command.ActiveMQTopic;
-import org.apache.activemq.pool.PooledConnection;
-import org.apache.karaf.jms.JmsMessage;
-import org.apache.karaf.jms.JmsService;
-import org.apache.karaf.util.TemplateUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-import javax.jms.*;
-
-import java.io.*;
-import java.lang.IllegalStateException;
-import java.util.*;
-
-/**
- * Default implementation of the JMS Service.
- */
-public class JmsServiceImpl implements JmsService {
-
- private BundleContext bundleContext;
- private File deployFolder;
-
- public JmsServiceImpl() {
- File karafBase = new File(System.getProperty("karaf.base"));
- deployFolder = new File(karafBase, "deploy");
- }
-
- @Override
- public void create(String name, String type, String url) throws Exception {
- if (!type.equalsIgnoreCase("activemq") && !type.equalsIgnoreCase("webspheremq")) {
- throw new IllegalArgumentException("JMS connection factory type not known");
- }
-
- File outFile = getConnectionFactoryFile(name);
- String template;
- HashMap<String, String> properties = new HashMap<String, String>();
- properties.put("name", name);
-
- if (type.equalsIgnoreCase("activemq")) {
- // activemq
- properties.put("url", url);
- template = "connectionfactory-activemq.xml";
- } else {
- // webspheremq
- String[] splitted = url.split("/");
- if (splitted.length != 4) {
- throw new IllegalStateException("WebsphereMQ URI should be in the following format: host/port/queuemanager/channel");
- }
-
- properties.put("host", splitted[0]);
- properties.put("port", splitted[1]);
- properties.put("queuemanager", splitted[2]);
- properties.put("channel", splitted[3]);
- template = "connectionfactory-webspheremq.xml";
- }
- InputStream is = this.getClass().getResourceAsStream(template);
- if (is == null) {
- throw new IllegalArgumentException("Template resource " + template + " doesn't exist");
- }
- TemplateUtils.createFromTemplate(outFile, is, properties);
- }
-
- private File getConnectionFactoryFile(String name) {
- return new File(deployFolder, "connectionfactory-" + name + ".xml");
- }
-
- @Override
- public void delete(String name) throws Exception {
- File connectionFactoryFile = getConnectionFactoryFile(name);
- if (!connectionFactoryFile.exists()) {
- throw new IllegalStateException("The JMS connection factory file " + connectionFactoryFile.getPath() + " doesn't exist");
- }
- connectionFactoryFile.delete();
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public List<String> connectionFactories() throws Exception {
- List<String> connectionFactories = new ArrayList<String>();
- ServiceReference[] references = bundleContext.getServiceReferences(ConnectionFactory.class.getName(), null);
- if (references != null) {
- for (ServiceReference reference : references) {
- if (reference.getProperty("osgi.jndi.service.name") != null) {
- connectionFactories.add((String) reference.getProperty("osgi.jndi.service.name"));
- } else if (reference.getProperty("name") != null) {
- connectionFactories.add((String) reference.getProperty("name"));
- } else {
- connectionFactories.add(reference.getProperty(Constants.SERVICE_ID).toString());
- }
- }
- }
- return connectionFactories;
- }
-
- @Override
- public List<String> connectionFactoryFileNames() throws Exception {
- String[] connectionFactoryFileNames = deployFolder.list(new FilenameFilter() {
-
- @Override
- public boolean accept(File dir, String name) {
- return name.startsWith("connectionfactory-") && name.endsWith(".xml");
- }
- });
-
- return Arrays.asList(connectionFactoryFileNames);
- }
-
- @Override
- public Map<String, String> info(String connectionFactory, String username, String password) throws IOException, JMSException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- ConnectionMetaData metaData = connector.connect().getMetaData();
- Map<String, String> map = new HashMap<String, String>();
- map.put("product", metaData.getJMSProviderName());
- map.put("version", metaData.getProviderVersion());
- return map;
- } finally {
- connector.close();
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public int count(String connectionFactory, final String destination, String username, String password) throws IOException, JMSException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- Session session = connector.createSession();
- QueueBrowser browser = session.createBrowser(session.createQueue(destination));
- Enumeration<Message> enumeration = browser.getEnumeration();
- int count = 0;
- while (enumeration.hasMoreElements()) {
- enumeration.nextElement();
- count++;
- }
- browser.close();
- return count;
- } finally {
- connector.close();
- }
- }
-
- private DestinationSource getDestinationSource(Connection connection) throws JMSException {
- if (connection instanceof PooledConnection) {
- connection = ((PooledConnection) connection).getConnection();
- }
- if (connection instanceof ActiveMQConnection) {
- return ((ActiveMQConnection) connection).getDestinationSource();
- } else {
- return null;
- }
- }
-
- @Override
- public List<String> queues(String connectionFactory, String username, String password) throws JMSException, IOException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- List<String> queues = new ArrayList<String>();
- DestinationSource destinationSource = getDestinationSource(connector.connect());
- if (destinationSource != null) {
- Set<ActiveMQQueue> activeMQQueues = destinationSource.getQueues();
- for (ActiveMQQueue activeMQQueue : activeMQQueues) {
- queues.add(activeMQQueue.getQueueName());
- }
- }
- return queues;
- } finally {
- connector.close();
- }
- }
-
- @Override
- public List<String> topics(String connectionFactory, String username, String password) throws IOException, JMSException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- DestinationSource destinationSource = getDestinationSource(connector.connect());
- List<String> topics = new ArrayList<String>();
- if (destinationSource != null) {
- Set<ActiveMQTopic> activeMQTopics = destinationSource.getTopics();
- for (ActiveMQTopic activeMQTopic : activeMQTopics) {
- topics.add(activeMQTopic.getTopicName());
- }
- }
- return topics;
- } finally {
- connector.close();
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public List<JmsMessage> browse(String connectionFactory, final String queue, final String filter,
- String username, String password) throws JMSException, IOException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- List<JmsMessage> messages = new ArrayList<JmsMessage>();
- Session session = connector.createSession();
- QueueBrowser browser = session.createBrowser(session.createQueue(queue), filter);
- Enumeration<Message> enumeration = browser.getEnumeration();
- while (enumeration.hasMoreElements()) {
- Message message = enumeration.nextElement();
-
- messages.add(new JmsMessage(message));
- }
- browser.close();
- return messages;
- } finally {
- connector.close();
- }
- }
-
- @Override
- public void send(String connectionFactory, final String queue, final String body, final String replyTo,
- String username, String password) throws IOException, JMSException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- Session session = connector.createSession();
- Message message = session.createTextMessage(body);
- if (replyTo != null) {
- message.setJMSReplyTo(session.createQueue(replyTo));
- }
- MessageProducer producer = session.createProducer(session.createQueue(queue));
- producer.send(message);
- producer.close();
- } finally {
- connector.close();
- }
- }
-
- @Override
- public int consume(String connectionFactory, final String queue, final String selector, String username,
- String password) throws Exception {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- int count = 0;
- Session session = connector.createSession();
- MessageConsumer consumer = session.createConsumer(session.createQueue(queue), selector);
- Message message;
- do {
- message = consumer.receive(5000L);
- if (message != null) {
- count++;
- }
- } while (message != null);
- return count;
- } finally {
- connector.close();
- }
- }
-
- @Override
- public int move(String connectionFactory, final String sourceQueue, final String targetQueue,
- final String selector, String username, String password) throws IOException, JMSException {
- JmsConnector connector = new JmsConnector(bundleContext, connectionFactory, username, password);
- try {
- int count = 0;
- Session session = connector.createSession();
- MessageConsumer consumer = session.createConsumer(session.createQueue(sourceQueue), selector);
- Message message;
- do {
- message = consumer.receive(5000L);
- if (message != null) {
- MessageProducer producer = session.createProducer(session.createQueue(targetQueue));
- producer.send(message);
- count++;
- }
- } while (message != null);
- consumer.close();
- return count;
- } finally {
- connector.close();
- }
- }
-
- public void setBundleContext(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml b/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
deleted file mode 100644
index 7dd8070..0000000
--- a/jms/core/src/main/resources/OSGI-INF/blueprint/jms-core.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
- default-activation="lazy">
-
- <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
- <bean id="jmsService" class="org.apache.karaf.jms.internal.JmsServiceImpl">
- <property name="bundleContext" ref="blueprintBundleContext"/>
- </bean>
-
- <service ref="jmsService" interface="org.apache.karaf.jms.JmsService" />
-
- <!-- Management -->
- <bean id="jmsMBeanImpl" class="org.apache.karaf.jms.internal.JmsMBeanImpl">
- <property name="jmsService" ref="jmsService"/>
- </bean>
-
- <service ref="jmsMBeanImpl" auto-export="interfaces">
- <service-properties>
- <entry key="jmx.objectname" value="org.apache.karaf:type=jms,name=$[karaf.name]"/>
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/OSGI-INF/bundle.info b/jms/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 1aeb646..0000000
--- a/jms/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,18 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the JMS service support.
-
-The JMS service allows you to create connection factories, and send/browse/consume messages.
-
-h1. See also
-
-JMS - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
deleted file mode 100644
index f0aabbd..0000000
--- a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-activemq.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="activemqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
- <property name="brokerURL" value="${url}" />
- </bean>
-
- <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
- <property name="maxConnections" value="8" />
- <property name="connectionFactory" ref="activemqConnectionFactory" />
- </bean>
-
- <bean id="resourceManager" class="org.apache.activemq.pool.ActiveMQResourceManager" init-method="recoverResource">
- <property name="transactionManager" ref="transactionManager" />
- <property name="connectionFactory" ref="activemqConnectionFactory" />
- <property name="resourceName" value="activemq.localhost" />
- </bean>
-
- <reference id="transactionManager" interface="javax.transaction.TransactionManager" />
-
- <service ref="pooledConnectionFactory" interface="javax.jms.ConnectionFactory">
- <service-properties>
- <entry key="name" value="${name}" />
- <entry key="osgi.jndi.service.name" value="jms/${name}" />
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
----------------------------------------------------------------------
diff --git a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml b/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
deleted file mode 100644
index 3123f49..0000000
--- a/jms/core/src/main/resources/org/apache/karaf/jms/internal/connectionfactory-webspheremq.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
- <bean id="wmqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
- <property name="transportType" value="1" />
- <property name="hostName" value="${hostname}" />
- <property name="port" value="${port}" />
- <property name="queueManager" value="${queuemanager}" />
- <property name="channel" value="${channel}" />
- <property name="useConnectionPooling" value="true" />
- </bean>
-
- <service ref="wmqConnectionFactory" interface="javax.jms.ConnectionFactory">
- <service-properties>
- <entry key="name" value="${name}"/>
- <entry key="osgi.jndi.service.name" value="jms/${name}"/>
- </service-properties>
- </service>
-
-</blueprint>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/pom.xml
----------------------------------------------------------------------
diff --git a/jms/pom.xml b/jms/pom.xml
index 4a2d8d2..c7cd769 100644
--- a/jms/pom.xml
+++ b/jms/pom.xml
@@ -29,13 +29,83 @@
</parent>
<groupId>org.apache.karaf.jms</groupId>
- <artifactId>jms</artifactId>
- <packaging>pom</packaging>
- <name>Apache Karaf :: JMS</name>
-
- <modules>
- <module>core</module>
- <module>command</module>
- </modules>
+ <artifactId>org.apache.karaf.jms.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: JMS :: Core</name>
+ <description>This bundle provides core implementation of the JMS service.</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>activemq-pool</artifactId>
+ <version>5.9.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.karaf.jms
+ </Export-Package>
+ <Import-Package>
+ org.apache.activemq*;resolution:=optional,
+ *
+ </Import-Package>
+ <Private-Package>
+ org.apache.karaf.jms.command,
+ org.apache.karaf.jms.command.completers,
+ org.apache.karaf.jms.internal,
+ org.apache.karaf.util
+ </Private-Package>
+ <Karaf-Commands>*</Karaf-Commands>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/JmsMBean.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/JmsMBean.java b/jms/src/main/java/org/apache/karaf/jms/JmsMBean.java
new file mode 100644
index 0000000..8540b86
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/JmsMBean.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JMS MBean.
+ */
+public interface JmsMBean {
+
+ /**
+ * List the JMS connection factories.
+ *
+ * @return the list of the JMS connection factories name.
+ * @throws MBeanException
+ */
+ List<String> getConnectionfactories() throws MBeanException;
+
+ /**
+ * Create a JMS connection factory.
+ *
+ * @param name the JMS connection factory name.
+ * @param type the JMS connection factory type (ActiveMQ or WebsphereMQ).
+ * @param url the JMS connection factory URL. NB: when type is WebsphereMQ, the URL has the format host/port/queuemanager/channel.
+ * @throws MBeanException
+ */
+ void create(String name, String type, String url) throws MBeanException;
+
+ /**
+ * Delete a JMS connection factory.
+ *
+ * @param name the JMS connection factory name.
+ * @throws MBeanException
+ */
+ void delete(String name) throws MBeanException;
+
+ /**
+ * Get details about a JMS connection factory.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return a map (property/value) containing details.
+ * @throws MBeanException
+ */
+ Map<String, String> info(String connectionFactory, String username, String password) throws MBeanException;
+
+ /**
+ * Count the messages on a given JMS queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the JMS queue name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return
+ * @throws MBeanException
+ */
+ int count(String connectionFactory, String queue, String username, String password) throws MBeanException;
+
+ /**
+ * List the JMS queues.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the list of JMS queues.
+ * @throws MBeanException
+ */
+ List<String> queues(String connectionFactory, String username, String password) throws MBeanException;
+
+ /**
+ * List the JMS topics.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the list of JMS topics.
+ * @throws MBeanException
+ */
+ List<String> topics(String connectionFactory, String username, String password) throws MBeanException;
+
+ /**
+ * Browse the messages in a JMS queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the JMS queue name.
+ * @param selector a selector to use to browse only certain messages.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return a tabular data with messages details.
+ * @throws MBeanException
+ */
+ TabularData browse(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
+
+ /**
+ * Send a JMS message to given queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the JMS queue name.
+ * @param content the message content.
+ * @param replyTo the message ReplyTo.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @throws MBeanException
+ */
+ void send(String connectionFactory, String queue, String content, String replyTo, String username, String password) throws MBeanException;
+
+ /**
+ * Consume JMS messages from a given queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the JMS queue name.
+ * @param selector a selector to use to consume only certain messages.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the number of messages consumed.
+ * @throws MBeanException
+ */
+ int consume(String connectionFactory, String queue, String selector, String username, String password) throws MBeanException;
+
+ /**
+ * Move JMS messages from one queue to another.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param source the source JMS queue name.
+ * @param destination the destination JMS queue name.
+ * @param selector a selector to move only certain messages.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the number of messages moved.
+ * @throws MBeanException
+ */
+ int move(String connectionFactory, String source, String destination, String selector, String username, String password) throws MBeanException;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/JmsMessage.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/JmsMessage.java b/jms/src/main/java/org/apache/karaf/jms/JmsMessage.java
new file mode 100644
index 0000000..a85af10
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/JmsMessage.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms;
+
+import javax.jms.*;
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Describe a JMS message is more human readable way.
+ */
+public class JmsMessage {
+
+ private Map<String, Object> properties = new HashMap<String, Object>();
+
+ private String content;
+ private String charset = "UTF-8";
+ private String correlationID;
+ private String deliveryMode;
+ private String destination;
+ private String expiration;
+ private String messageId;
+ private int priority;
+ private boolean redelivered;
+ private String replyTo;
+ private String timestamp;
+ private String type;
+
+ public JmsMessage(Message message) {
+ try {
+ initFromMessage(message);
+ } catch (JMSException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public void initFromMessage(Message message) throws JMSException {
+ @SuppressWarnings("unchecked")
+ Enumeration<String> names = message.getPropertyNames();
+ while (names.hasMoreElements()) {
+ String key = names.nextElement();
+ Object value = message.getObjectProperty(key);
+ properties.put(key, value);
+ }
+
+ correlationID = message.getJMSCorrelationID();
+ if (message.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT) {
+ deliveryMode = "Non Persistent";
+ } else {
+ deliveryMode = "Persistent";
+ }
+ Destination destinationDest = message.getJMSDestination();
+ if (destinationDest != null) {
+ destination = destinationDest.toString();
+ }
+ if (message.getJMSExpiration() > 0) {
+ expiration = new Date(message.getJMSExpiration()).toString();
+ } else {
+ expiration = "Never";
+ }
+ messageId = message.getJMSMessageID();
+ priority = message.getJMSPriority();
+ redelivered = message.getJMSRedelivered();
+ Destination replyToDest = message.getJMSReplyTo();
+ if (replyToDest != null) {
+ replyTo = replyToDest.toString();
+ }
+ if (message.getJMSTimestamp() > 0) {
+ timestamp = new Date(message.getJMSTimestamp()).toString();
+ } else {
+ timestamp = "";
+ }
+ type = message.getJMSType();
+ content = getMessageContent(message);
+ }
+
+
+ private String getMessageContent(Message message) throws JMSException {
+ if (message instanceof TextMessage) {
+ return ((TextMessage) message).getText();
+ } else if (message instanceof BytesMessage) {
+ BytesMessage bMessage = (BytesMessage) message;
+ long length = bMessage.getBodyLength();
+ byte[] content = new byte[(int) length];
+ bMessage.readBytes(content);
+ try {
+ return new String(content, charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+ return "";
+ }
+
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public String getCharset() {
+ return charset;
+ }
+
+ public String getCorrelationID() {
+ return correlationID;
+ }
+
+ public String getDeliveryMode() {
+ return deliveryMode;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public String getExpiration() {
+ return expiration;
+ }
+
+ public String getMessageId() {
+ return messageId;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public boolean isRedelivered() {
+ return redelivered;
+ }
+
+ public String getReplyTo() {
+ return replyTo;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/JmsService.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/JmsService.java b/jms/src/main/java/org/apache/karaf/jms/JmsService.java
new file mode 100644
index 0000000..8aa970f
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/JmsService.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JMS Service.
+ */
+public interface JmsService {
+
+ /**
+ * List the JMS connection factories.
+ *
+ * @return the list of JMS connection factory names.
+ * @throws Exception
+ */
+ List<String> connectionFactories() throws Exception;
+
+ /**
+ * List the JMS connecion factories file names.
+ *
+ * @return the list of JMS connection factory file names.
+ * @throws Exception
+ */
+ List<String> connectionFactoryFileNames() throws Exception;
+
+ /**
+ * Create a new JMS connection factory.
+ *
+ * @param name the JMS connection factory name.
+ * @param type the JMS connection factory type (ActiveMQ, WebsphereMQ, ...).
+ * @param url the JMS URL to use.
+ * @throws Exception
+ */
+ void create(String name, String type, String url) throws Exception;
+
+ /**
+ * Delete a JMS connection factory.
+ *
+ * @param name the JMS connection factory name.
+ * @throws Exception
+ */
+ void delete(String name) throws Exception;
+
+ /**
+ * Get details about a given JMS connection factory.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return a map (property/value) containing details.
+ * @throws Exception
+ */
+ Map<String, String> info(String connectionFactory, String username, String password) throws Exception;
+
+ /**
+ * Count the number of messages in a JMS queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the queue name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the number of messages in a JMS queue.
+ * @throws Exception
+ */
+ int count(String connectionFactory, String queue, String username, String password) throws Exception;
+
+ /**
+ * List the queues.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the list of queues.
+ * @throws Exception
+ */
+ List<String> queues(String connectionFactory, String username, String password) throws Exception;
+
+ /**
+ * List the topics.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the list of topics.
+ * @throws Exception
+ */
+ List<String> topics(String connectionFactory, String username, String password) throws Exception;
+
+ /**
+ * Browse a destination.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the queue name.
+ * @param selector the selector.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the list of messages.
+ * @throws Exception
+ */
+ List<JmsMessage> browse(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
+
+ /**
+ * Send a message on the given queue.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the queue name.
+ * @param body the message body.
+ * @param replyTo the message replyTo header.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @throws Exception
+ */
+ void send(String connectionFactory, String queue, String body, String replyTo, String username, String password) throws Exception;
+
+ /**
+ * Consume messages from a given destination.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param queue the queue name.
+ * @param selector the messages selector.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the number of messages consumed.
+ * @throws Exception
+ */
+ int consume(String connectionFactory, String queue, String selector, String username, String password) throws Exception;
+
+ /**
+ * Move messages from a destination to another.
+ *
+ * @param connectionFactory the JMS connection factory name.
+ * @param sourceQueue the source queue.
+ * @param targetQueue the target queue.
+ * @param selector the messages selector on the source queue.
+ * @param username optional username to connect to the JMS broker.
+ * @param password optional password to connect to the JMS broker.
+ * @return the number of messages moved.
+ * @throws Exception
+ */
+ int move(String connectionFactory, String sourceQueue, String targetQueue, String selector, String username, String password) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
new file mode 100644
index 0000000..cb86aa6
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/BrowseCommand.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import java.util.List;
+
+import org.apache.karaf.jms.JmsMessage;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "browse", description = "Browse a JMS queue")
+@Service
+public class BrowseCommand extends JmsConnectionCommandSupport {
+
+ @Argument(index = 1, name = "queue", description = "The JMS queue to browse", required = true, multiValued = false)
+ String queue;
+
+ @Option(name = "-s", aliases = { "--selector" }, description = "The selector to select the messages to browse", required = false, multiValued = false)
+ String selector;
+
+ @Option(name = "-v", aliases = { "--verbose" }, description = "Display JMS properties", required = false, multiValued = false)
+ boolean verbose = false;
+
+ @Override
+ public Object execute() throws Exception {
+
+ ShellTable table = new ShellTable();
+ table.column("Message ID");
+ table.column("Content").maxSize(80);
+ table.column("Charset");
+ table.column("Type");
+ table.column("Correlation ID");
+ table.column("Delivery Mode");
+ table.column("Destination");
+ table.column("Expiration");
+ table.column("Priority");
+ table.column("Redelivered");
+ table.column("ReplyTo");
+ table.column("Timestamp");
+ if (verbose) {
+ table.column("Properties");
+ }
+
+ List<JmsMessage> messages = getJmsService().browse(connectionFactory, queue, selector, username, password);
+ for (JmsMessage message : messages) {
+ if (verbose) {
+ StringBuilder properties = new StringBuilder();
+ for (String property : message.getProperties().keySet()) {
+ properties.append(property).append("=").append(message.getProperties().get(property)).append("\n");
+ }
+ table.addRow().addContent(
+ message.getMessageId(),
+ message.getContent(),
+ message.getCharset(),
+ message.getType(),
+ message.getCorrelationID(),
+ message.getDeliveryMode(),
+ message.getDestination(),
+ message.getExpiration(),
+ message.getPriority(),
+ message.isRedelivered(),
+ message.getReplyTo(),
+ message.getTimestamp(),
+ properties.toString());
+ } else {
+ table.addRow().addContent(
+ message.getMessageId(),
+ message.getContent(),
+ message.getCharset(),
+ message.getType(),
+ message.getCorrelationID(),
+ message.getDeliveryMode(),
+ message.getDestination(),
+ message.getExpiration(),
+ message.getPriority(),
+ message.isRedelivered(),
+ message.getReplyTo(),
+ message.getTimestamp());
+ }
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
new file mode 100644
index 0000000..b698336
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/ConnectionFactoriesCommand.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "connectionfactories", description = "List the JMS connection factories")
+@Service
+public class ConnectionFactoriesCommand extends JmsCommandSupport {
+
+ @Override
+ public Object execute() throws Exception {
+
+ ShellTable table = new ShellTable();
+ table.column("JMS Connection Factory");
+
+ List<String> connectionFactories = getJmsService().connectionFactories();
+ for (String connectionFactory : connectionFactories) {
+ table.addRow().addContent(connectionFactory);
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
new file mode 100644
index 0000000..cd8caaf
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/ConsumeCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jms", name = "consume", description = "Consume messages from a JMS queue.")
+@Service
+public class ConsumeCommand extends JmsConnectionCommandSupport {
+
+ @Argument(index = 1, name = "queue", description = "The JMS queue where to consume messages", required = true, multiValued = false)
+ String queue;
+
+ @Option(name = "-s", aliases = { "--selector" }, description = "The selector to use to select the messages to consume", required = false, multiValued = false)
+ String selector;
+
+ @Override
+ public Object execute() throws Exception {
+ System.out.println(getJmsService().consume(connectionFactory, queue, selector, username, password) + " message(s) consumed");
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/CountCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/CountCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/CountCommand.java
new file mode 100644
index 0000000..576e8dd
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/CountCommand.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "count", description = "Count the number of messages on a JMS queue.")
+@Service
+public class CountCommand extends JmsConnectionCommandSupport {
+
+ @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
+ String queue;
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+ table.column("Messages Count");
+ table.addRow().addContent(getJmsService().count(connectionFactory, queue, username, password));
+ table.print(System.out);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/CreateCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
new file mode 100644
index 0000000..c2c7eca
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/CreateCommand.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+@Command(scope = "jms", name = "create", description = "Create a JMS connection factory.")
+@Service
+public class CreateCommand extends JmsCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
+ String name;
+
+ @Option(name = "-t", aliases = { "--type" }, description = "The JMS connection factory type (ActiveMQ or WebsphereMQ)", required = false, multiValued = false)
+ @Completion(value = StringsCompleter.class, values = { "activemq", "webspheremq" })
+ String type = "ActiveMQ";
+
+ @Option(name = "--url", description = "URL of the JMS broker. For WebsphereMQ type, the URL is hostname/port/queuemanager/channel", required = false, multiValued = false)
+ String url = "tcp://localhost:61616";
+
+ @Override
+ public Object execute() throws Exception {
+ getJmsService().create(name, type, url);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
new file mode 100644
index 0000000..cab3123
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/DeleteCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.jms.command.completers.ConnectionFactoriesFileNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jms", name = "delete", description = "Delete a JMS connection factory")
+@Service
+public class DeleteCommand extends JmsCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "The JMS connection factory name", required = true, multiValued = false)
+ @Completion(ConnectionFactoriesFileNameCompleter.class)
+ String name;
+
+ @Override
+ public Object execute() throws Exception {
+ getJmsService().delete(name);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/InfoCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
new file mode 100644
index 0000000..354db39
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/InfoCommand.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "info", description = "Provides details about a JMS connection factory.")
+@Service
+public class InfoCommand extends JmsConnectionCommandSupport {
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+ table.column("Property");
+ table.column("Value");
+
+ Map<String, String> info = getJmsService().info(connectionFactory, username, password);
+ for (String key : info.keySet()) {
+ table.addRow().addContent(key, info.get(key));
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java b/jms/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
new file mode 100644
index 0000000..2f5df8f
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/JmsCommandSupport.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+
+public abstract class JmsCommandSupport implements Action {
+
+ @Reference
+ private JmsService jmsService;
+
+ public JmsService getJmsService() {
+ return jmsService;
+ }
+
+ public void setJmsService(JmsService jmsService) {
+ this.jmsService = jmsService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java b/jms/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
new file mode 100644
index 0000000..64adfe4
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/JmsConnectionCommandSupport.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+import org.apache.karaf.jms.command.completers.ConnectionFactoriesNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+
+/**
+ * For commands that need a connection factory and authentication information
+ */
+public abstract class JmsConnectionCommandSupport extends JmsCommandSupport {
+
+ @Argument(index = 0, name = "connectionFactory", description = "The JMS connection factory name", required = true, multiValued = false)
+ @Completion(ConnectionFactoriesNameCompleter.class)
+ String connectionFactory;
+
+ @Option(name = "-u", aliases = { "--username" }, description = "Username to connect to the JMS broker", required = false, multiValued = false)
+ String username = "karaf";
+
+ @Option(name = "-p", aliases = { "--password" }, description = "Password to connect to the JMS broker", required = false, multiValued = false)
+ String password = "karaf";
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/MoveCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
new file mode 100644
index 0000000..a4c8d12
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/MoveCommand.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jms", name = "move", description = "Move messages from one JMS queue to another one.")
+@Service
+public class MoveCommand extends JmsConnectionCommandSupport {
+
+ @Argument(index = 1, name = "source", description = "The source JMS queue", required = true, multiValued = false)
+ String source;
+
+ @Argument(index = 2, name = "destination", description = "The destination JMS queue", required = true, multiValued = false)
+ String destination;
+
+ @Option(name = "-s", aliases = { "--selector" }, description = "Selector to move only some messages", required = false, multiValued = false)
+ String selector;
+
+ @Override
+ public Object execute() throws Exception {
+ System.out.println(getJmsService().move(connectionFactory, source, destination, selector, username, password) + " message(s) moved");
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
new file mode 100644
index 0000000..7cf1dac
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/QueuesCommand.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "queues", description = "List the JMS queues.")
+@Service
+public class QueuesCommand extends JmsConnectionCommandSupport {
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ table.column("JMS Queues");
+
+ for (String queue : getJmsService().queues(connectionFactory, username, password)) {
+ table.addRow().addContent(queue);
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/SendCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/SendCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/SendCommand.java
new file mode 100644
index 0000000..63d3f4a
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/SendCommand.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jms", name = "send", description = "Send a message to ")
+@Service
+public class SendCommand extends JmsConnectionCommandSupport {
+
+ @Argument(index = 1, name = "queue", description = "The JMS queue name", required = true, multiValued = false)
+ String queue;
+
+ @Argument(index = 2, name = "message", description = "The JMS message content", required = true, multiValued = false)
+ String message;
+
+ @Option(name = "-r", aliases = { "--replyTo" }, description = "Set the message ReplyTo", required = false, multiValued = false)
+ String replyTo;
+
+ @Override
+ public Object execute() throws Exception {
+ getJmsService().send(connectionFactory, queue, message, replyTo, username, password);
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java b/jms/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
new file mode 100644
index 0000000..b583bc4
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/TopicsCommand.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command;
+
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "jms", name = "topics", description = "List the JMS topics.")
+@Service
+public class TopicsCommand extends JmsConnectionCommandSupport {
+
+ @Override
+ public Object execute() throws Exception {
+ ShellTable table = new ShellTable();
+
+ table.column("JMS Topics");
+
+ for (String topic : getJmsService().topics(connectionFactory, username, password)) {
+ table.addRow().addContent(topic);
+ }
+
+ table.print(System.out);
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java b/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
new file mode 100644
index 0000000..c33ff62
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesFileNameCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Completer on the JMS connection factory file names.
+ */
+@Service
+public class ConnectionFactoriesFileNameCompleter implements Completer {
+
+ @Reference
+ private JmsService jmsService;
+
+ @Override
+ public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (String connectionFactory : jmsService.connectionFactoryFileNames()) {
+ delegate.getStrings().add(connectionFactory.replace("connectionfactory-", "").replace(".xml", ""));
+ }
+ } catch (Exception e) {
+ // nothing to do
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ public JmsService getJmsService() {
+ return jmsService;
+ }
+
+ public void setJmsService(JmsService jmsService) {
+ this.jmsService = jmsService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java b/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
new file mode 100644
index 0000000..98f97b3
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/command/completers/ConnectionFactoriesNameCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.jms.JmsService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Completer on the JMS connection factories name.
+ */
+@Service
+public class ConnectionFactoriesNameCompleter implements Completer {
+
+ @Reference
+ private JmsService jmsService;
+
+ @Override
+ public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ try {
+ for (String connectionFactory : jmsService.connectionFactories()) {
+ delegate.getStrings().add(connectionFactory);
+ }
+ } catch (Exception e) {
+ // nothing to do
+ }
+ return delegate.complete(session, commandLine, candidates);
+ }
+
+ public JmsService getJmsService() {
+ return jmsService;
+ }
+
+ public void setJmsService(JmsService jmsService) {
+ this.jmsService = jmsService;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0f53437c/jms/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
----------------------------------------------------------------------
diff --git a/jms/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java b/jms/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
new file mode 100644
index 0000000..ecace89
--- /dev/null
+++ b/jms/src/main/java/org/apache/karaf/jms/internal/JmsConnector.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.jms.internal;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.JMSException;
+import javax.jms.Session;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class JmsConnector implements Closeable {
+ private BundleContext bc;
+ private ServiceReference<ConnectionFactory> reference;
+ private Connection connection;
+ private Session session;
+ private String connectionFactoryName;
+ private String username;
+ private String password;
+
+ public JmsConnector(BundleContext bc, String connectionFactoryName, String username, String password) throws JMSException {
+ this.bc = bc;
+ this.connectionFactoryName = connectionFactoryName;
+ this.username = username;
+ this.password = password;
+ }
+
+ private ServiceReference<ConnectionFactory> lookupConnectionFactory(String name) {
+ Collection<ServiceReference<ConnectionFactory>> references;
+ try {
+ references = bc.getServiceReferences(ConnectionFactory.class, "(|(osgi.jndi.service.name=" + name + ")(name=" + name + ")(service.id=" + name + "))");
+ } catch (InvalidSyntaxException e) {
+ throw new RuntimeException("Error finding connection factory service " + name, e);
+ }
+ if (references == null || references.size() == 0) {
+ throw new IllegalArgumentException("No JMS connection factory found for " + name);
+ }
+ if (references.size() > 1) {
+ throw new IllegalArgumentException("Multiple JMS connection factories found for " + name);
+ }
+ return references.iterator().next();
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (session != null) {
+ try {
+ session.close();
+ } catch (JMSException e) {
+ // Ignore
+ }
+ }
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (JMSException e) {
+ // Ignore
+ }
+ }
+ if (reference != null) {
+ bc.ungetService(reference);
+ }
+ }
+
+ public Connection connect() throws JMSException {
+ reference = this.lookupConnectionFactory(connectionFactoryName);
+ ConnectionFactory cf = (ConnectionFactory) bc.getService(reference);
+ connection = cf.createConnection(username, password);
+ connection.start();
+ return connection;
+ }
+
+ public Session createSession() throws JMSException {
+ if (connection == null) {
+ connect();
+ }
+ return session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+}
[21/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
deleted file mode 100644
index be0da05..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.osgi;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.internal.service.EventAdminListener;
-import org.apache.karaf.features.internal.service.FeatureConfigInstaller;
-import org.apache.karaf.features.internal.service.FeatureFinder;
-import org.apache.karaf.features.internal.service.BootFeaturesInstaller;
-import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
-import org.apache.karaf.features.internal.service.StateStorage;
-import org.apache.karaf.features.internal.management.FeaturesServiceMBeanImpl;
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.apache.karaf.util.tracker.SingleServiceTracker;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.url.URLStreamHandlerService;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class Activator extends BaseActivator {
-
- public static final String FEATURES_REPOS_PID = "org.apache.karaf.features.repos";
- public static final String FEATURES_SERVICE_CONFIG_FILE = "org.apache.karaf.features.cfg";
-
- private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
- private FeaturesServiceImpl featuresService;
- private SingleServiceTracker<RegionsPersistence> regionsTracker;
-
- public Activator() {
- // Special case here, as we don't want the activator to wait for current job to finish,
- // else it would forbid the features service to refresh itself
- setSchedulerStopTimeout(0);
- }
-
- @Override
- protected void doOpen() throws Exception {
- trackService(URLStreamHandlerService.class, "(url.handler.protocol=mvn)");
- trackService(ConfigurationAdmin.class);
-
- Properties configuration = new Properties();
- File configFile = new File(System.getProperty("karaf.etc"), FEATURES_SERVICE_CONFIG_FILE);
- if (configFile.isFile() && configFile.canRead()) {
- try {
- configuration.load(new FileReader(configFile));
- } catch (IOException e) {
- logger.warn("Error reading configuration file " + configFile.toString(), e);
- }
- }
- updated((Dictionary) configuration);
- }
-
- protected void doStart() throws Exception {
- ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
- URLStreamHandlerService mvnUrlHandler = getTrackedService(URLStreamHandlerService.class);
-
- if (configurationAdmin == null || mvnUrlHandler == null) {
- return;
- }
-
- FeatureFinder featureFinder = new FeatureFinder();
- Hashtable<String, Object> props = new Hashtable<String, Object>();
- props.put(Constants.SERVICE_PID, FEATURES_REPOS_PID);
- register(ManagedService.class, featureFinder, props);
-
- // TODO: region support
-// final BundleManager bundleManager = new BundleManager(bundleContext);
-// regionsTracker = new SingleServiceTracker<RegionsPersistence>(bundleContext, RegionsPersistence.class,
-// new SingleServiceTracker.SingleServiceListener() {
-// @Override
-// public void serviceFound() {
-// bundleManager.setRegionsPersistence(regionsTracker.getService());
-// }
-// @Override
-// public void serviceLost() {
-// serviceFound();
-// }
-// @Override
-// public void serviceReplaced() {
-// serviceFound();
-// }
-// });
-// regionsTracker.open();
-
-
- FeatureConfigInstaller configInstaller = new FeatureConfigInstaller(configurationAdmin);
- // TODO: honor respectStartLvlDuringFeatureStartup and respectStartLvlDuringFeatureUninstall
-// boolean respectStartLvlDuringFeatureStartup = getBoolean("respectStartLvlDuringFeatureStartup", true);
-// boolean respectStartLvlDuringFeatureUninstall = getBoolean("respectStartLvlDuringFeatureUninstall", true);
- String overrides = getString("overrides", new File(System.getProperty("karaf.etc"), "overrides.properties").toURI().toString());
- String featureResolutionRange = getString("featureResolutionRange", FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
- String bundleUpdateRange = getString("bundleUpdateRange", FeaturesServiceImpl.DEFAULT_BUNDLE_UPDATE_RANGE);
- String updateSnapshots = getString("updateSnapshots", FeaturesServiceImpl.DEFAULT_UPDATE_SNAPSHOTS);
- StateStorage stateStorage = new StateStorage() {
- @Override
- protected InputStream getInputStream() throws IOException {
- File file = bundleContext.getDataFile("FeaturesServiceState.properties");
- if (file.exists()) {
- return new FileInputStream(file);
- } else {
- return null;
- }
- }
-
- @Override
- protected OutputStream getOutputStream() throws IOException {
- File file = bundleContext.getDataFile("FeaturesServiceState.properties");
- return new FileOutputStream(file);
- }
- };
- EventAdminListener eventAdminListener;
- try {
- eventAdminListener = new EventAdminListener(bundleContext);
- } catch (Throwable t) {
- eventAdminListener = null;
- }
- featuresService = new FeaturesServiceImpl(
- bundleContext.getBundle(),
- bundleContext.getBundle(0).getBundleContext(),
- stateStorage,
- featureFinder,
- eventAdminListener,
- configInstaller,
- overrides,
- featureResolutionRange,
- bundleUpdateRange,
- updateSnapshots);
- register(FeaturesService.class, featuresService);
-
- featuresListenerTracker = new ServiceTracker<FeaturesListener, FeaturesListener>(
- bundleContext, FeaturesListener.class, new ServiceTrackerCustomizer<FeaturesListener, FeaturesListener>() {
- @Override
- public FeaturesListener addingService(ServiceReference<FeaturesListener> reference) {
- FeaturesListener service = bundleContext.getService(reference);
- featuresService.registerListener(service);
- return service;
- }
- @Override
- public void modifiedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
- }
- @Override
- public void removedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
- featuresService.unregisterListener(service);
- bundleContext.ungetService(reference);
- }
- }
- );
- featuresListenerTracker.open();
-
- String featuresRepositories = getString("featuresRepositories", "");
- String featuresBoot = getString("featuresBoot", "");
- boolean featuresBootAsynchronous = getBoolean("featuresBootAsynchronous", false);
- BootFeaturesInstaller bootFeaturesInstaller = new BootFeaturesInstaller(
- bundleContext, featuresService,
- featuresRepositories, featuresBoot, featuresBootAsynchronous);
- bootFeaturesInstaller.start();
-
- FeaturesServiceMBeanImpl featuresServiceMBean = new FeaturesServiceMBeanImpl();
- featuresServiceMBean.setBundleContext(bundleContext);
- featuresServiceMBean.setFeaturesService(featuresService);
- registerMBean(featuresServiceMBean, "type=feature");
- }
-
- protected void doStop() {
- if (regionsTracker != null) {
- regionsTracker.close();
- regionsTracker = null;
- }
- if (featuresListenerTracker != null) {
- featuresListenerTracker.close();
- featuresListenerTracker = null;
- }
- super.doStop();
- if (featuresService != null) {
- featuresService = null;
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
deleted file mode 100644
index 0d5e83d..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
-
-public class AggregateRepository implements Repository {
-
- private final Collection<Repository> repositories;
-
- public AggregateRepository(Collection<Repository> repositories) {
- this.repositories = repositories;
- }
-
- @Override
- public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
- Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
- for (Requirement requirement : requirements) {
- List<Capability> caps = new ArrayList<Capability>();
- for (Repository repository : repositories) {
- Map<Requirement, Collection<Capability>> resMap =
- repository.findProviders(Collections.singleton(requirement));
- Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
- if (res != null) {
- caps.addAll(res);
- }
- }
- result.put(requirement, caps);
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
deleted file mode 100644
index c4c0d16..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.features.internal.resolver.CapabilitySet;
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
-import org.apache.karaf.features.internal.resolver.SimpleFilter;
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-
-/**
- */
-public class BaseRepository implements Repository {
-
- protected final List<Resource> resources;
- protected final Map<String, CapabilitySet> capSets;
-
- public BaseRepository() {
- this.resources = new ArrayList<Resource>();
- this.capSets = new HashMap<String, CapabilitySet>();
- }
-
- protected void addResource(Resource resource) {
- for (Capability cap : resource.getCapabilities(null)) {
- String ns = cap.getNamespace();
- CapabilitySet set = capSets.get(ns);
- if (set == null) {
- set = new CapabilitySet(Collections.singletonList(ns));
- capSets.put(ns, set);
- }
- set.addCapability(cap);
- }
- resources.add(resource);
- }
-
- public List<Resource> getResources() {
- return resources;
- }
-
- @Override
- public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
- Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
- for (Requirement requirement : requirements) {
- CapabilitySet set = capSets.get(requirement.getNamespace());
- if (set != null) {
- SimpleFilter sf;
- if (requirement instanceof RequirementImpl) {
- sf = ((RequirementImpl) requirement).getFilter();
- } else {
- String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
- sf = (filter != null)
- ? SimpleFilter.parse(filter)
- : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
- }
- result.put(requirement, set.match(sf, true));
- } else {
- result.put(requirement, Collections.<Capability>emptyList());
- }
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
deleted file mode 100644
index 7916821..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
-
-public class CacheRepository implements Repository {
-
- private final Repository repository;
- private final Map<Requirement, Collection<Capability>> cache =
- new ConcurrentHashMap<Requirement, Collection<Capability>>();
-
- public CacheRepository(Repository repository) {
- this.repository = repository;
- }
-
- @Override
- public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
- List<Requirement> missing = new ArrayList<Requirement>();
- Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
- for (Requirement requirement : requirements) {
- Collection<Capability> caps = cache.get(requirement);
- if (caps == null) {
- missing.add(requirement);
- } else {
- result.put(requirement, caps);
- }
- }
- Map<Requirement, Collection<Capability>> newCache = repository.findProviders(missing);
- for (Requirement requirement : newCache.keySet()) {
- cache.put(requirement, newCache.get(requirement));
- result.put(requirement, newCache.get(requirement));
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java b/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
deleted file mode 100644
index 1aecef1..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.karaf.features.internal.util.JsonReader;
-
-/**
- */
-public class HttpMetadataProvider implements MetadataProvider {
-
- public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
- public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
- public static final String GZIP = "gzip";
-
- private final String url;
- private long lastModified;
- private Map<String, Map<String, String>> metadatas;
-
- public HttpMetadataProvider(String url) {
- this.url = url;
- }
-
- @Override
- public long getLastModified() {
- return lastModified;
- }
-
- @Override
- public Map<String, Map<String, String>> getMetadatas() {
- try {
- HttpURLConnection.setFollowRedirects(false);
- HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
- if (lastModified > 0) {
- con.setIfModifiedSince(lastModified);
- }
- con.setRequestProperty(HEADER_ACCEPT_ENCODING, GZIP);
- if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
- lastModified = con.getLastModified();
- InputStream is = con.getInputStream();
- if (GZIP.equals(con.getHeaderField(HEADER_CONTENT_ENCODING))) {
- is = new GZIPInputStream(is);
- }
- metadatas = verify(JsonReader.read(is));
- } else if (con.getResponseCode() != HttpURLConnection.HTTP_NOT_MODIFIED) {
- throw new IOException("Unexpected http response: "
- + con.getResponseCode() + " " + con.getResponseMessage());
- }
- return metadatas;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private Map<String, Map<String, String>> verify(Object value) {
- Map<?,?> obj = Map.class.cast(value);
- for (Map.Entry<?,?> entry : obj.entrySet()) {
- String.class.cast(entry.getKey());
- Map<?,?> child = Map.class.cast(entry.getValue());
- for (Map.Entry<?,?> ce : child.entrySet()) {
- String.class.cast(ce.getKey());
- String.class.cast(ce.getValue());
- }
- }
- return (Map<String, Map<String, String>>) obj;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
deleted file mode 100644
index 9ac54a1..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.Map;
-
-/**
- */
-public interface MetadataProvider {
-
- long getLastModified();
-
- Map<String, Map<String, String>> getMetadatas();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
deleted file mode 100644
index 2d4fbba..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.Map;
-
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.osgi.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class MetadataRepository extends BaseRepository {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(MetadataRepository.class);
-
- public MetadataRepository(MetadataProvider provider) {
- Map<String, Map<String, String>> metadatas = provider.getMetadatas();
- for (Map.Entry<String, Map<String, String>> metadata : metadatas.entrySet()) {
- try {
- Resource resource = ResourceBuilder.build(metadata.getKey(), metadata.getValue());
- addResource(resource);
- } catch (Exception e) {
- LOGGER.info("Unable to build resource for " + metadata.getKey(), e);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
deleted file mode 100644
index f289c8d..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.repository;
-
-import java.util.Collection;
-
-import org.osgi.resource.Resource;
-
-/**
- */
-public class StaticRepository extends BaseRepository {
-
- public StaticRepository(Collection<Resource> resources) {
- for (Resource resource : resources) {
- addResource(resource);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
deleted file mode 100644
index 0653398..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.Map;
-
-import org.osgi.framework.Version;
-import org.osgi.resource.Resource;
-
-/**
- */
-public abstract class BaseClause {
-
- public abstract Resource getResource();
-
- public abstract String getNamespace();
-
- public abstract Map<String, String> getDirectives();
-
- public abstract Map<String, Object> getAttributes();
-
- @Override
- public String toString() {
- return toString(getResource(), getNamespace(), getAttributes(), getDirectives());
- }
-
- public static String toString(Resource res, String namespace, Map<String, Object> attrs, Map<String, String> dirs) {
- StringBuilder sb = new StringBuilder();
- if (res != null) {
- sb.append("[").append(res).append("] ");
- }
- sb.append(namespace);
- for (String key : attrs.keySet()) {
- sb.append("; ");
- append(sb, key, attrs.get(key), true);
- }
- for (String key : dirs.keySet()) {
- sb.append("; ");
- append(sb, key, dirs.get(key), false);
- }
- return sb.toString();
- }
-
- private static void append(StringBuilder sb, String key, Object val, boolean attribute) {
- sb.append(key);
- if (val instanceof Version) {
- sb.append(":Version=");
- sb.append(val);
- } else if (val instanceof Long) {
- sb.append(":Long=");
- sb.append(val);
- } else if (val instanceof Double) {
- sb.append(":Double=");
- sb.append(val);
- } else if (val instanceof Iterable) {
- Iterable it = (Iterable) val;
- String scalar = null;
- for (Object o : it) {
- String ts;
- if (o instanceof String) {
- ts = "String";
- } else if (o instanceof Long) {
- ts = "Long";
- } else if (o instanceof Double) {
- ts = "Double";
- } else if (o instanceof Version) {
- ts = "Version";
- } else {
- throw new IllegalArgumentException("Unsupported scalar type: " + o);
- }
- if (scalar == null) {
- scalar = ts;
- } else if (!scalar.equals(ts)) {
- throw new IllegalArgumentException("Unconsistent list type for attribute " + key);
- }
- }
- sb.append(":List<").append(scalar).append(">=");
- sb.append("\"");
- boolean first = true;
- for (Object o : it) {
- if (first) {
- first = false;
- } else {
- sb.append(",");
- }
- sb.append(o.toString().replace("\"", "\\\"").replace(",", "\\,"));
- }
- sb.append("\"");
- } else {
- sb.append(attribute ? "=" : ":=");
- String s = val.toString();
- if (s.matches("[0-9a-zA-Z_\\-.]*")) {
- sb.append(s);
- } else {
- sb.append("\"").append(s.replace("\"", "\\\\")).append("\"");
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
deleted file mode 100644
index ad4cc85..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.Comparator;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.BundleNamespace;
-import org.osgi.framework.namespace.PackageNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.resource.Capability;
-
-public class CandidateComparator implements Comparator<Capability>
-{
- public int compare(Capability cap1, Capability cap2)
- {
- int c = 0;
- // Always prefer system bundle
- if (cap1 instanceof BundleCapability && !(cap2 instanceof BundleCapability)) {
- c = -1;
- } else if (!(cap1 instanceof BundleCapability) && cap2 instanceof BundleCapability) {
- c = 1;
- }
- // Compare revision capabilities.
- if ((c == 0) && cap1.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
- {
- c = ((Comparable) cap1.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE))
- .compareTo(cap2.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE));
- if (c == 0)
- {
- Version v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
- Version v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
- // Compare these in reverse order, since we want
- // highest version to have priority.
- c = compareVersions(v2, v1);
- }
- }
- // Compare package capabilities.
- else if ((c == 0) && cap1.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
- {
- c = ((Comparable) cap1.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))
- .compareTo(cap2.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
- if (c == 0)
- {
- Version v1 = (!cap1.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap1.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
- Version v2 = (!cap2.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap2.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
- // Compare these in reverse order, since we want
- // highest version to have priority.
- c = compareVersions(v2, v1);
- // if same version, rather compare on the bundle version
- if (c == 0)
- {
- v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
- v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
- // Compare these in reverse order, since we want
- // highest version to have priority.
- c = compareVersions(v2, v1);
- }
- }
- }
- // Compare feature capabilities
- else if ((c == 0) && cap1.getNamespace().equals(FeatureNamespace.FEATURE_NAMESPACE))
- {
- c = ((Comparable) cap1.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE))
- .compareTo(cap2.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE));
- if (c == 0)
- {
- Version v1 = (!cap1.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap1.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
- Version v2 = (!cap2.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
- ? Version.emptyVersion
- : (Version) cap2.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
- // Compare these in reverse order, since we want
- // highest version to have priority.
- c = compareVersions(v2, v1);
- }
- }
- return c;
- }
-
- private int compareVersions(Version v1, Version v2) {
- int c = v1.getMajor() - v2.getMajor();
- if (c != 0) {
- return c;
- }
- c = v1.getMinor() - v2.getMinor();
- if (c != 0) {
- return c;
- }
- c = v1.getMicro() - v2.getMicro();
- if (c != 0) {
- return c;
- }
- String q1 = cleanQualifierForComparison(v1.getQualifier());
- String q2 = cleanQualifierForComparison(v2.getQualifier());
- return q1.compareTo(q2);
- }
-
- private String cleanQualifierForComparison(String qualifier) {
- return qualifier.replaceAll("(redhat-[0-9]{3})([0-9]{3})", "$1-$2");
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
deleted file mode 100644
index bfe9b40..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Resource;
-
-public class CapabilityImpl extends BaseClause implements Capability {
-
- private final Resource m_resource;
- private final String m_namespace;
- private final Map<String, String> m_dirs;
- private final Map<String, Object> m_attrs;
- private final List<String> m_uses;
- private final List<List<String>> m_includeFilter;
- private final List<List<String>> m_excludeFilter;
- private final Set<String> m_mandatory;
-
- public CapabilityImpl(Capability capability) {
- this(null, capability.getNamespace(), capability.getDirectives(), capability.getAttributes());
- }
-
- public CapabilityImpl(Resource resource, String namespace,
- Map<String, String> dirs, Map<String, Object> attrs) {
- m_namespace = namespace;
- m_resource = resource;
- m_dirs = dirs;
- m_attrs = attrs;
-
- // Find all export directives: uses, mandatory, include, and exclude.
-
- List<String> uses = Collections.emptyList();
- String value = m_dirs.get(Constants.USES_DIRECTIVE);
- if (value != null) {
- // Parse these uses directive.
- StringTokenizer tok = new StringTokenizer(value, ",");
- uses = new ArrayList<String>(tok.countTokens());
- while (tok.hasMoreTokens()) {
- uses.add(tok.nextToken().trim());
- }
- }
- m_uses = uses;
-
- value = m_dirs.get(Constants.INCLUDE_DIRECTIVE);
- if (value != null) {
- List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
- m_includeFilter = new ArrayList<List<String>>(filters.size());
- for (String filter : filters) {
- List<String> substrings = SimpleFilter.parseSubstring(filter);
- m_includeFilter.add(substrings);
- }
- } else {
- m_includeFilter = null;
- }
-
- value = m_dirs.get(Constants.EXCLUDE_DIRECTIVE);
- if (value != null) {
- List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
- m_excludeFilter = new ArrayList<List<String>>(filters.size());
- for (String filter : filters) {
- List<String> substrings = SimpleFilter.parseSubstring(filter);
- m_excludeFilter.add(substrings);
- }
- } else {
- m_excludeFilter = null;
- }
-
- Set<String> mandatory = Collections.emptySet();
- value = m_dirs.get(Constants.MANDATORY_DIRECTIVE);
- if (value != null) {
- List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
- mandatory = new HashSet<String>(names.size());
- for (String name : names) {
- // If attribute exists, then record it as mandatory.
- if (m_attrs.containsKey(name)) {
- mandatory.add(name);
- }
- // Otherwise, report an error.
- else {
- throw new IllegalArgumentException("Mandatory attribute '" + name + "' does not exist.");
- }
- }
- }
- m_mandatory = mandatory;
- }
-
- public Resource getResource() {
- return m_resource;
- }
-
- public String getNamespace() {
- return m_namespace;
- }
-
- public Map<String, String> getDirectives() {
- return m_dirs;
- }
-
- public Map<String, Object> getAttributes() {
- return m_attrs;
- }
-
- public boolean isAttributeMandatory(String name) {
- return !m_mandatory.isEmpty() && m_mandatory.contains(name);
- }
-
- public List<String> getUses() {
- return m_uses;
- }
-
- public boolean isIncluded(String name) {
- if ((m_includeFilter == null) && (m_excludeFilter == null)) {
- return true;
- }
-
- // Get the class name portion of the target class.
- String className = getClassName(name);
-
- // If there are no include filters then all classes are included
- // by default, otherwise try to find one match.
- boolean included = (m_includeFilter == null);
- for (int i = 0; !included && m_includeFilter != null && i < m_includeFilter.size(); i++) {
- included = SimpleFilter.compareSubstring(m_includeFilter.get(i), className);
- }
-
- // If there are no exclude filters then no classes are excluded
- // by default, otherwise try to find one match.
- boolean excluded = false;
- for (int i = 0; (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size()); i++) {
- excluded = SimpleFilter.compareSubstring(m_excludeFilter.get(i), className);
- }
- return included && !excluded;
- }
-
- private static String getClassName(String className) {
- if (className == null) {
- className = "";
- }
- return (className.lastIndexOf('.') < 0) ? "" : className.substring(className.lastIndexOf('.') + 1);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
deleted file mode 100644
index 4c5656d..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-
-public class CapabilitySet
-{
- private final Map<String, Map<Object, Set<Capability>>> m_indices;
- private final Set<Capability> m_capSet = new HashSet<Capability>();
-
-public void dump()
-{
- for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
- {
- boolean header1 = false;
- for (Entry<Object, Set<Capability>> entry2 : entry.getValue().entrySet())
- {
- boolean header2 = false;
- for (Capability cap : entry2.getValue())
- {
- if (!header1)
- {
- System.out.println(entry.getKey() + ":");
- header1 = true;
- }
- if (!header2)
- {
- System.out.println(" " + entry2.getKey());
- header2 = true;
- }
- System.out.println(" " + cap);
- }
- }
- }
-}
-
- public CapabilitySet(List<String> indexProps)
- {
- m_indices = new TreeMap<String, Map<Object, Set<Capability>>>();
- for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++)
- {
- m_indices.put(
- indexProps.get(i), new HashMap<Object, Set<Capability>>());
- }
- }
-
- public void addCapability(Capability cap)
- {
- m_capSet.add(cap);
-
- // Index capability.
- for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
- {
- Object value = cap.getAttributes().get(entry.getKey());
- if (value != null)
- {
- if (value.getClass().isArray())
- {
- value = convertArrayToList(value);
- }
-
- Map<Object, Set<Capability>> index = entry.getValue();
-
- if (value instanceof Collection)
- {
- Collection c = (Collection) value;
- for (Object o : c)
- {
- indexCapability(index, cap, o);
- }
- }
- else
- {
- indexCapability(index, cap, value);
- }
- }
- }
- }
-
- private void indexCapability(
- Map<Object, Set<Capability>> index, Capability cap, Object capValue)
- {
- Set<Capability> caps = index.get(capValue);
- if (caps == null)
- {
- caps = new HashSet<Capability>();
- index.put(capValue, caps);
- }
- caps.add(cap);
- }
-
- public void removeCapability(Capability cap)
- {
- if (m_capSet.remove(cap))
- {
- for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
- {
- Object value = cap.getAttributes().get(entry.getKey());
- if (value != null)
- {
- if (value.getClass().isArray())
- {
- value = convertArrayToList(value);
- }
-
- Map<Object, Set<Capability>> index = entry.getValue();
-
- if (value instanceof Collection)
- {
- Collection c = (Collection) value;
- for (Object o : c)
- {
- deindexCapability(index, cap, o);
- }
- }
- else
- {
- deindexCapability(index, cap, value);
- }
- }
- }
- }
- }
-
- private void deindexCapability(
- Map<Object, Set<Capability>> index, Capability cap, Object value)
- {
- Set<Capability> caps = index.get(value);
- if (caps != null)
- {
- caps.remove(cap);
- if (caps.isEmpty())
- {
- index.remove(value);
- }
- }
- }
-
- public Set<Capability> match(SimpleFilter sf, boolean obeyMandatory)
- {
- Set<Capability> matches = match(m_capSet, sf);
- return (obeyMandatory)
- ? matchMandatory(matches, sf)
- : matches;
- }
-
- private Set<Capability> match(Set<Capability> caps, SimpleFilter sf)
- {
- Set<Capability> matches = new HashSet<Capability>();
-
- if (sf.getOperation() == SimpleFilter.MATCH_ALL)
- {
- matches.addAll(caps);
- }
- else if (sf.getOperation() == SimpleFilter.AND)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For AND we calculate the intersection of each subfilter.
- // We can short-circuit the AND operation if there are no
- // remaining capabilities.
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; (caps.size() > 0) && (i < sfs.size()); i++)
- {
- matches = match(caps, sfs.get(i));
- caps = matches;
- }
- }
- else if (sf.getOperation() == SimpleFilter.OR)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For OR we calculate the union of each subfilter.
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; i < sfs.size(); i++)
- {
- matches.addAll(match(caps, sfs.get(i)));
- }
- }
- else if (sf.getOperation() == SimpleFilter.NOT)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For OR we calculate the union of each subfilter.
- matches.addAll(caps);
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; i < sfs.size(); i++)
- {
- matches.removeAll(match(caps, sfs.get(i)));
- }
- }
- else
- {
- Map<Object, Set<Capability>> index = m_indices.get(sf.getName());
- if ((sf.getOperation() == SimpleFilter.EQ) && (index != null))
- {
- Set<Capability> existingCaps = index.get(sf.getValue());
- if (existingCaps != null)
- {
- matches.addAll(existingCaps);
- matches.retainAll(caps);
- }
- }
- else
- {
- for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
- {
- Capability cap = it.next();
- Object lhs = cap.getAttributes().get(sf.getName());
- if (lhs != null)
- {
- if (compare(lhs, sf.getValue(), sf.getOperation()))
- {
- matches.add(cap);
- }
- }
- }
- }
- }
-
- return matches;
- }
-
- public static boolean matches(Capability cap, SimpleFilter sf)
- {
- return matchesInternal(cap, sf) && matchMandatory(cap, sf);
- }
-
- private static boolean matchesInternal(Capability cap, SimpleFilter sf)
- {
- boolean matched = true;
-
- if (sf.getOperation() == SimpleFilter.MATCH_ALL)
- {
- matched = true;
- }
- else if (sf.getOperation() == SimpleFilter.AND)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For AND we calculate the intersection of each subfilter.
- // We can short-circuit the AND operation if there are no
- // remaining capabilities.
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; matched && (i < sfs.size()); i++)
- {
- matched = matchesInternal(cap, sfs.get(i));
- }
- }
- else if (sf.getOperation() == SimpleFilter.OR)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For OR we calculate the union of each subfilter.
- matched = false;
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; !matched && (i < sfs.size()); i++)
- {
- matched = matchesInternal(cap, sfs.get(i));
- }
- }
- else if (sf.getOperation() == SimpleFilter.NOT)
- {
- // Evaluate each subfilter against the remaining capabilities.
- // For OR we calculate the union of each subfilter.
- List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
- for (int i = 0; i < sfs.size(); i++)
- {
- matched = !(matchesInternal(cap, sfs.get(i)));
- }
- }
- else
- {
- matched = false;
- Object lhs = cap.getAttributes().get(sf.getName());
- if (lhs != null)
- {
- matched = compare(lhs, sf.getValue(), sf.getOperation());
- }
- }
-
- return matched;
- }
-
- private static Set<Capability> matchMandatory(
- Set<Capability> caps, SimpleFilter sf)
- {
- for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
- {
- Capability cap = it.next();
- if (!matchMandatory(cap, sf))
- {
- it.remove();
- }
- }
- return caps;
- }
-
- private static boolean matchMandatory(Capability cap, SimpleFilter sf)
- {
- if (cap instanceof CapabilityImpl) {
- for (Entry<String, Object> entry : cap.getAttributes().entrySet())
- {
- if (((CapabilityImpl) cap).isAttributeMandatory(entry.getKey())
- && !matchMandatoryAttribute(entry.getKey(), sf))
- {
- return false;
- }
- }
- } else {
- String value = cap.getDirectives().get(Constants.MANDATORY_DIRECTIVE);
- if (value != null) {
- List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
- for (Entry<String, Object> entry : cap.getAttributes().entrySet())
- {
- if (names.contains(entry.getKey())
- && !matchMandatoryAttribute(entry.getKey(), sf))
- {
- return false;
- }
- }
- }
-
- }
- return true;
- }
-
- private static boolean matchMandatoryAttribute(String attrName, SimpleFilter sf)
- {
- if ((sf.getName() != null) && sf.getName().equals(attrName))
- {
- return true;
- }
- else if (sf.getOperation() == SimpleFilter.AND)
- {
- List list = (List) sf.getValue();
- for (int i = 0; i < list.size(); i++)
- {
- SimpleFilter sf2 = (SimpleFilter) list.get(i);
- if ((sf2.getName() != null)
- && sf2.getName().equals(attrName))
- {
- return true;
- }
- }
- }
- return false;
- }
-
- private static final Class<?>[] STRING_CLASS = new Class[] { String.class };
-
- private static boolean compare(Object lhs, Object rhsUnknown, int op)
- {
- if (lhs == null)
- {
- return false;
- }
-
- // If this is a PRESENT operation, then just return true immediately
- // since we wouldn't be here if the attribute wasn't present.
- if (op == SimpleFilter.PRESENT)
- {
- return true;
- }
-
- // If the type is comparable, then we can just return the
- // result immediately.
- if (lhs instanceof Comparable)
- {
- // Spec says SUBSTRING is false for all types other than string.
- if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
- {
- return false;
- }
-
- Object rhs;
- if (op == SimpleFilter.SUBSTRING)
- {
- rhs = rhsUnknown;
- }
- else
- {
- try
- {
- rhs = coerceType(lhs, (String) rhsUnknown);
- }
- catch (Exception ex)
- {
- return false;
- }
- }
-
- switch (op)
- {
- case SimpleFilter.EQ :
- try
- {
- return (((Comparable) lhs).compareTo(rhs) == 0);
- }
- catch (Exception ex)
- {
- return false;
- }
- case SimpleFilter.GTE :
- try
- {
- return (((Comparable) lhs).compareTo(rhs) >= 0);
- }
- catch (Exception ex)
- {
- return false;
- }
- case SimpleFilter.LTE :
- try
- {
- return (((Comparable) lhs).compareTo(rhs) <= 0);
- }
- catch (Exception ex)
- {
- return false;
- }
- case SimpleFilter.APPROX :
- return compareApproximate(((Comparable) lhs), rhs);
- case SimpleFilter.SUBSTRING :
- return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
- default:
- throw new RuntimeException(
- "Unknown comparison operator: " + op);
- }
- }
- // Booleans do not implement comparable, so special case them.
- else if (lhs instanceof Boolean)
- {
- Object rhs;
- try
- {
- rhs = coerceType(lhs, (String) rhsUnknown);
- }
- catch (Exception ex)
- {
- return false;
- }
-
- switch (op)
- {
- case SimpleFilter.EQ :
- case SimpleFilter.GTE :
- case SimpleFilter.LTE :
- case SimpleFilter.APPROX :
- return (lhs.equals(rhs));
- default:
- throw new RuntimeException(
- "Unknown comparison operator: " + op);
- }
- }
-
- // If the LHS is not a comparable or boolean, check if it is an
- // array. If so, convert it to a list so we can treat it as a
- // collection.
- if (lhs.getClass().isArray())
- {
- lhs = convertArrayToList(lhs);
- }
-
- // If LHS is a collection, then call compare() on each element
- // of the collection until a match is found.
- if (lhs instanceof Collection)
- {
- for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext(); )
- {
- if (compare(iter.next(), rhsUnknown, op))
- {
- return true;
- }
- }
-
- return false;
- }
-
- // Spec says SUBSTRING is false for all types other than string.
- if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
- {
- return false;
- }
-
- // Since we cannot identify the LHS type, then we can only perform
- // equality comparison.
- try
- {
- return lhs.equals(coerceType(lhs, (String) rhsUnknown));
- }
- catch (Exception ex)
- {
- return false;
- }
- }
-
- private static boolean compareApproximate(Object lhs, Object rhs)
- {
- if (rhs instanceof String)
- {
- return removeWhitespace((String) lhs)
- .equalsIgnoreCase(removeWhitespace((String) rhs));
- }
- else if (rhs instanceof Character)
- {
- return Character.toLowerCase(((Character) lhs))
- == Character.toLowerCase(((Character) rhs));
- }
- return lhs.equals(rhs);
- }
-
- private static String removeWhitespace(String s)
- {
- StringBuffer sb = new StringBuffer(s.length());
- for (int i = 0; i < s.length(); i++)
- {
- if (!Character.isWhitespace(s.charAt(i)))
- {
- sb.append(s.charAt(i));
- }
- }
- return sb.toString();
- }
-
- private static Object coerceType(Object lhs, String rhsString) throws Exception
- {
- // If the LHS expects a string, then we can just return
- // the RHS since it is a string.
- if (lhs.getClass() == rhsString.getClass())
- {
- return rhsString;
- }
-
- // Try to convert the RHS type to the LHS type by using
- // the string constructor of the LHS class, if it has one.
- Object rhs = null;
- try
- {
- // The Character class is a special case, since its constructor
- // does not take a string, so handle it separately.
- if (lhs instanceof Character)
- {
- rhs = new Character(rhsString.charAt(0));
- }
- else
- {
- // Spec says we should trim number types.
- if ((lhs instanceof Number) || (lhs instanceof Boolean))
- {
- rhsString = rhsString.trim();
- }
- Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
- ctor.setAccessible(true);
- rhs = ctor.newInstance(new Object[] { rhsString });
- }
- }
- catch (Exception ex)
- {
- throw new Exception(
- "Could not instantiate class "
- + lhs.getClass().getName()
- + " from string constructor with argument '"
- + rhsString + "' because " + ex);
- }
-
- return rhs;
- }
-
- /**
- * This is an ugly utility method to convert an array of primitives
- * to an array of primitive wrapper objects. This method simplifies
- * processing LDAP filters since the special case of primitive arrays
- * can be ignored.
- * @param array An array of primitive types.
- * @return An corresponding array using pritive wrapper objects.
- **/
- private static List convertArrayToList(Object array)
- {
- int len = Array.getLength(array);
- List list = new ArrayList(len);
- for (int i = 0; i < len; i++)
- {
- list.add(Array.get(array, i));
- }
- return list;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
deleted file mode 100644
index e211618..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.List;
-
-import org.osgi.framework.Version;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Namespace;
-import org.osgi.resource.Resource;
-
-/**
- */
-public final class FeatureNamespace extends Namespace {
-
- public static final String FEATURE_NAMESPACE = "karaf.feature";
-
- public static final String CAPABILITY_VERSION_ATTRIBUTE = "version";
-
- /**
- * The attribute value identifying the resource
- * {@link org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE type} as an OSGi bundle.
- *
- * @see org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
- */
- public static final String TYPE_FEATURE = "karaf.feature";
-
- public static String getName(Resource resource)
- {
- List<Capability> caps = resource.getCapabilities(null);
- for (Capability cap : caps)
- {
- if (cap.getNamespace().equals(FEATURE_NAMESPACE))
- {
- return cap.getAttributes().get(FEATURE_NAMESPACE).toString();
- }
- }
- return null;
- }
-
- public static Version getVersion(Resource resource)
- {
- List<Capability> caps = resource.getCapabilities(null);
- for (Capability cap : caps)
- {
- if (cap.getNamespace().equals(FEATURE_NAMESPACE))
- {
- return (Version)
- cap.getAttributes().get(CAPABILITY_VERSION_ATTRIBUTE);
- }
- }
- return null;
- }
-
-
- private FeatureNamespace() {
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
deleted file mode 100644
index e3b0101..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.internal.util.Macro;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-/**
-*/
-public class FeatureResource extends ResourceImpl {
-
- private final Feature feature;
-
- public static Resource build(Feature feature, Conditional conditional, String featureRange, Map<String, Resource> locToRes) throws BundleException {
- Feature fcond = conditional.asFeature(feature.getName(), feature.getVersion());
- FeatureResource resource = (FeatureResource) build(fcond, featureRange, locToRes);
- for (String cond : conditional.getCondition()) {
- if (cond.startsWith("req:")) {
- cond = cond.substring("req:".length());
- List<Requirement> reqs = ResourceBuilder.parseRequirement(resource, cond);
- resource.addRequirements(reqs);
- } else {
- org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
- String[] p = cond.split("/");
- dep.setName(p[0]);
- if (p.length > 1) {
- dep.setVersion(p[1]);
- }
- addDependency(resource, dep, featureRange);
- }
- }
- org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
- dep.setName(feature.getName());
- dep.setVersion(feature.getVersion());
- addDependency(resource, dep, featureRange);
- return resource;
- }
-
- public static Resource build(Feature feature, String featureRange, Map<String, Resource> locToRes) throws BundleException {
- FeatureResource resource = new FeatureResource(feature);
- Map<String, String> dirs = new HashMap<String, String>();
- Map<String, Object> attrs = new HashMap<String, Object>();
- attrs.put(FeatureNamespace.FEATURE_NAMESPACE, feature.getName());
- attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, VersionTable.getVersion(feature.getVersion()));
- resource.addCapability(new CapabilityImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
- for (BundleInfo info : feature.getBundles()) {
- if (!info.isDependency()) {
- Resource res = locToRes.get(info.getLocation());
- if (res == null) {
- throw new IllegalStateException("Resource not found for url " + info.getLocation());
- }
- List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
- if (caps.size() != 1) {
- throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
- }
- dirs = new HashMap<String, String>();
- attrs = new HashMap<String, Object>();
- attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, caps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
- attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
- attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
- resource.addRequirement(new RequirementImpl(resource, IdentityNamespace.IDENTITY_NAMESPACE, dirs, attrs));
- }
- }
- for (Dependency dep : feature.getDependencies()) {
- addDependency(resource, dep, featureRange);
- }
- for (org.apache.karaf.features.Capability cap : feature.getCapabilities()) {
- resource.addCapabilities(ResourceBuilder.parseCapability(resource, cap.getValue()));
- }
- for (org.apache.karaf.features.Requirement req : feature.getRequirements()) {
- resource.addRequirements(ResourceBuilder.parseRequirement(resource, req.getValue()));
- }
- return resource;
- }
-
- protected static void addDependency(FeatureResource resource, Dependency dep, String featureRange) {
- Map<String, String> dirs;
- Map<String, Object> attrs;
- String name = dep.getName();
- String version = dep.getVersion();
- if (version.equals("0.0.0")) {
- version = null;
- } else if (!version.startsWith("[") && !version.startsWith("(")) {
- version = Macro.transform(featureRange, version);
- }
- dirs = new HashMap<String, String>();
- attrs = new HashMap<String, Object>();
- attrs.put(FeatureNamespace.FEATURE_NAMESPACE, name);
- if (version != null) {
- attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(version));
- }
- resource.addRequirement(new RequirementImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
- }
-
- public FeatureResource(Feature feature) {
- super(feature.getName(), FeatureNamespace.TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
- this.feature = feature;
- }
-
- public Feature getFeature() {
- return feature;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
deleted file mode 100644
index cdc00d1..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Resource;
-
-class IdentityCapability extends BaseClause implements Capability
-{
- private final Resource m_resource;
- private final Map<String, String> m_dirs;
- private final Map<String, Object> m_attrs;
-
- public IdentityCapability(Resource resource, String name, String type, Version version)
- {
- m_resource = resource;
- m_dirs = new HashMap<String, String>();
- m_attrs = new HashMap<String, Object>();
- m_attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
- m_attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, type);
- m_attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
- }
-
- public String getNamespace()
- {
- return IdentityNamespace.IDENTITY_NAMESPACE;
- }
-
- public Map<String, String> getDirectives()
- {
- return m_dirs;
- }
-
- public Map<String, Object> getAttributes()
- {
- return m_attrs;
- }
-
- public Resource getResource()
- {
- return m_resource;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
deleted file mode 100644
index a4ef775..0000000
--- a/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features.internal.resolver;
-
-import java.util.Map;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-public class RequirementImpl extends BaseClause implements Requirement {
- private final Resource m_resource;
- private final String m_namespace;
- private final SimpleFilter m_filter;
- private final boolean m_optional;
- private final Map<String, String> m_dirs;
- private final Map<String, Object> m_attrs;
-
- public RequirementImpl(
- Resource resource, String namespace,
- Map<String, String> dirs, Map<String, Object> attrs, SimpleFilter filter) {
- m_resource = resource;
- m_namespace = namespace;
- m_dirs = dirs;
- m_attrs = attrs;
- m_filter = filter;
- // Find resolution import directives.
- m_optional = Constants.RESOLUTION_OPTIONAL.equals(m_dirs.get(Constants.RESOLUTION_DIRECTIVE));
- }
-
- public RequirementImpl(
- Resource resource, String namespace,
- Map<String, String> dirs, Map<String, Object> attrs) {
- this(resource, namespace, dirs, attrs, SimpleFilter.convert(attrs));
- }
-
- public String getNamespace() {
- return m_namespace;
- }
-
- public Map<String, String> getDirectives() {
- return m_dirs;
- }
-
- public Map<String, Object> getAttributes() {
- return m_attrs;
- }
-
- public Resource getResource() {
- return m_resource;
- }
-
- public boolean matches(Capability cap) {
- return CapabilitySet.matches(cap, getFilter());
- }
-
- public boolean isOptional() {
- return m_optional;
- }
-
- public SimpleFilter getFilter() {
- return m_filter;
- }
-
-}
[24/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
new file mode 100644
index 0000000..bed8104
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import org.apache.karaf.features.TestBase;
+
+public class BundleManagerTest extends TestBase {
+
+ /*
+ @Test
+ public void testfindBundlestoRefreshWithHostToRefresh() throws Exception {
+ Bundle hostBundle = createDummyBundle(12345l, "Host", headers());
+ Bundle fragmentBundle = createDummyBundle(54321l, "fragment", headers(Constants.FRAGMENT_HOST, "Host"));
+
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ BundleManager bundleManager = new BundleManager(bundleContext);
+
+ // Host was already installed, fragment is new
+ Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(hostBundle, fragmentBundle));
+ Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(fragmentBundle));
+
+ replay(bundleContext);
+ Set<Bundle> bundles = bundleManager.findBundlesWithFragmentsToRefresh(existing, installed);
+ EasyMock.verify(bundleContext);
+
+ Assert.assertEquals(1, bundles.size());
+ Assert.assertEquals(hostBundle, bundles.iterator().next());
+ }
+
+ @Test
+ public void testfindBundlestoRefreshWithOptionalPackages() throws Exception {
+ Bundle exporterBundle = createDummyBundle(12345l, "exporter", headers(Constants.EXPORT_PACKAGE, "org.my.package"));
+ Bundle importerBundle = createDummyBundle(54321l, "importer", headers(Constants.IMPORT_PACKAGE, "org.my.package;resolution:=optional"));
+
+ BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+ BundleManager bundleManager = new BundleManager(bundleContext);
+
+ // Importer was already installed, exporter is new
+ Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(importerBundle, exporterBundle));
+ Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(exporterBundle));
+
+ replay(bundleContext);
+ Set<Bundle> bundles = bundleManager.findBundlesWithOptionalPackagesToRefresh(existing, installed);
+ EasyMock.verify(bundleContext);
+
+ Assert.assertEquals(1, bundles.size());
+ Assert.assertEquals(importerBundle, bundles.iterator().next());
+ }
+ */
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
new file mode 100644
index 0000000..b8b5fc0
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.TestBase;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link org.apache.karaf.features.internal.service.FeaturesServiceImpl}
+ */
+public class FeaturesServiceImplTest extends TestBase {
+
+ File dataFile;
+
+ @Before
+ public void setUp() throws IOException {
+ dataFile = File.createTempFile("features", null, null);
+ }
+
+ @Test
+ public void testGetFeature() throws Exception {
+ Feature transactionFeature = feature("transaction", "1.0.0");
+ final Map<String, Map<String, Feature>> features = features(transactionFeature);
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+ return features;
+ }
+ };
+ assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+ assertSame(transactionFeature, impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+ }
+
+ @Test
+ public void testGetFeatureStripVersion() throws Exception {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+ return features(feature("transaction", "1.0.0"));
+ }
+ };
+ Feature feature = impl.getFeature("transaction", " 1.0.0 ");
+ assertNotNull(feature);
+ assertSame("transaction", feature.getName());
+ }
+
+ @Test
+ public void testGetFeatureNotAvailable() throws Exception {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+ return features(feature("transaction", "1.0.0"));
+ }
+ };
+ assertNull(impl.getFeature("activemq", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+ }
+
+ @Test
+ public void testGetFeatureHighestAvailable() throws Exception {
+ final Map<String, Map<String, Feature>> features = features(
+ feature("transaction", "1.0.0"),
+ feature("transaction", "2.0.0")
+ );
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+ return features;
+ }
+ };
+ assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+ assertSame("2.0.0", impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION).getVersion());
+ }
+
+ /**
+ * This test ensures that every feature get installed only once, even if it appears multiple times in the list
+ * of transitive feature dependencies (KARAF-1600)
+ */
+ /*
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testNoDuplicateFeaturesInstallation() throws Exception {
+ final List<Feature> installed = new LinkedList<Feature>();
+ BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+ expect(bundleManager.installBundleIfNeeded(EasyMock.anyObject(String.class), EasyMock.anyInt(), EasyMock.anyObject(String.class)))
+ .andReturn(new BundleInstallerResult(createDummyBundle(1l, "", headers()), true)).anyTimes();
+ bundleManager.refreshBundles(EasyMock.anyObject(Set.class), EasyMock.anyObject(Set.class), EasyMock.anyObject(EnumSet.class));
+ EasyMock.expectLastCall();
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(bundleManager, null) {
+ // override methods which refers to bundle context to avoid mocking everything
+ @Override
+ protected boolean loadState() {
+ return true;
+ }
+
+ @Override
+ protected void saveState() {
+
+ }
+
+ @Override
+ protected void doInstallFeature(InstallationState state, Feature feature, boolean verbose) throws Exception {
+ installed.add(feature);
+
+ super.doInstallFeature(state, feature, verbose);
+ }
+
+ };
+ replay(bundleManager);
+ impl.addRepository(getClass().getResource("repo2.xml").toURI());
+ impl.installFeature("all");
+
+ // copying the features to a set to filter out the duplicates
+ Set<Feature> noduplicates = new HashSet<Feature>();
+ noduplicates.addAll(installed);
+
+ assertEquals("Every feature should only have been installed once", installed.size(), noduplicates.size());
+ }
+
+ @Test
+ public void testGetOptionalImportsOnly() {
+ BundleManager bundleManager = new BundleManager(null, 0l);
+
+ List<Clause> result = bundleManager.getOptionalImports("org.apache.karaf,org.apache.karaf.optional;resolution:=optional");
+ assertEquals("One optional import expected", 1, result.size());
+ assertEquals("org.apache.karaf.optional", result.get(0).getName());
+
+ result = bundleManager.getOptionalImports(null);
+ assertNotNull(result);
+ assertEquals("No optional imports expected", 0, result.size());
+ }
+ */
+
+ static class Storage extends StateStorage {
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ return null;
+ }
+ @Override
+ protected OutputStream getOutputStream() throws IOException {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
new file mode 100644
index 0000000..9e33ee3
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class FeaturesValidationTest {
+
+ @Test
+ public void testNs10() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
+ }
+
+ @Test
+ public void testNs10Unmarshall() throws Exception {
+ URL url = getClass().getResource("f02.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
+ public void testNs10NoName() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f03.xml").toURI());
+ }
+
+ @Test
+ public void testNs10NoNameUnmarshall() throws Exception {
+ URL url = getClass().getResource("f03.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
+ public void testNs11() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f04.xml").toURI());
+ }
+
+ @Test
+ public void testNs11Unmarshall() throws Exception {
+ URL url = getClass().getResource("f04.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
+ public void testNs11NoName() throws Exception {
+ try {
+ FeatureValidationUtil.validate(getClass().getResource("f05.xml").toURI());
+ fail("Validation should have failed");
+ } catch (Exception e) {
+ // ok
+ }
+ }
+
+ @Test
+ public void testNs12() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
+ }
+
+ @Test
+ public void testNs12Unmarshall() throws Exception {
+ URL url = getClass().getResource("f06.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+ @Test
+ public void testNs13() throws Exception {
+ FeatureValidationUtil.validate(getClass().getResource("f07.xml").toURI());
+ }
+
+ @Test
+ public void testNs13Unmarshall() throws Exception {
+ URL url = getClass().getResource("f07.xml");
+ Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+ assertNotNull(features);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
new file mode 100644
index 0000000..c4976cf
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.resolver.UriNamespace;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.BundleException;
+import org.osgi.resource.Resource;
+
+import static org.apache.karaf.features.internal.resolver.UriNamespace.getUri;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class OverridesTest {
+
+ private String bsn = "bsn";
+ private Resource b100;
+ private Resource b101;
+ private Resource b102;
+ private Resource b110;
+ private Resource c100;
+ private Resource c101;
+ private Resource c110;
+
+ @Before
+ public void setUp() throws BundleException {
+ b100 = resource("karaf-100.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.0.0")
+ .build();
+
+ b101 = resource("karaf-101.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.0.1")
+ .build();
+
+ b102 = resource("karaf-102.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.0.2")
+ .build();
+
+ b110 = resource("karaf-110.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.1.0")
+ .build();
+
+ c100 = resource("karafc-100.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.0.0")
+ .set("Bundle-Vendor", "Apache")
+ .build();
+
+ c101 = resource("karafc-101.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.0.1")
+ .set("Bundle-Vendor", "NotApache")
+ .build();
+
+ c110 = resource("karafc-110.jar")
+ .set("Bundle-SymbolicName", bsn)
+ .set("Bundle-Version", "1.1.0")
+ .set("Bundle-Vendor", "NotApache")
+ .build();
+ }
+
+ @Test
+ public void testDifferentVendors() throws IOException {
+ Map<String, Resource> map = asResourceMap(c100, c101, c110);
+ assertEquals(c100, map.get(getUri(c100)));
+ Overrides.override(map, Arrays.asList(getUri(c101), getUri(c110)));
+ assertEquals(c101, map.get(getUri(c100)));
+ }
+
+ @Test
+ public void testMatching101() throws IOException {
+ Map<String, Resource> map = asResourceMap(b100, b101, b110);
+ assertEquals(b100, map.get(getUri(b100)));
+ Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110)));
+ assertEquals(b101, map.get(getUri(b100)));
+ }
+
+ @Test
+ public void testMatching102() throws IOException {
+ Map<String, Resource> map = asResourceMap(b100, b101, b102, b110);
+ assertEquals(b100, map.get(getUri(b100)));
+ Overrides.override(map, Arrays.asList(getUri(b101), getUri(b102), getUri(b110)));
+ assertEquals(b102, map.get(getUri(b100)));
+ }
+
+ @Test
+ public void testMatchingRange() throws IOException {
+ Map<String, Resource> map = asResourceMap(b100, b101, b110);
+ assertEquals(b100, map.get(getUri(b100)));
+ Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110) + ";range=\"[1.0, 2.0)\""));
+ assertEquals(b110, map.get(getUri(b100)));
+ }
+
+ @Test
+ public void testNotMatching() throws IOException {
+ Map<String, Resource> map = asResourceMap(b100, b110);
+ assertEquals(b100, map.get(getUri(b100)));
+ Overrides.override(map, Arrays.asList(getUri(b110)));
+ assertEquals(b100, map.get(getUri(b100)));
+ }
+
+ @Test
+ public void testLoadOverrides() {
+ Set<String> overrides = Overrides.loadOverrides(getClass().getResource("overrides.properties").toExternalForm());
+ assertEquals(2, overrides.size());
+
+ Clause karafAdminCommand = null;
+ Clause karafAdminCore = null;
+ for (Clause clause : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
+ if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X")) {
+ karafAdminCommand = clause;
+ }
+ if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X")) {
+ karafAdminCore = clause;
+ }
+ }
+ assertNotNull("Missing admin.command bundle override", karafAdminCommand);
+ assertNotNull("Missing admin.core bundle override", karafAdminCore);
+ assertNotNull("Missing range on admin.core override", karafAdminCore.getAttribute(Overrides.OVERRIDE_RANGE));
+ }
+
+ /**
+ * Copies the content of {@link java.io.InputStream} to {@link java.io.OutputStream}.
+ *
+ * @param input
+ * @param output
+ * @throws java.io.IOException
+ */
+ private void copy(final InputStream input, final OutputStream output) throws IOException {
+ byte[] buffer = new byte[1024 * 16];
+ int n;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ output.flush();
+ }
+ input.close();
+ output.close();
+ }
+
+ static Builder resource(String uri) {
+ return new Builder(uri);
+ }
+
+ static Map<String, Resource> asResourceMap(Resource... resources) {
+ Map<String, Resource> map = new HashMap<String, Resource>();
+ for (Resource resource : resources) {
+ map.put(getUri(resource), resource);
+ }
+ return map;
+ }
+
+ static class Builder {
+ String uri;
+ Map<String,String> headers = new HashMap<String,String>();
+ Builder(String uri) {
+ this.uri = uri;
+ this.headers.put("Bundle-ManifestVersion", "2");
+ }
+ Builder set(String key, String value) {
+ this.headers.put(key, value);
+ return this;
+ }
+ Resource build() throws BundleException {
+ return ResourceBuilder.build(uri, headers);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
new file mode 100644
index 0000000..814c722
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="karaf-2.0.0">
+ <feature name="spring" version="3.0.3.RELEASE">
+ <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-asm/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-expression/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-beans/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-aop/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-context/3.0.3.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/3.0.3.RELEASE</bundle>
+ </feature>
+ <feature name="spring-dm" version="1.2.0">
+ <feature version="3.0.3.RELEASE">spring</feature>
+ <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.0</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.0</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.0</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.0</bundle>
+ <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.0.0</bundle>
+ </feature>
+ <feature name="wrapper" version="2.0.0">
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.0.0</bundle>
+ </feature>
+ <feature name="obr" version="2.0.0">
+ <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.0.0</bundle>
+ <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.0.0</bundle>
+ </feature>
+ <feature name="http" version="2.0.0">
+ <config name="org.ops4j.pax.web">
+ org.osgi.service.http.port=8181
+ </config>
+ <bundle>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
+ <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jetty-bundle/6.1.22_1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-api/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-spi/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/0.7.2</bundle>
+ </feature>
+ <feature name="war" version="2.0.0">
+ <feature version="2.0.0">http</feature>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/0.7.2</bundle>
+ <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.1.3</bundle>
+ <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.war/2.0.0</bundle>
+ </feature>
+ <feature name="webconsole" version="2.0.0">
+ <feature version="2.0.0">http</feature>
+ <config name="org.apache.karaf.webconsole">
+ realm=karaf
+ </config>
+ <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.2</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.0.0</bundle>
+ <bundle>mvn:org.apache.felix/org.apache.felix.webconsole/3.1.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.0.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.0.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.0.0</bundle>
+ </feature>
+ <feature name="ssh" version="2.0.0">
+ <config name="org.apache.karaf.shell.ssh">
+ sshPort=8101
+ sshHost=0.0.0.0
+ sshRealm=karaf
+ </config>
+ <bundle>mvn:org.apache.mina/mina-core/2.0.0-RC1</bundle>
+ <bundle>mvn:org.apache.sshd/sshd-core/0.4.0</bundle>
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.0.0</bundle>
+ </feature>
+ <feature name="management" version="2.0.0">
+ <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.0.0</bundle>
+ <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.1-r964701</bundle>
+ <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.1-r964701</bundle>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
new file mode 100644
index 0000000..1578faa
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="karaf-2.2.0" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ </feature>
+ <feature name="spring-web" version="2.5.6.SEC02" resolver="(obr)">
+ <feature version="2.5.6.SEC02">spring</feature>
+ <feature version="2.2.0">http</feature>
+ <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-webmvc/2.5.6.SEC02</bundle>
+ </feature>
+ <feature name="spring" version="3.0.5.RELEASE" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-asm/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-expression/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-beans/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-aop/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-context/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/3.0.5.RELEASE</bundle>
+ </feature>
+ <feature name="spring-web" version="3.0.5.RELEASE" resolver="(obr)">
+ <feature version="3.0.5.RELEASE">spring</feature>
+ <feature version="2.2.0">http</feature>
+ <bundle>mvn:org.springframework/spring-web/3.0.5.RELEASE</bundle>
+ <bundle>mvn:org.springframework/spring-webmvc/3.0.5.RELEASE</bundle>
+ </feature>
+ <feature name="spring-dm" version="1.2.1" resolver="(obr)">
+ <feature version="[2.5.6,4)">spring</feature>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.1</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.1</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.1</bundle>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.1</bundle>
+ <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.2.0</bundle>
+ </feature>
+ <feature name="spring-dm-web" version="1.2.1" resolver="(obr)">
+ <feature version="1.2.1">spring-dm</feature>
+ <feature version="[2.5.6,4)">spring-web</feature>
+ <feature version="2.2.0">http</feature>
+ <bundle>mvn:org.springframework.osgi/spring-osgi-web/1.2.1</bundle>
+ </feature>
+ <feature name="wrapper" version="2.2.0">
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.2.0</bundle>
+ </feature>
+ <feature name="obr" version="2.2.0">
+ <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.2.0</bundle>
+ <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.2.0</bundle>
+ </feature>
+ <feature name="config" version="2.2.0">
+ <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.config/2.2.0</bundle>
+ </feature>
+ <feature name="jetty" version="7.2.2.v20101205" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.asm/3.3_1</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-util/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-io/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-http/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-continuation/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-server/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-security/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-servlet/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-xml/7.2.2.v20101205</bundle>
+ </feature>
+ <feature name="jetty-jaas" version="7.2.2.v20101205" resolver="(obr)">
+ <feature version="[7.0,8.0)">jetty</feature>
+ <bundle dependency='true'>mvn:javax.mail/mail/1.4.3</bundle>
+ <bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-webapp/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-jndi/7.2.2.v20101205</bundle>
+ <bundle>mvn:org.eclipse.jetty/jetty-plus/7.2.2.v20101205</bundle>
+ </feature>
+ <feature name="http" version="2.2.0" resolver="(obr)">
+ <configfile finalname="/etc/jetty.xml">mvn:org.apache.karaf/apache-karaf/2.2.0/xml/jettyconfig</configfile>
+ <config name="org.ops4j.pax.web">
+ org.osgi.service.http.port=8181
+ javax.servlet.context.tempdir=${karaf.data}/pax-web-jsp
+ org.ops4j.pax.web.config.file=${karaf.etc}/jetty.xml
+ </config>
+ <feature version="[7.0,8.0)">jetty</feature>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-api/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-spi/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/1.0.1</bundle>
+ </feature>
+ <feature name="war" version="2.2.0" resolver="(obr)">
+ <config name="org.ops4j.pax.url.war">
+ org.ops4j.pax.url.war.importPaxLoggingPackages=true
+ </config>
+ <feature>http</feature>
+ <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.web/2.2.0</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.web/pax-web-deployer/1.0.1</bundle>
+ <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.2.5</bundle>
+ </feature>
+ <feature name="kar" version="2.2.0">
+ <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/2.2.0</bundle>
+ </feature>
+ <feature name="webconsole-base" version="2.2.0">
+ <config name="org.apache.karaf.webconsole">
+ realm=karaf
+ </config>
+ <feature>http</feature>
+ <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.4</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.2.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.console/2.2.0</bundle>
+ </feature>
+ <feature name="webconsole" version="2.2.0">
+ <feature version="2.2.0">webconsole-base</feature>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.2.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.2.0</bundle>
+ <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.2.0</bundle>
+ <bundle>mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/1.0.2</bundle>
+ </feature>
+ <feature name="ssh" version="2.2.0">
+ <config name="org.apache.karaf.shell">
+ sshPort=8101
+ sshHost=0.0.0.0
+ sshRealm=karaf
+ hostKey=${karaf.etc}/host.key
+ </config>
+ <bundle dependency='true'>mvn:org.apache.mina/mina-core/2.0.1</bundle>
+ <bundle dependency='true'>mvn:org.apache.sshd/sshd-core/0.5.0</bundle>
+ <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.2.0</bundle>
+ </feature>
+ <feature name="management" version="2.2.0">
+ <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.2.0</bundle>
+ <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.3</bundle>
+ <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.3</bundle>
+ </feature>
+ <feature name="eventadmin" version="2.2.0">
+ <bundle start-level='30'>mvn:org.apache.felix/org.apache.felix.eventadmin/1.2.8</bundle>
+ </feature>
+ <feature name="jasypt-encryption" version="2.2.0" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/1.3_3</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/2.4_4</bundle>
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1</bundle>
+ <bundle>mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.jasypt/2.2.0</bundle>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
new file mode 100644
index 0000000..c058095
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
new file mode 100644
index 0000000..85f28ad
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ </feature>
+</features>
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
new file mode 100644
index 0000000..15d84e2
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ </feature>
+</features>
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
new file mode 100644
index 0000000..51e78f1
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ <conditional>
+ <condition>http</condition>
+ <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+ </conditional>
+ <conditional>
+ <condition>req:osgi.ee;filter:="(&(osgi.ee=JavaSE)(!(version>=1.7)))"</condition>
+ <bundle start="true" start-level="30">mvn:org.apache.mina/mina-core/${mina.version}</bundle>
+ </conditional>
+ </feature>
+</features>
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
new file mode 100644
index 0000000..5b7dd90
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+ <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+ <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
+ <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+ <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+ <conditional>
+ <condition>http</condition>
+ <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+ </conditional>
+ <capability>
+ service-reference;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
+ </capability>
+ </feature>
+</features>
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties b/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
new file mode 100644
index 0000000..d34fa7e
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
@@ -0,0 +1,23 @@
+
+################################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+################################################################################
+
+# Sample etc/overrides.properties file for testing purposes
+mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X
+mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X;range=[2.3.0,2.5)
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
new file mode 100644
index 0000000..5fd51d0
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
@@ -0,0 +1,41 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="repo2">
+ <feature name="common">
+ <bundle>b1</bundle>
+ </feature>
+ <feature name="f1">
+ <feature>common</feature>
+ <bundle>b2</bundle>
+ </feature>
+ <feature name="f2">
+ <feature>common</feature>
+ <feature>f1</feature>
+ <bundle>b3</bundle>
+ </feature>
+ <feature name="f3">
+ <feature>f1</feature>
+ <feature>f2</feature>
+ <bundle>b4</bundle>
+ </feature>
+ <feature name="all">
+ <feature>f1</feature>
+ <feature>f2</feature>
+ <feature>f3</feature>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo1.xml b/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
new file mode 100644
index 0000000..641ef12
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+ <repository>urn:r1</repository>
+ <feature name="f1" region="foo">
+ <config name="c1">
+ k=v
+ </config>
+ <bundle>b1</bundle>
+ <bundle>b2</bundle>
+ </feature>
+ <feature name="f2">
+ <feature>f1</feature>
+ <bundle>b3</bundle>
+ </feature>
+ <feature name="f3">
+ <configfile finalname="cf1" override="true">cfloc</configfile>
+ <bundle>b4</bundle>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo2.xml b/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
new file mode 100644
index 0000000..f5e96ae
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+ <repository>
+ urn:r1
+ </repository>
+ <feature name="f1" region="foo">
+ <config name="c1">
+ k=v
+ </config>
+ <bundle>b1</bundle>
+ <bundle>b2</bundle>
+ </feature>
+ <feature name="f2">
+ <feature>f1</feature>
+ <bundle>b3</bundle>
+ </feature>
+ <feature name="f3">
+ <configfile finalname="cf1" override="true">cfloc</configfile>
+ <bundle>b4</bundle>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo3.xml b/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
new file mode 100644
index 0000000..ffe08ed
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+ <feature name="f1">
+ <capability>
+ cap
+ </capability>
+ <requirement>
+ req
+ </requirement>
+ </feature>
+</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/pom.xml
----------------------------------------------------------------------
diff --git a/features/pom.xml b/features/pom.xml
index d722ada..8cfede1 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -29,124 +29,13 @@
</parent>
<groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.core</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: Features :: Core</name>
- <description>This bundle is the core implementation of the Karaf features support.</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- <scope>provided</scope>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.utils</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf</groupId>
- <artifactId>org.apache.karaf.util</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.resolver</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.core</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-jdk14</artifactId>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>org.ops4j.pax.tinybundles</groupId>
- <artifactId>tinybundles</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>${project.basedir}/src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Export-Package>
- org.apache.karaf.features;
- org.apache.karaf.features.command;
- org.apache.karaf.features.command.completers;
- org.apache.karaf.features.management;
- org.apache.karaf.features.management.codec;
- -noimport:=true
- </Export-Package>
- <Provide-Capability>
- service-reference;effective:=active;objectClass=org.apache.karaf.features.FeaturesService
- </Provide-Capability>
- <Private-Package>
- org.apache.karaf.features.internal.*,
- org.apache.felix.resolver,
- org.apache.felix.utils.version,
- org.apache.felix.utils.manifest,
- org.apache.karaf.util,
- org.apache.karaf.util.collections,
- org.apache.karaf.util.json,
- org.apache.karaf.util.tracker,
- org.osgi.service.resolver,
- org.osgi.service.repository
- </Private-Package>
- <Embed-Dependency>
- org.apache.karaf.util;inline="org/apache/karaf/util/XmlUtils*.class"
- </Embed-Dependency>
- <Bundle-Activator>
- org.apache.karaf.features.internal.osgi.Activator
- </Bundle-Activator>
- <Karaf-Commands>org.apache.karaf.features.command.*</Karaf-Commands>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <artifactId>features</artifactId>
+ <packaging>pom</packaging>
+ <name>Apache Karaf :: Features</name>
+
+ <modules>
+ <module>core</module>
+ <module>command</module>
+ </modules>
</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/BootFinished.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/BootFinished.java b/features/src/main/java/org/apache/karaf/features/BootFinished.java
deleted file mode 100644
index aa72248..0000000
--- a/features/src/main/java/org/apache/karaf/features/BootFinished.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-/**
- * Marker interface for a service that announces when the karaf boot is finished
- */
-public interface BootFinished {
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/BundleInfo.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/BundleInfo.java b/features/src/main/java/org/apache/karaf/features/BundleInfo.java
deleted file mode 100644
index 97a541f..0000000
--- a/features/src/main/java/org/apache/karaf/features/BundleInfo.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-/**
- * A bundle info holds info about a Bundle.
- */
-public interface BundleInfo {
-
- String getLocation();
-
- int getStartLevel();
-
- boolean isStart();
-
- boolean isDependency();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Capability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Capability.java b/features/src/main/java/org/apache/karaf/features/Capability.java
deleted file mode 100644
index d329708..0000000
--- a/features/src/main/java/org/apache/karaf/features/Capability.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-public interface Capability {
-
- String getValue();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Conditional.java b/features/src/main/java/org/apache/karaf/features/Conditional.java
deleted file mode 100644
index fdc9261..0000000
--- a/features/src/main/java/org/apache/karaf/features/Conditional.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.List;
-import java.util.Map;
-
-public interface Conditional {
-
- List<String> getCondition();
-
- List<Dependency> getDependencies();
-
- List<BundleInfo> getBundles();
-
- Map<String, Map<String, String>> getConfigurations();
-
- List<ConfigFileInfo> getConfigurationFiles();
-
- Feature asFeature(String name, String version);
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java b/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
deleted file mode 100644
index 960fb31..0000000
--- a/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-public interface ConfigFileInfo {
-
- String getLocation();
-
- String getFinalname();
-
- boolean isOverride();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Dependency.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Dependency.java b/features/src/main/java/org/apache/karaf/features/Dependency.java
deleted file mode 100644
index cafdd92..0000000
--- a/features/src/main/java/org/apache/karaf/features/Dependency.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-
-
-package org.apache.karaf.features;
-
-public interface Dependency {
-
- String getName();
-
- String getVersion();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/EventConstants.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/EventConstants.java b/features/src/main/java/org/apache/karaf/features/EventConstants.java
deleted file mode 100644
index f83f185..0000000
--- a/features/src/main/java/org/apache/karaf/features/EventConstants.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-/**
- * Constants for EventAdmin events
- */
-public final class EventConstants {
-
- public static final String TYPE = "type";
- public static final String EVENT = "event";
- public static final String TIMESTAMP = "timestamp";
-
- public static final String FEATURE_NAME = "name";
- public static final String FEATURE_VERSION = "version";
-
- public static final String REPOSITORY_NAME = "name";
- public static final String REPOSITORY_URI = "uri";
-
- public static final String TOPIC_EVENTS = "org/apache/karaf/features";
- public static final String TOPIC_FEATURES_INSTALLED = TOPIC_EVENTS + "/features/INSTALLED";
- public static final String TOPIC_FEATURES_UNINSTALLED = TOPIC_EVENTS + "/features/UNINSTALLED";
- public static final String TOPIC_REPOSITORY_ADDED = TOPIC_EVENTS + "/repositories/ADDED";
- public static final String TOPIC_REPOSITORY_REMOVED = TOPIC_EVENTS + "/repositories/REMOVED";
-
- private EventConstants() {
- // non-instantiable class
- }
-
-
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/Feature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Feature.java b/features/src/main/java/org/apache/karaf/features/Feature.java
deleted file mode 100644
index 2f9f001..0000000
--- a/features/src/main/java/org/apache/karaf/features/Feature.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * A feature is a list of bundles associated identified by its name.
- */
-public interface Feature {
-
- public static String DEFAULT_INSTALL_MODE = "auto";
-
- String getId();
-
- String getName();
-
- String getDescription();
-
- String getDetails();
-
- String getVersion();
-
- boolean hasVersion();
-
- String getResolver();
-
- String getInstall();
-
- List<Dependency> getDependencies();
-
- List<BundleInfo> getBundles();
-
- Map<String, Map<String, String>> getConfigurations();
-
- List<ConfigFileInfo> getConfigurationFiles();
-
- List<? extends Conditional> getConditional();
-
- int getStartLevel();
-
- String getRegion();
-
- List<? extends Capability> getCapabilities();
-
- List<? extends Requirement> getRequirements();
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeatureEvent.java b/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
deleted file mode 100644
index 516c988..0000000
--- a/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import java.util.EventObject;
-
-public class FeatureEvent extends EventObject {
-
- public static enum EventType {
- FeatureInstalled,
- FeatureUninstalled
- }
-
- private final EventType type;
- private final Feature feature;
- private final boolean replay;
-
- public FeatureEvent(Feature feature, EventType type, boolean replay) {
- super(feature);
- this.type = type;
- this.feature = feature;
- this.replay = replay;
- }
-
- public EventType getType() {
- return type;
- }
-
- public Feature getFeature() {
- return feature;
- }
-
- public boolean isReplay() {
- return replay;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesListener.java b/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
deleted file mode 100644
index 69f68c6..0000000
--- a/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-public interface FeaturesListener {
-
- void featureEvent(FeatureEvent event);
-
- void repositoryEvent(RepositoryEvent event);
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java b/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
deleted file mode 100644
index 282ff71..0000000
--- a/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.karaf.features;
-
-import javax.xml.namespace.QName;
-
-/**
- * Provides features XML/XSD constants.
- */
-public interface FeaturesNamespaces {
-
- String URI_0_0_0 = "";
- String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0";
- String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0";
- String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0";
- String URI_1_3_0 = "http://karaf.apache.org/xmlns/features/v1.3.0";
-
- String URI_CURRENT = URI_1_3_0;
-
- QName FEATURES_0_0_0 = new QName("features");
- QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
- QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features");
- QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features");
- QName FEATURES_1_3_0 = new QName(URI_1_3_0, "features");
-
- QName FEATURES_CURRENT = FEATURES_1_3_0;
-
-}
[12/33] git commit: [KARAF-2852] Remove obsolete artifacts references
Posted by gn...@apache.org.
[KARAF-2852] Remove obsolete artifacts references
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/286939f9
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/286939f9
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/286939f9
Branch: refs/heads/master
Commit: 286939f9bb41391c06dbbf7a69ecf810d726086d
Parents: 1306af5
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 11:15:19 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:03 2014 +0200
----------------------------------------------------------------------
assemblies/features/standard/pom.xml | 67 +---------------------
pom.xml | 95 -------------------------------
2 files changed, 1 insertion(+), 161 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/286939f9/assemblies/features/standard/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/pom.xml b/assemblies/features/standard/pom.xml
index dda4142..e693f54 100644
--- a/assemblies/features/standard/pom.xml
+++ b/assemblies/features/standard/pom.xml
@@ -51,21 +51,11 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.instance</groupId>
<artifactId>org.apache.karaf.instance.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.instance</groupId>
- <artifactId>org.apache.karaf.instance.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.jaas</groupId>
<artifactId>org.apache.karaf.jaas.modules</artifactId>
<scope>provided</scope>
@@ -86,31 +76,16 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.diagnostic</groupId>
- <artifactId>org.apache.karaf.diagnostic.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.log</groupId>
<artifactId>org.apache.karaf.log.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.log</groupId>
- <artifactId>org.apache.karaf.log.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.service</groupId>
<artifactId>org.apache.karaf.service.core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.service</groupId>
- <artifactId>org.apache.karaf.service.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.core</artifactId>
<scope>provided</scope>
@@ -144,11 +119,6 @@
<artifactId>org.apache.karaf.wrapper.core</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.wrapper</groupId>
- <artifactId>org.apache.karaf.wrapper.command</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- obr deps -->
<dependency>
@@ -177,11 +147,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.obr</groupId>
- <artifactId>org.apache.karaf.obr.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-lifecycle</artifactId>
<scope>provided</scope>
@@ -209,11 +174,6 @@
<artifactId>org.apache.karaf.config.core</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.config</groupId>
- <artifactId>org.apache.karaf.config.command</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- region deps -->
<dependency>
@@ -223,12 +183,7 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.persist</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.command</artifactId>
+ <artifactId>org.apache.karaf.region.core</artifactId>
<scope>provided</scope>
</dependency>
@@ -270,11 +225,6 @@
<artifactId>org.apache.karaf.package.core</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.package</groupId>
- <artifactId>org.apache.karaf.package.command</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- http deps -->
<dependency>
@@ -302,11 +252,6 @@
<artifactId>org.apache.karaf.http.core</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.http</groupId>
- <artifactId>org.apache.karaf.http.command</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- http-whiteboard deps -->
<dependency>
@@ -362,11 +307,6 @@
<artifactId>org.apache.karaf.web.core</artifactId>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.web</groupId>
- <artifactId>org.apache.karaf.web.command</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- kar deps -->
<dependency>
@@ -375,11 +315,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>org.apache.karaf.kar</groupId>
- <artifactId>org.apache.karaf.kar.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
<groupId>org.apache.karaf.deployer</groupId>
<artifactId>org.apache.karaf.deployer.kar</artifactId>
<scope>provided</scope>
http://git-wip-us.apache.org/repos/asf/karaf/blob/286939f9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index d5f8423..48c5951 100644
--- a/pom.xml
+++ b/pom.xml
@@ -385,11 +385,6 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.bundle</groupId>
- <artifactId>org.apache.karaf.bundle.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.bundle</groupId>
<artifactId>org.apache.karaf.bundle.springstate</artifactId>
<version>${project.version}</version>
</dependency>
@@ -404,55 +399,30 @@
<artifactId>org.apache.karaf.package.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.package</groupId>
- <artifactId>org.apache.karaf.package.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.http</groupId>
<artifactId>org.apache.karaf.http.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.http</groupId>
- <artifactId>org.apache.karaf.http.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.jdbc</groupId>
<artifactId>org.apache.karaf.jdbc.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.jdbc</groupId>
- <artifactId>org.apache.karaf.jdbc.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.jms</groupId>
<artifactId>org.apache.karaf.jms.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.jms</groupId>
- <artifactId>org.apache.karaf.jms.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.jndi</groupId>
<artifactId>org.apache.karaf.jndi.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.jndi</groupId>
- <artifactId>org.apache.karaf.jndi.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.service</groupId>
@@ -461,11 +431,6 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.service</groupId>
- <artifactId>org.apache.karaf.service.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.service</groupId>
<artifactId>org.apache.karaf.service.guard</artifactId>
<version>${project.version}</version>
</dependency>
@@ -475,22 +440,12 @@
<artifactId>org.apache.karaf.log.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.log</groupId>
- <artifactId>org.apache.karaf.log.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.config</groupId>
<artifactId>org.apache.karaf.config.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.config</groupId>
- <artifactId>org.apache.karaf.config.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.deployer</groupId>
@@ -520,22 +475,12 @@
<dependency>
<groupId>org.apache.karaf.kar</groupId>
- <artifactId>org.apache.karaf.kar.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.kar</groupId>
<artifactId>org.apache.karaf.kar.core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.obr</groupId>
- <artifactId>org.apache.karaf.obr.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.obr</groupId>
<artifactId>org.apache.karaf.obr.core</artifactId>
<version>${project.version}</version>
</dependency>
@@ -564,11 +509,6 @@
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.obr</artifactId>
<version>${project.version}</version>
</dependency>
@@ -578,52 +518,27 @@
<artifactId>org.apache.karaf.diagnostic.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.diagnostic</groupId>
- <artifactId>org.apache.karaf.diagnostic.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.instance</groupId>
<artifactId>org.apache.karaf.instance.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.instance</groupId>
- <artifactId>org.apache.karaf.instance.command</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.system</groupId>
- <artifactId>org.apache.karaf.system.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.system</groupId>
<artifactId>org.apache.karaf.system.core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.web</groupId>
- <artifactId>org.apache.karaf.web.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.web</groupId>
<artifactId>org.apache.karaf.web.core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.wrapper</groupId>
- <artifactId>org.apache.karaf.wrapper.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.wrapper</groupId>
<artifactId>org.apache.karaf.wrapper.core</artifactId>
<version>${project.version}</version>
</dependency>
@@ -633,16 +548,6 @@
<artifactId>org.apache.karaf.region.core</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.command</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.persist</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
[31/33] Revert "[KARAF-2852] Merge features/core and features/command"
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/pom.xml
----------------------------------------------------------------------
diff --git a/features/core/pom.xml b/features/core/pom.xml
new file mode 100644
index 0000000..d8a2620
--- /dev/null
+++ b/features/core/pom.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>features</artifactId>
+ <version>4.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.karaf.features.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Features :: Core</name>
+ <description>This bundle is the core implementation of the Karaf features support.</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>org.apache.karaf.util</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.resolver</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.ops4j.pax.tinybundles</groupId>
+ <artifactId>tinybundles</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.karaf.features;
+ org.apache.karaf.features.management;
+ org.apache.karaf.features.management.codec;
+ -noimport:=true
+ </Export-Package>
+ <Provide-Capability>
+ service-reference;effective:=active;objectClass=org.apache.karaf.features.FeaturesService
+ </Provide-Capability>
+ <Private-Package>
+ org.apache.karaf.features.internal.*,
+ org.apache.felix.resolver,
+ org.apache.felix.utils.version,
+ org.apache.felix.utils.manifest,
+ org.apache.karaf.util.collections,
+ org.apache.karaf.util.json,
+ org.apache.karaf.util.tracker,
+ org.osgi.service.resolver,
+ org.osgi.service.repository
+ </Private-Package>
+ <Embed-Dependency>
+ org.apache.karaf.util;inline="org/apache/karaf/util/XmlUtils*.class"
+ </Embed-Dependency>
+ <Bundle-Activator>
+ org.apache.karaf.features.internal.osgi.Activator
+ </Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/BootFinished.java b/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
new file mode 100644
index 0000000..aa72248
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+/**
+ * Marker interface for a service that announces when the karaf boot is finished
+ */
+public interface BootFinished {
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java b/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
new file mode 100644
index 0000000..97a541f
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+/**
+ * A bundle info holds info about a Bundle.
+ */
+public interface BundleInfo {
+
+ String getLocation();
+
+ int getStartLevel();
+
+ boolean isStart();
+
+ boolean isDependency();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Capability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Capability.java b/features/core/src/main/java/org/apache/karaf/features/Capability.java
new file mode 100644
index 0000000..d329708
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Capability.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+public interface Capability {
+
+ String getValue();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/Conditional.java
new file mode 100644
index 0000000..fdc9261
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Conditional.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.List;
+import java.util.Map;
+
+public interface Conditional {
+
+ List<String> getCondition();
+
+ List<Dependency> getDependencies();
+
+ List<BundleInfo> getBundles();
+
+ Map<String, Map<String, String>> getConfigurations();
+
+ List<ConfigFileInfo> getConfigurationFiles();
+
+ Feature asFeature(String name, String version);
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java b/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
new file mode 100644
index 0000000..960fb31
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+public interface ConfigFileInfo {
+
+ String getLocation();
+
+ String getFinalname();
+
+ boolean isOverride();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Dependency.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Dependency.java b/features/core/src/main/java/org/apache/karaf/features/Dependency.java
new file mode 100644
index 0000000..cafdd92
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Dependency.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+package org.apache.karaf.features;
+
+public interface Dependency {
+
+ String getName();
+
+ String getVersion();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/EventConstants.java b/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
new file mode 100644
index 0000000..f83f185
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+/**
+ * Constants for EventAdmin events
+ */
+public final class EventConstants {
+
+ public static final String TYPE = "type";
+ public static final String EVENT = "event";
+ public static final String TIMESTAMP = "timestamp";
+
+ public static final String FEATURE_NAME = "name";
+ public static final String FEATURE_VERSION = "version";
+
+ public static final String REPOSITORY_NAME = "name";
+ public static final String REPOSITORY_URI = "uri";
+
+ public static final String TOPIC_EVENTS = "org/apache/karaf/features";
+ public static final String TOPIC_FEATURES_INSTALLED = TOPIC_EVENTS + "/features/INSTALLED";
+ public static final String TOPIC_FEATURES_UNINSTALLED = TOPIC_EVENTS + "/features/UNINSTALLED";
+ public static final String TOPIC_REPOSITORY_ADDED = TOPIC_EVENTS + "/repositories/ADDED";
+ public static final String TOPIC_REPOSITORY_REMOVED = TOPIC_EVENTS + "/repositories/REMOVED";
+
+ private EventConstants() {
+ // non-instantiable class
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Feature.java b/features/core/src/main/java/org/apache/karaf/features/Feature.java
new file mode 100644
index 0000000..2f9f001
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Feature.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A feature is a list of bundles associated identified by its name.
+ */
+public interface Feature {
+
+ public static String DEFAULT_INSTALL_MODE = "auto";
+
+ String getId();
+
+ String getName();
+
+ String getDescription();
+
+ String getDetails();
+
+ String getVersion();
+
+ boolean hasVersion();
+
+ String getResolver();
+
+ String getInstall();
+
+ List<Dependency> getDependencies();
+
+ List<BundleInfo> getBundles();
+
+ Map<String, Map<String, String>> getConfigurations();
+
+ List<ConfigFileInfo> getConfigurationFiles();
+
+ List<? extends Conditional> getConditional();
+
+ int getStartLevel();
+
+ String getRegion();
+
+ List<? extends Capability> getCapabilities();
+
+ List<? extends Requirement> getRequirements();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java b/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
new file mode 100644
index 0000000..516c988
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.EventObject;
+
+public class FeatureEvent extends EventObject {
+
+ public static enum EventType {
+ FeatureInstalled,
+ FeatureUninstalled
+ }
+
+ private final EventType type;
+ private final Feature feature;
+ private final boolean replay;
+
+ public FeatureEvent(Feature feature, EventType type, boolean replay) {
+ super(feature);
+ this.type = type;
+ this.feature = feature;
+ this.replay = replay;
+ }
+
+ public EventType getType() {
+ return type;
+ }
+
+ public Feature getFeature() {
+ return feature;
+ }
+
+ public boolean isReplay() {
+ return replay;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
new file mode 100644
index 0000000..69f68c6
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+public interface FeaturesListener {
+
+ void featureEvent(FeatureEvent event);
+
+ void repositoryEvent(RepositoryEvent event);
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
new file mode 100644
index 0000000..282ff71
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Provides features XML/XSD constants.
+ */
+public interface FeaturesNamespaces {
+
+ String URI_0_0_0 = "";
+ String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0";
+ String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0";
+ String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0";
+ String URI_1_3_0 = "http://karaf.apache.org/xmlns/features/v1.3.0";
+
+ String URI_CURRENT = URI_1_3_0;
+
+ QName FEATURES_0_0_0 = new QName("features");
+ QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
+ QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features");
+ QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features");
+ QName FEATURES_1_3_0 = new QName(URI_1_3_0, "features");
+
+ QName FEATURES_CURRENT = FEATURES_1_3_0;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
new file mode 100644
index 0000000..ef3dbcf
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.net.URI;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * The service managing features repositories.
+ */
+public interface FeaturesService {
+
+ enum Option {
+ NoFailOnFeatureNotFound,
+ NoAutoRefreshManagedBundles,
+ NoAutoRefreshUnmanagedBundles,
+ NoAutoRefreshBundles,
+ NoAutoStartBundles,
+ Simulate,
+ Verbose
+ }
+
+ /**
+ * Validate repository contents.
+ *
+ * @param uri Repository uri.
+ * @throws Exception When validation fails.
+ */
+ void validateRepository(URI uri) throws Exception;
+
+ void addRepository(URI uri) throws Exception;
+
+ void addRepository(URI uri, boolean install) throws Exception;
+
+ void removeRepository(URI uri) throws Exception;
+
+ void removeRepository(URI uri, boolean uninstall) throws Exception;
+
+ void restoreRepository(URI uri) throws Exception;
+
+ Repository[] listRequiredRepositories() throws Exception;
+
+ Repository[] listRepositories() throws Exception;
+
+ Repository getRepository(String repoName) throws Exception;
+
+ void installFeature(String name) throws Exception;
+
+ void installFeature(String name, EnumSet<Option> options) throws Exception;
+
+ void installFeature(String name, String version) throws Exception;
+
+ void installFeature(String name, String version, EnumSet<Option> options) throws Exception;
+
+ void installFeature(Feature f, EnumSet<Option> options) throws Exception;
+
+ void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+
+ void uninstallFeature(String name, EnumSet<Option> options) throws Exception;
+
+ void uninstallFeature(String name) throws Exception;
+
+ void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception;
+
+ void uninstallFeature(String name, String version) throws Exception;
+
+ void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+
+ Feature[] listFeatures() throws Exception;
+
+ Feature[] listRequiredFeatures() throws Exception;
+
+ Feature[] listInstalledFeatures() throws Exception;
+
+ boolean isRequired(Feature f);
+
+ boolean isInstalled(Feature f);
+
+ Feature getFeature(String name, String version) throws Exception;
+
+ Feature getFeature(String name) throws Exception;
+
+ void refreshRepository(URI uri) throws Exception;
+
+ public URI getRepositoryUriFor(String name, String version);
+
+ public String[] getRepositoryNames();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java b/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
new file mode 100644
index 0000000..96ca7da
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.karaf.features;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+public interface RegionsPersistence {
+ void install(Bundle b, String regionName) throws BundleException;
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Repository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Repository.java b/features/core/src/main/java/org/apache/karaf/features/Repository.java
new file mode 100644
index 0000000..3ea12ec
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Repository.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.io.IOException;
+import java.net.URI;
+
+/**
+ * A repository of features.
+ */
+public interface Repository {
+
+ String getName() throws IOException;
+
+ URI getURI();
+
+ URI[] getRepositories() throws Exception;
+
+ Feature[] getFeatures() throws Exception;
+
+ boolean isValid();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java b/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
new file mode 100644
index 0000000..68f287b
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.EventObject;
+
+public class RepositoryEvent extends EventObject {
+
+ public static enum EventType {
+ RepositoryAdded,
+ RepositoryRemoved,
+ }
+
+ private final EventType type;
+ private final Repository repository;
+ private final boolean replay;
+
+ public RepositoryEvent(Repository repository, EventType type, boolean replay) {
+ super(repository);
+ this.type = type;
+ this.repository = repository;
+ this.replay = replay;
+ }
+
+ public EventType getType() {
+ return type;
+ }
+
+ public Repository getRepository() {
+ return repository;
+ }
+
+ public boolean isReplay() {
+ return replay;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Requirement.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Requirement.java b/features/core/src/main/java/org/apache/karaf/features/Requirement.java
new file mode 100644
index 0000000..4446335
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Requirement.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+public interface Requirement {
+
+ String getValue();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/Resolver.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Resolver.java b/features/core/src/main/java/org/apache/karaf/features/Resolver.java
new file mode 100644
index 0000000..d2fa941
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Resolver.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features;
+
+import java.util.List;
+
+public interface Resolver {
+
+ List<BundleInfo> resolve(Feature feature) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
new file mode 100644
index 0000000..c3ac2b7
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
@@ -0,0 +1,354 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.felix.resolver.ResolverImpl;
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.repository.AggregateRepository;
+import org.apache.karaf.features.internal.repository.StaticRepository;
+import org.apache.karaf.features.internal.resolver.FeatureNamespace;
+import org.apache.karaf.features.internal.resolver.FeatureResource;
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.ResolveContextImpl;
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.resolver.ResourceImpl;
+import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
+import org.apache.karaf.features.internal.service.Overrides;
+import org.apache.karaf.features.internal.util.Macro;
+import org.apache.karaf.features.internal.util.MultiException;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.resolver.ResolveContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class DeploymentBuilder {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentBuilder.class);
+
+ public static final String REQ_PROTOCOL = "req:";
+
+ private final Collection<Repository> repositories;
+
+ private final List<org.osgi.service.repository.Repository> resourceRepos;
+
+ String featureRange = "${range;[====,====]}";
+
+ Downloader downloader;
+ ResourceImpl requirements;
+ Map<String, Resource> resources;
+ Set<Resource> optionals;
+ Map<String, StreamProvider> providers;
+
+ Set<Feature> featuresToRegister = new HashSet<Feature>();
+
+ public DeploymentBuilder(Downloader downloader,
+ Collection<Repository> repositories) {
+ this.downloader = downloader;
+ this.repositories = repositories;
+ this.resourceRepos = new ArrayList<org.osgi.service.repository.Repository>();
+ }
+
+ public void addResourceRepository(org.osgi.service.repository.Repository repository) {
+ resourceRepos.add(repository);
+ }
+
+ public Map<String, StreamProvider> getProviders() {
+ return providers;
+ }
+
+ public void setFeatureRange(String featureRange) {
+ this.featureRange = featureRange;
+ }
+
+ public Map<String, Resource> download(
+ Set<String> features,
+ Set<String> bundles,
+ Set<String> reqs,
+ Set<String> overrides,
+ Set<String> optionals)
+ throws IOException, MultiException, InterruptedException, ResolutionException, BundleException {
+ this.resources = new ConcurrentHashMap<String, Resource>();
+ this.optionals = new HashSet<Resource>();
+ this.providers = new ConcurrentHashMap<String, StreamProvider>();
+ this.requirements = new ResourceImpl("dummy", "dummy", Version.emptyVersion);
+ // First, gather all bundle resources
+ for (String feature : features) {
+ registerMatchingFeatures(feature);
+ }
+ for (String bundle : bundles) {
+ downloadAndBuildResource(bundle);
+ }
+ for (String req : reqs) {
+ buildRequirement(req);
+ }
+ for (String override : overrides) {
+ // TODO: ignore download failures for overrides
+ downloadAndBuildResource(Overrides.extractUrl(override));
+ }
+ for (String optional : optionals) {
+ downloadAndBuildResource(optional);
+ }
+ // Wait for all resources to be created
+ downloader.await();
+ // Do override replacement
+ Overrides.override(resources, overrides);
+ // Build features resources
+ for (Feature feature : featuresToRegister) {
+ Resource resource = FeatureResource.build(feature, featureRange, resources);
+ resources.put("feature:" + feature.getName() + "/" + feature.getVersion(), resource);
+ for (Conditional cond : feature.getConditional()) {
+ this.optionals.add(FeatureResource.build(feature, cond, featureRange, resources));
+ }
+ }
+ // Build requirements
+ for (String feature : features) {
+ requireFeature(feature);
+ }
+ for (String bundle : bundles) {
+ requireResource(bundle);
+ }
+ for (String req : reqs) {
+ requireResource(REQ_PROTOCOL + req);
+ }
+ return resources;
+ }
+
+ public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles) throws ResolutionException {
+ // Resolve
+ for (int i = 0; i < systemBundles.size(); i++) {
+ resources.put("system-bundle-" + i, systemBundles.get(i));
+ }
+
+ List<org.osgi.service.repository.Repository> repos = new ArrayList<org.osgi.service.repository.Repository>();
+ repos.add(new StaticRepository(resources.values()));
+ repos.addAll(resourceRepos);
+
+ ResolverImpl resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
+ ResolveContext context = new ResolveContextImpl(
+ Collections.<Resource>singleton(requirements),
+ Collections.<Resource>emptySet(),
+ new AggregateRepository(repos),
+ false);
+ Map<Resource, List<Wire>> best = resolver.resolve(context);
+
+ // TODO: we actually need to use multiple passes for conditionals
+ // TODO: but it may be optimized by passing the old wiring instead
+ // TODO: of computing everything again
+ Set<Resource> resources = new HashSet<Resource>();
+ resources.add(requirements);
+ for (Resource optional : optionals) {
+ try {
+ Set<Resource> newSet = new HashSet<Resource>(resources);
+ newSet.add(optional);
+ context = new ResolveContextImpl(
+ newSet,
+ Collections.<Resource>emptySet(),
+ new AggregateRepository(repos),
+ false);
+ best = resolver.resolve(context);
+ resources = newSet;
+ } catch (ResolutionException e) {
+ // Ignore this resource
+ }
+ }
+ return best;
+ }
+
+ public void requireFeature(String feature) throws IOException {
+ // Find name and version range
+ String[] split = feature.split("/");
+ String name = split[0].trim();
+ String version = (split.length > 1) ? split[1].trim() : null;
+ if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
+ version = Macro.transform(featureRange, version);
+ }
+ VersionRange range = version != null ? new VersionRange(version) : VersionRange.ANY_VERSION;
+ // Add requirement
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
+ attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, FeatureNamespace.TYPE_FEATURE);
+ attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, range);
+ requirements.addRequirement(
+ new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
+ Collections.<String, String>emptyMap(), attrs)
+ );
+ }
+
+ public void requireResource(String location) {
+ Resource res = resources.get(location);
+ if (res == null) {
+ throw new IllegalStateException("Could not find resource for " + location);
+ }
+ List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ if (caps.size() != 1) {
+ throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
+ }
+ Capability cap = caps.get(0);
+ // Add requirement
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
+ requirements.addRequirement(
+ new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
+ Collections.<String, String>emptyMap(), attrs));
+
+ }
+
+ public void registerMatchingFeatures(String feature) throws IOException {
+ // Find name and version range
+ String[] split = feature.split("/");
+ String name = split[0].trim();
+ String version = (split.length > 1)
+ ? split[1].trim() : Version.emptyVersion.toString();
+ // Register matching features
+ registerMatchingFeatures(name, new VersionRange(version));
+ }
+
+ public void registerMatchingFeatures(String name, String version) throws IOException {
+ if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
+ version = Macro.transform(featureRange, version);
+ }
+ registerMatchingFeatures(name, version != null ? new VersionRange(version) : VersionRange.ANY_VERSION);
+ }
+
+ public void registerMatchingFeatures(String name, VersionRange range) throws IOException {
+ for (Repository repo : repositories) {
+ Feature[] features;
+ try {
+ features = repo.getFeatures();
+ } catch (Exception e) {
+ // This should not happen as the repository has been loaded already
+ throw new IllegalStateException(e);
+ }
+ for (Feature f : features) {
+ if (name.equals(f.getName())) {
+ Version v = VersionTable.getVersion(f.getVersion());
+ if (range.contains(v)) {
+ featuresToRegister.add(f);
+ for (Dependency dep : f.getDependencies()) {
+ registerMatchingFeatures(dep.getName(), dep.getVersion());
+ }
+ for (BundleInfo bundle : f.getBundles()) {
+ downloadAndBuildResource(bundle.getLocation());
+ }
+ for (Conditional cond : f.getConditional()) {
+ Feature c = cond.asFeature(f.getName(), f.getVersion());
+ featuresToRegister.add(c);
+ for (BundleInfo bundle : c.getBundles()) {
+ downloadAndBuildResource(bundle.getLocation());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void buildRequirement(String requirement) {
+ try {
+ String location = REQ_PROTOCOL + requirement;
+ ResourceImpl resource = new ResourceImpl(location, "dummy", Version.emptyVersion);
+ for (Requirement req : ResourceBuilder.parseRequirement(resource, requirement)) {
+ resource.addRequirement(req);
+ }
+ resources.put(location, resource);
+ } catch (BundleException e) {
+ throw new IllegalArgumentException("Error parsing requirement: " + requirement, e);
+ }
+ }
+
+ public void downloadAndBuildResource(final String location) throws IOException {
+ if (!resources.containsKey(location)) {
+ downloader.download(location, new Downloader.DownloadCallback() {
+ @Override
+ public void downloaded(StreamProvider provider) throws Exception {
+ manageResource(location, provider);
+ }
+ });
+ }
+ }
+
+ private void manageResource(String location, StreamProvider provider) throws Exception {
+ if (!resources.containsKey(location)) {
+ Attributes attributes = getAttributes(location, provider);
+ Resource resource = createResource(location, attributes);
+ resources.put(location, resource);
+ providers.put(location, provider);
+ }
+ }
+
+ private Resource createResource(String uri, Attributes attributes) throws Exception {
+ Map<String, String> headers = new HashMap<String, String>();
+ for (Map.Entry attr : attributes.entrySet()) {
+ headers.put(attr.getKey().toString(), attr.getValue().toString());
+ }
+ try {
+ return ResourceBuilder.build(uri, headers);
+ } catch (BundleException e) {
+ throw new Exception("Unable to create resource for bundle " + uri, e);
+ }
+ }
+
+ protected Attributes getAttributes(String uri, StreamProvider provider) throws Exception {
+ InputStream is = provider.open();
+ try {
+ ZipInputStream zis = new ZipInputStream(is);
+ ZipEntry entry;
+ while ( (entry = zis.getNextEntry()) != null ) {
+ if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
+ return new Manifest(zis).getMainAttributes();
+ }
+ }
+ } finally {
+ is.close();
+ }
+ throw new IllegalArgumentException("Resource " + uri + " does not contain a manifest");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
new file mode 100644
index 0000000..2d5dd98
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.deployment;
+
+import java.net.MalformedURLException;
+
+import org.apache.karaf.features.internal.util.MultiException;
+
+public interface Downloader {
+
+ void await() throws InterruptedException, MultiException;
+
+ void download(String location, DownloadCallback downloadCallback) throws MalformedURLException;
+
+ interface DownloadCallback {
+
+ void downloaded(StreamProvider provider) throws Exception;
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
new file mode 100644
index 0000000..60a3dfc
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface StreamProvider {
+
+ InputStream open() throws IOException;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
new file mode 100644
index 0000000..b1a5865
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
@@ -0,0 +1,290 @@
+/*
+ * 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.
+ */
+package org.apache.karaf.features.internal.management;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.openmbean.TabularData;
+
+import org.apache.karaf.features.*;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+import org.apache.karaf.features.management.codec.JmxFeature;
+import org.apache.karaf.features.management.codec.JmxFeatureEvent;
+import org.apache.karaf.features.management.codec.JmxRepository;
+import org.apache.karaf.features.management.codec.JmxRepositoryEvent;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Implementation of {@link FeaturesServiceMBean}.
+ */
+public class FeaturesServiceMBeanImpl extends StandardEmitterMBean implements
+ MBeanRegistration, FeaturesServiceMBean {
+
+ private ServiceRegistration<FeaturesListener> registration;
+
+ private BundleContext bundleContext;
+
+ private ObjectName objectName;
+
+ private volatile long sequenceNumber = 0;
+
+ private org.apache.karaf.features.FeaturesService featuresService;
+
+ public FeaturesServiceMBeanImpl() throws NotCompliantMBeanException {
+ super(FeaturesServiceMBean.class);
+ }
+
+ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+ objectName = name;
+ return name;
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ registration = bundleContext.registerService(FeaturesListener.class,
+ getFeaturesListener(), new Hashtable<String, String>());
+ }
+
+ public void preDeregister() throws Exception {
+ registration.unregister();
+ }
+
+ public void postDeregister() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TabularData getFeatures() throws Exception {
+ try {
+ List<Feature> allFeatures = Arrays.asList(featuresService.listFeatures());
+ List<Feature> insFeatures = Arrays.asList(featuresService.listInstalledFeatures());
+ ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
+ for (Feature feature : allFeatures) {
+ try {
+ features.add(new JmxFeature(feature, insFeatures.contains(feature)));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ TabularData table = JmxFeature.tableFrom(features);
+ return table;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TabularData getRepositories() throws Exception {
+ try {
+ List<Repository> allRepositories = Arrays.asList(featuresService.listRepositories());
+ ArrayList<JmxRepository> repositories = new ArrayList<JmxRepository>();
+ for (Repository repository : allRepositories) {
+ try {
+ repositories.add(new JmxRepository(repository));
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ TabularData table = JmxRepository.tableFrom(repositories);
+ return table;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ public void addRepository(String uri) throws Exception {
+ featuresService.addRepository(new URI(uri));
+ }
+
+ public void addRepository(String uri, boolean install) throws Exception {
+ featuresService.addRepository(new URI(uri), install);
+ }
+
+ public void removeRepository(String uri) throws Exception {
+ featuresService.removeRepository(new URI(uri));
+ }
+
+ public void removeRepository(String uri, boolean uninstall) throws Exception {
+ featuresService.removeRepository(new URI(uri), uninstall);
+ }
+
+ public void installFeature(String name) throws Exception {
+ featuresService.installFeature(name);
+ }
+
+ public void installFeature(String name, boolean noRefresh) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ featuresService.installFeature(name, options);
+ }
+
+ public void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ if (noStart) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
+ }
+ featuresService.installFeature(name, options);
+ }
+
+ public void installFeature(String name, String version) throws Exception {
+ featuresService.installFeature(name, version);
+ }
+
+ public void installFeature(String name, String version, boolean noRefresh) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ featuresService.installFeature(name, version, options);
+ }
+
+ public void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ if (noStart) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
+ }
+ featuresService.installFeature(name, version, options);
+ }
+
+ public TabularData infoFeature(String name) throws Exception {
+ try {
+ Feature feature = featuresService.getFeature(name);
+ return infoFeature(feature);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ public TabularData infoFeature(String name, String version) throws Exception {
+ try {
+ Feature feature = featuresService.getFeature(name, version);
+ return infoFeature(feature);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return null;
+ }
+ }
+
+ private TabularData infoFeature(Feature feature) throws Exception {
+ JmxFeature jmxFeature = null;
+ if (featuresService.isInstalled(feature)) {
+ jmxFeature = new JmxFeature(feature, true);
+ } else {
+ jmxFeature = new JmxFeature(feature, false);
+ }
+ ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
+ features.add(jmxFeature);
+ TabularData table = JmxFeature.tableFrom(features);
+ return table;
+ }
+
+ public void uninstallFeature(String name) throws Exception {
+ featuresService.uninstallFeature(name);
+ }
+
+ public void uninstallFeature(String name, boolean noRefresh) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ featuresService.uninstallFeature(name, options);
+ }
+
+ public void uninstallFeature(String name, String version) throws Exception {
+ featuresService.uninstallFeature(name, version);
+ }
+
+ public void uninstallFeature(String name, String version, boolean noRefresh) throws Exception {
+ EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+ if (noRefresh) {
+ options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+ }
+ featuresService.uninstallFeature(name, version, options);
+ }
+
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ public void setFeaturesService(org.apache.karaf.features.FeaturesService featuresService) {
+ this.featuresService = featuresService;
+ }
+
+ public FeaturesListener getFeaturesListener() {
+ return new FeaturesListener() {
+ public void featureEvent(FeatureEvent event) {
+ if (!event.isReplay()) {
+ Notification notification = new Notification(FEATURE_EVENT_TYPE, objectName, sequenceNumber++);
+ notification.setUserData(new JmxFeatureEvent(event).asCompositeData());
+ sendNotification(notification);
+ }
+ }
+
+ public void repositoryEvent(RepositoryEvent event) {
+ if (!event.isReplay()) {
+ Notification notification = new Notification(REPOSITORY_EVENT_TYPE, objectName, sequenceNumber++);
+ notification.setUserData(new JmxRepositoryEvent(event).asCompositeData());
+ sendNotification(notification);
+ }
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ return o.equals(this);
+ }
+
+ };
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return getBroadcastInfo();
+ }
+
+ private static MBeanNotificationInfo[] getBroadcastInfo() {
+ String type = Notification.class.getCanonicalName();
+ MBeanNotificationInfo info1 = new MBeanNotificationInfo(new String[]{FEATURE_EVENT_EVENT_TYPE},
+ type, "Some features notification");
+ MBeanNotificationInfo info2 = new MBeanNotificationInfo(new String[]{REPOSITORY_EVENT_EVENT_TYPE},
+ type, "Some repository notification");
+ return new MBeanNotificationInfo[]{info1, info2};
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java b/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
new file mode 100644
index 0000000..13a4b6c
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package org.apache.karaf.features.internal.management;
+
+import javax.management.*;
+
+public class StandardEmitterMBean extends StandardMBean implements NotificationEmitter {
+
+ private final NotificationBroadcasterSupport emitter;
+
+ @SuppressWarnings("rawtypes")
+ public StandardEmitterMBean(Class mbeanInterface) throws NotCompliantMBeanException {
+ super(mbeanInterface);
+ this.emitter = new NotificationBroadcasterSupport() {
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return StandardEmitterMBean.this.getNotificationInfo();
+ }
+ };
+ }
+
+ public void sendNotification(Notification notification) {
+ emitter.sendNotification(notification);
+ }
+
+
+ public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
+ emitter.removeNotificationListener(listener, filter, handback);
+ }
+
+ public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
+ emitter.addNotificationListener(listener, filter, handback);
+ }
+
+ public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
+ emitter.removeNotificationListener(listener);
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ return new MBeanNotificationInfo[0];
+ }
+
+ @Override
+ public MBeanInfo getMBeanInfo() {
+ MBeanInfo mbeanInfo = super.getMBeanInfo();
+ if (mbeanInfo != null) {
+ MBeanNotificationInfo[] notificationInfo = getNotificationInfo();
+ mbeanInfo = new MBeanInfo(mbeanInfo.getClassName(), mbeanInfo.getDescription(), mbeanInfo.getAttributes(),
+ mbeanInfo.getConstructors(), mbeanInfo.getOperations(), notificationInfo);
+ }
+ return mbeanInfo;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
new file mode 100644
index 0000000..7eebbe5
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import org.apache.karaf.features.BundleInfo;
+
+
+/**
+ *
+ * Deployable element to install.
+ *
+ *
+ * <p>Java class for bundle complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="bundle">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>anyURI">
+ * <attribute name="start-level" type="{http://www.w3.org/2001/XMLSchema}int" />
+ * <attribute name="start" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ * <attribute name="dependency" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "bundle", propOrder = {
+ "value"
+})
+public class Bundle implements BundleInfo {
+
+ @XmlValue
+ @XmlSchemaType(name = "anyURI")
+ protected String value;
+ @XmlAttribute(name = "start-level")
+ protected Integer startLevel;
+ @XmlAttribute
+ protected Boolean start;// = true;
+ @XmlAttribute
+ protected Boolean dependency;
+
+
+ public Bundle() {
+ }
+
+ public Bundle(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getLocation() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setLocation(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value of the startLevel property.
+ *
+ * @return
+ * possible object is
+ * {@link Integer }
+ *
+ */
+ public int getStartLevel() {
+ return startLevel == null? 0: startLevel;
+ }
+
+ /**
+ * Sets the value of the startLevel property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Integer }
+ *
+ */
+ public void setStartLevel(Integer value) {
+ this.startLevel = value;
+ }
+
+ /**
+ * Gets the value of the start property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public boolean isStart() {
+ return start == null? true: start;
+ }
+
+ /**
+ * Sets the value of the start property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setStart(Boolean value) {
+ this.start = value;
+ }
+
+ /**
+ * Gets the value of the dependency property.
+ *
+ * @return
+ * possible object is
+ * {@link Boolean }
+ *
+ */
+ public boolean isDependency() {
+ return dependency == null? false: dependency;
+ }
+
+ /**
+ * Sets the value of the dependency property.
+ *
+ * @param value
+ * allowed object is
+ * {@link Boolean }
+ *
+ */
+ public void setDependency(Boolean value) {
+ this.dependency = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Bundle bundle = (Bundle) o;
+
+ if (dependency != bundle.dependency) return false;
+ if (start != bundle.start) return false;
+ if (startLevel != bundle.startLevel) return false;
+ if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = value != null ? value.hashCode() : 0;
+ result = 31 * result + getStartLevel();
+ result = 31 * result + (isStart() ? 1 : 0);
+ result = 31 * result + (isDependency() ? 1 : 0);
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
new file mode 100644
index 0000000..b866151
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+import org.apache.karaf.features.BundleInfo;
+
+
+/**
+ *
+ * Additional capability for a feature.
+ *
+ *
+ * <p>Java class for bundle complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="capability">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "capability", propOrder = {
+ "value"
+})
+public class Capability implements org.apache.karaf.features.Capability {
+
+ @XmlValue
+ protected String value;
+
+
+ public Capability() {
+ }
+
+ public Capability(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Capability bundle = (Capability) o;
+
+ if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = value != null ? value.hashCode() : 0;
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
new file mode 100644
index 0000000..ed0e8ff
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.karaf.features.Feature;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "conditional", propOrder = {
+ "condition",
+ "config",
+ "configfile",
+ "feature",
+ "bundle"
+})
+public class Conditional extends Content implements org.apache.karaf.features.Conditional {
+
+ @XmlElement(name = "condition")
+ protected List<String> condition;
+
+ public List<String> getCondition() {
+ if (condition == null) {
+ this.condition = new ArrayList<String>();
+ }
+ return condition;
+ }
+
+ @Override
+ public Feature asFeature(String name, String version) {
+ String conditionName = name + "-condition-" + getConditionId().replaceAll("[^A-Za-z0-9 ]", "_");
+ org.apache.karaf.features.internal.model.Feature f = new org.apache.karaf.features.internal.model.Feature(conditionName, version);
+ f.getBundle().addAll(getBundle());
+ f.getConfig().addAll(getConfig());
+ f.getConfigfile().addAll(getConfigfile());
+ f.getFeature().addAll(getFeature());
+ return f;
+ }
+
+ private String getConditionId() {
+ StringBuffer sb = new StringBuffer();
+ for (String cond : getCondition()) {
+ if (sb.length() > 0) {
+ sb.append("_");
+ }
+ sb.append(cond);
+ }
+ return sb.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/0c8e8a81/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
new file mode 100644
index 0000000..a2c6674
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ *
+ * Configuration entries which should be created during feature installation. This
+ * configuration may be used with OSGi Configuration Admin.
+ *
+ *
+ * <p>Java class for config complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * <complexType name="config">
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "config", propOrder = {
+ "value"
+})
+public class Config {
+
+ @XmlValue
+ protected String value;
+ @XmlAttribute(required = true)
+ protected String name;
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+}
[04/33] git commit: [KARAF-2888] Better computation of bundles to
refresh and print them in simulation
Posted by gn...@apache.org.
[KARAF-2888] Better computation of bundles to refresh and print them in simulation
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/53996d9c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/53996d9c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/53996d9c
Branch: refs/heads/master
Commit: 53996d9c13aa766b590cfa34a77b738df2c50afa
Parents: 6a19214
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 23:39:15 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:02 2014 +0200
----------------------------------------------------------------------
.../internal/service/FeaturesServiceImpl.java | 172 ++++++++-----------
1 file changed, 71 insertions(+), 101 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/53996d9c/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index e6dbc32..0bd1e67 100644
--- a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -69,6 +69,8 @@ import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.Resource;
import org.osgi.resource.Wire;
@@ -793,7 +795,7 @@ public class FeaturesServiceImpl implements FeaturesService {
Collections.<String>emptySet(),
overrides,
Collections.<String>emptySet());
- Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, false);
+ Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, true);
Collection<Resource> allResources = resolution.keySet();
Map<String, StreamProvider> providers = builder.getProviders();
@@ -858,14 +860,76 @@ public class FeaturesServiceImpl implements FeaturesService {
//
logDeployment(deployment, verbose);
+ //
+ // Compute the set of bundles to refresh
+ //
+ Set<Bundle> toRefresh = new HashSet<Bundle>();
+ toRefresh.addAll(deployment.toDelete);
+ toRefresh.addAll(deployment.toUpdate.keySet());
+
+ if (!noRefreshManaged) {
+ int size;
+ do {
+ size = toRefresh.size();
+ for (Bundle bundle : bundles) {
+ // Continue if we already know about this bundle
+ if (toRefresh.contains(bundle)) {
+ continue;
+ }
+ // Ignore non resolved bundle
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ if (wiring == null) {
+ continue;
+ }
+ // Get through the old resolution and flag this bundle
+ // if it was wired to a bundle to be refreshed
+ for (BundleWire wire : wiring.getRequiredWires(null)) {
+ if (toRefresh.contains(wire.getProvider().getBundle())) {
+ toRefresh.add(bundle);
+ break;
+ }
+ }
+ // Get through the new resolution and flag this bundle
+ // if it's wired to any new bundle
+ List<Wire> newWires = resolution.get(wiring.getRevision());
+ if (newWires != null) {
+ for (Wire wire : newWires) {
+ Bundle b = null;
+ if (wire.getProvider() instanceof BundleRevision) {
+ b = ((BundleRevision) wire.getProvider()).getBundle();
+ } else {
+ b = deployment.resToBnd.get(wire.getProvider());
+ }
+ if (b == null || toRefresh.contains(b)) {
+ toRefresh.add(bundle);
+ break;
+ }
+ }
+ }
+ }
+ } while (toRefresh.size() > size);
+ }
+ if (noRefreshUnmanaged) {
+ Set<Bundle> newSet = new HashSet<Bundle>();
+ for (Bundle bundle : toRefresh) {
+ if (managed.contains(bundle.getBundleId())) {
+ newSet.add(bundle);
+ }
+ }
+ toRefresh = newSet;
+ }
+
+
if (simulate) {
- // TODO: it would be nice to print bundles that will be refreshed
- // TODO: it could be done by checking the differences between
- // TODO: the resolution result and the actual wiring state
+ if (!toRefresh.isEmpty()) {
+ print(" Bundles to refresh:", verbose);
+ for (Bundle bundle : toRefresh) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ }
+ }
return;
}
- Set<Bundle> toRefresh = new HashSet<Bundle>();
Set<Bundle> toStart = new HashSet<Bundle>();
//
@@ -908,7 +972,6 @@ public class FeaturesServiceImpl implements FeaturesService {
print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
bundle.uninstall();
managed.remove(bundle.getBundleId());
- toRefresh.add(bundle);
}
}
if (!deployment.toUpdate.isEmpty()) {
@@ -920,7 +983,6 @@ public class FeaturesServiceImpl implements FeaturesService {
print(" " + uri, verbose);
InputStream is = getBundleInputStream(resource, providers);
bundle.update(is);
- toRefresh.add(bundle);
toStart.add(bundle);
BundleInfo bi = bundleInfos.get(uri);
if (bi != null && bi.getStartLevel() > 0) {
@@ -940,7 +1002,6 @@ public class FeaturesServiceImpl implements FeaturesService {
if (!noStart || resourceLinkedToOldFeatures.contains(resource)) {
toStart.add(bundle);
}
- toRefresh.add(bundle);
deployment.resToBnd.put(resource, bundle);
// save a checksum of installed snapshot bundle
if (UPDATE_SNAPSHOTS_CRC.equals(updateSnaphots)
@@ -982,23 +1043,9 @@ public class FeaturesServiceImpl implements FeaturesService {
}
}
- if (!noRefreshManaged) {
- findBundlesWithOptionalPackagesToRefresh(toRefresh);
- findBundlesWithFragmentsToRefresh(toRefresh);
- }
-
- if (noRefreshUnmanaged) {
- Set<Bundle> newSet = new HashSet<Bundle>();
- for (Bundle bundle : toRefresh) {
- if (managed.contains(bundle.getBundleId())) {
- newSet.add(bundle);
- }
- }
- toRefresh = newSet;
- }
-
// TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
- RequirementSort sort = new RequirementSort();
+ new CopyOnWriteArrayIdentityList().iterator();
+ new RequirementSort();
if (!noRefresh) {
toStop = new HashSet<Bundle>();
@@ -1347,83 +1394,6 @@ public class FeaturesServiceImpl implements FeaturesService {
return provider.open();
}
- protected void findBundlesWithOptionalPackagesToRefresh(Set<Bundle> toRefresh) {
- // First pass: include all bundles contained in these features
- if (toRefresh.isEmpty()) {
- return;
- }
- Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
- bundles.removeAll(toRefresh);
- if (bundles.isEmpty()) {
- return;
- }
- // Second pass: for each bundle, check if there is any unresolved optional package that could be resolved
- for (Bundle bundle : bundles) {
- BundleRevision rev = bundle.adapt(BundleRevision.class);
- boolean matches = false;
- if (rev != null) {
- for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
- if (PackageNamespace.PACKAGE_NAMESPACE.equals(req.getNamespace())
- && PackageNamespace.RESOLUTION_OPTIONAL.equals(req.getDirectives().get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
- // This requirement is an optional import package
- for (Bundle provider : toRefresh) {
- BundleRevision providerRev = provider.adapt(BundleRevision.class);
- if (providerRev != null) {
- for (BundleCapability cap : providerRev.getDeclaredCapabilities(null)) {
- if (req.matches(cap)) {
- matches = true;
- break;
- }
- }
- }
- if (matches) {
- break;
- }
- }
- }
- if (matches) {
- break;
- }
- }
- }
- if (matches) {
- toRefresh.add(bundle);
- }
- }
- }
-
- protected void findBundlesWithFragmentsToRefresh(Set<Bundle> toRefresh) {
- if (toRefresh.isEmpty()) {
- return;
- }
- Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
- bundles.removeAll(toRefresh);
- if (bundles.isEmpty()) {
- return;
- }
- for (Bundle bundle : new ArrayList<Bundle>(toRefresh)) {
- BundleRevision rev = bundle.adapt(BundleRevision.class);
- if (rev != null) {
- for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
- if (BundleRevision.HOST_NAMESPACE.equals(req.getNamespace())) {
- for (Bundle hostBundle : bundles) {
- if (!toRefresh.contains(hostBundle)) {
- BundleRevision hostRev = hostBundle.adapt(BundleRevision.class);
- if (hostRev != null) {
- for (BundleCapability cap : hostRev.getDeclaredCapabilities(null)) {
- if (req.matches(cap)) {
- toRefresh.add(hostBundle);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
FrameworkWiring fw = systemBundleContext.getBundle().adapt(FrameworkWiring.class);
[10/33] git commit: [KARAF-2852] Remove unused files
Posted by gn...@apache.org.
[KARAF-2852] Remove unused files
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/fc37f55e
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/fc37f55e
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/fc37f55e
Branch: refs/heads/master
Commit: fc37f55e2b3946490296eeef54a383fed21b0381
Parents: 78fbae7
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 11 15:50:24 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 11 19:20:03 2014 +0200
----------------------------------------------------------------------
service/command/NOTICE | 71 --------------
service/command/pom.xml | 98 --------------------
.../src/main/resources/OSGI-INF/bundle.info | 20 ----
3 files changed, 189 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/fc37f55e/service/command/NOTICE
----------------------------------------------------------------------
diff --git a/service/command/NOTICE b/service/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/service/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/fc37f55e/service/command/pom.xml
----------------------------------------------------------------------
diff --git a/service/command/pom.xml b/service/command/pom.xml
deleted file mode 100644
index c33e13d..0000000
--- a/service/command/pom.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
- <!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You 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.
- -->
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.karaf.service</groupId>
- <artifactId>service</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
-
- <artifactId>org.apache.karaf.service.command</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: Service :: Command</name>
- <description>Provides shell commands to manipulate OSGi services</description>
-
- <properties>
- <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
- </properties>
-
- <dependencies>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.bundle</groupId>
- <artifactId>org.apache.karaf.bundle.command</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-jdk14</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- <includes>
- <include>**/*.info</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Karaf-Commands>org.apache.karaf.service.command</Karaf-Commands>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/fc37f55e/service/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/service/command/src/main/resources/OSGI-INF/bundle.info b/service/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index eff1072..0000000
--- a/service/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,20 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
- [mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the shell commands to manipulate OSGi services.
-
-The following commands are available:
-* services:list - Gets the list of OSGi services available
-* service:wait - Wait for a given OSGi service
-
-h1. See also
-
-Commands and Using the console sections of the Karaf User Guide