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/18 23:35:51 UTC
[1/6] [KARAF-2923] Region support in features service
Repository: karaf
Updated Branches:
refs/heads/master 53ad48f2a -> 2705ad889
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
deleted file mode 100644
index 857c2b3..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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;
-
-
-/**
- * <p>Java class for filterAttributeType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="filterAttributeType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * </sequence>
- * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterAttributeType")
-public class FilterAttributeType {
-
- @XmlAttribute(required = true)
- protected String name;
- @XmlAttribute(required = true)
- protected String 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;
- }
-
- /**
- * 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;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
deleted file mode 100644
index a9a9fbb..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlType;
-
-
-/**
- * <p>Java class for filterBundleType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="filterBundleType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
- * <attribute name="symbolic-name" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterBundleType", propOrder = {
- "attribute"
-})
-public class FilterBundleType {
-
- protected List<FilterAttributeType> attribute;
- @XmlAttribute
- protected Long id;
- @XmlAttribute(name = "symbolic-name")
- protected String symbolicName;
- @XmlAttribute
- protected String version;
-
- /**
- * Gets the value of the attribute 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 attribute property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getAttribute().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterAttributeType }
- *
- *
- */
- public List<FilterAttributeType> getAttribute() {
- if (attribute == null) {
- attribute = new ArrayList<FilterAttributeType>();
- }
- return this.attribute;
- }
-
- /**
- * Gets the value of the id property.
- *
- * @return
- * possible object is
- * {@link Long }
- *
- */
- public Long getId() {
- return id;
- }
-
- /**
- * Sets the value of the id property.
- *
- * @param value
- * allowed object is
- * {@link Long }
- *
- */
- public void setId(Long value) {
- this.id = value;
- }
-
- /**
- * Gets the value of the symbolicName property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getSymbolicName() {
- return symbolicName;
- }
-
- /**
- * Sets the value of the symbolicName property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setSymbolicName(String value) {
- this.symbolicName = value;
- }
-
- /**
- * Gets the value of the version property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getVersion() {
- return version;
- }
-
- /**
- * Sets the value of the version property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setVersion(String value) {
- this.version = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
deleted file mode 100644
index 52b937a..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlType;
-
-
-/**
- * <p>Java class for filterNamespaceType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="filterNamespaceType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterNamespaceType", propOrder = {
- "attribute"
-})
-public class FilterNamespaceType {
-
- protected List<FilterAttributeType> attribute;
- @XmlAttribute(required = true)
- protected String name;
-
- /**
- * Gets the value of the attribute 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 attribute property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getAttribute().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterAttributeType }
- *
- *
- */
- public List<FilterAttributeType> getAttribute() {
- if (attribute == null) {
- attribute = new ArrayList<FilterAttributeType>();
- }
- return this.attribute;
- }
-
- /**
- * 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/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
deleted file mode 100644
index b4216ee..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlType;
-
-
-/**
- * <p>Java class for filterPackageType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="filterPackageType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterPackageType", propOrder = {
- "attribute"
-})
-public class FilterPackageType {
-
- protected List<FilterAttributeType> attribute;
- @XmlAttribute
- protected String name;
- @XmlAttribute
- protected String version;
-
- /**
- * Gets the value of the attribute 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 attribute property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getAttribute().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterAttributeType }
- *
- *
- */
- public List<FilterAttributeType> getAttribute() {
- if (attribute == null) {
- attribute = new ArrayList<FilterAttributeType>();
- }
- return this.attribute;
- }
-
- /**
- * 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() {
- return version;
- }
-
- /**
- * Sets the value of the version property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setVersion(String value) {
- this.version = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
deleted file mode 100644
index f4d1352..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
+++ /dev/null
@@ -1,195 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlElement;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="filterType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterBundleType" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="package" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterPackageType" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="namespace" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterNamespaceType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="from" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * <attribute name="to" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterType", propOrder = {
- "bundle",
- "_package",
- "namespace"
-})
-public class FilterType {
-
- protected List<FilterBundleType> bundle;
- @XmlElement(name = "package")
- protected List<FilterPackageType> _package;
- protected List<FilterNamespaceType> namespace;
- @XmlAttribute(required = true)
- protected String from;
- @XmlAttribute(required = true)
- protected String to;
-
- /**
- * Gets the value of the bundle 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 bundle property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getBundle().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterBundleType }
- *
- *
- */
- public List<FilterBundleType> getBundle() {
- if (bundle == null) {
- bundle = new ArrayList<FilterBundleType>();
- }
- return this.bundle;
- }
-
- /**
- * Gets the value of the package 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 package property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getPackage().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterPackageType }
- *
- *
- */
- public List<FilterPackageType> getPackage() {
- if (_package == null) {
- _package = new ArrayList<FilterPackageType>();
- }
- return this._package;
- }
-
- /**
- * Gets the value of the namespace 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 namespace property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getNamespace().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterNamespaceType }
- *
- *
- */
- public List<FilterNamespaceType> getNamespace() {
- if (namespace == null) {
- namespace = new ArrayList<FilterNamespaceType>();
- }
- return this.namespace;
- }
-
- /**
- * Gets the value of the from property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getFrom() {
- return from;
- }
-
- /**
- * Sets the value of the from property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setFrom(String value) {
- this.from = value;
- }
-
- /**
- * Gets the value of the to property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getTo() {
- return to;
- }
-
- /**
- * Sets the value of the to property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setTo(String value) {
- this.to = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
deleted file mode 100644
index 54f5f3c..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.region.persist.internal.model 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 _Regions_QNAME = new QName("http://karaf.apache.org/xmlns/region/v1.0.0", "regions");
-
- /**
- * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.region.persist.internal.model
- *
- */
- public ObjectFactory() {
- }
-
- /**
- * Create an instance of {@link FilterNamespaceType }
- *
- */
- public FilterNamespaceType createFilterNamespaceType() {
- return new FilterNamespaceType();
- }
-
- /**
- * Create an instance of {@link FilterType }
- *
- */
- public FilterType createFilterType() {
- return new FilterType();
- }
-
- /**
- * Create an instance of {@link RegionBundleType }
- *
- */
- public RegionBundleType createRegionBundleType() {
- return new RegionBundleType();
- }
-
- /**
- * Create an instance of {@link FilterBundleType }
- *
- */
- public FilterBundleType createFilterBundleType() {
- return new FilterBundleType();
- }
-
- /**
- * Create an instance of {@link FilterPackageType }
- *
- */
- public FilterPackageType createFilterPackageType() {
- return new FilterPackageType();
- }
-
- /**
- * Create an instance of {@link FilterAttributeType }
- *
- */
- public FilterAttributeType createFilterAttributeType() {
- return new FilterAttributeType();
- }
-
- /**
- * Create an instance of {@link RegionType }
- *
- */
- public RegionType createRegionType() {
- return new RegionType();
- }
-
- /**
- * Create an instance of {@link RegionsType }
- *
- */
- public RegionsType createRegionsType() {
- return new RegionsType();
- }
-
- /**
- * Create an instance of {@link JAXBElement }{@code <}{@link RegionsType }{@code >}}
- *
- */
- @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", name = "regions")
- public JAXBElement<RegionsType> createRegions(RegionsType value) {
- return new JAXBElement<RegionsType>(_Regions_QNAME, RegionsType.class, null, value);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
deleted file mode 100644
index 7ba3585..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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;
-
-
-/**
- * <p>Java class for regionBundleType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="regionBundleType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * </sequence>
- * <attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
- * <attribute name="location" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionBundleType")
-public class RegionBundleType {
-
- @XmlAttribute
- protected Long id;
- @XmlAttribute
- protected String location;
-
- /**
- * Gets the value of the id property.
- *
- * @return
- * possible object is
- * {@link Long }
- *
- */
- public Long getId() {
- return id;
- }
-
- /**
- * Sets the value of the id property.
- *
- * @param value
- * allowed object is
- * {@link Long }
- *
- */
- public void setId(Long value) {
- this.id = value;
- }
-
- /**
- * Gets the value of the location property.
- *
- * @return
- * possible object is
- * {@link String }
- *
- */
- public String getLocation() {
- return location;
- }
-
- /**
- * Sets the value of the location property.
- *
- * @param value
- * allowed object is
- * {@link String }
- *
- */
- public void setLocation(String value) {
- this.location = value;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
deleted file mode 100644
index f7a810d..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlType;
-
-
-/**
- *
- * Regions element
- *
- *
- * <p>Java class for regionType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="regionType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionBundleType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionType", propOrder = {
- "bundle"
-})
-public class RegionType {
-
- protected List<RegionBundleType> bundle;
- @XmlAttribute(required = true)
- protected String name;
-
- /**
- * Gets the value of the bundle 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 bundle property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getBundle().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link RegionBundleType }
- *
- *
- */
- public List<RegionBundleType> getBundle() {
- if (bundle == null) {
- bundle = new ArrayList<RegionBundleType>();
- }
- return this.bundle;
- }
-
- /**
- * 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/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
deleted file mode 100644
index be172e4..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-
-package org.apache.karaf.region.persist.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.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- *
- * Regions element
- *
- *
- * <p>Java class for regionsType complex type.
- *
- * <p>The following schema fragment specifies the expected content contained within this class.
- *
- * <pre>
- * <complexType name="regionsType">
- * <complexContent>
- * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- * <sequence>
- * <element name="region" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionType" maxOccurs="unbounded" minOccurs="0"/>
- * <element name="filter" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterType" maxOccurs="unbounded" minOccurs="0"/>
- * </sequence>
- * </restriction>
- * </complexContent>
- * </complexType>
- * </pre>
- *
- *
- */
-@XmlRootElement(name = "regions")
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionsType", propOrder = {
- "region",
- "filter"
-})
-public class RegionsType {
-
- protected List<RegionType> region;
- protected List<FilterType> filter;
-
- /**
- * Gets the value of the region 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 region property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getRegion().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link RegionType }
- *
- *
- */
- public List<RegionType> getRegion() {
- if (region == null) {
- region = new ArrayList<RegionType>();
- }
- return this.region;
- }
-
- /**
- * Gets the value of the filter 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 filter property.
- *
- * <p>
- * For example, to add a new item, do as follows:
- * <pre>
- * getFilter().add(newItem);
- * </pre>
- *
- *
- * <p>
- * Objects of the following type(s) are allowed in the list
- * {@link FilterType }
- *
- *
- */
- public List<FilterType> getFilter() {
- if (filter == null) {
- filter = new ArrayList<FilterType>();
- }
- return this.filter;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
deleted file mode 100644
index cae062c..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
-// Any modifications to this file will be lost upon recompilation of the source schema.
-// Generated on: 2011.10.28 at 03:20:55 PM PDT
-//
-
-@javax.xml.bind.annotation.XmlSchema(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
-package org.apache.karaf.region.persist.internal.model;
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
deleted file mode 100644
index 410121c..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
+++ /dev/null
@@ -1,661 +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.region.persist.internal.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.osgi.framework.Constants;
-
-public class ManifestHeaderProcessor
-{
- public static final String NESTED_FILTER_ATTRIBUTE = "org.apache.aries.application.filter.attribute";
- private static final Pattern FILTER_ATTR = Pattern.compile("(\\(!)?\\((.*?)([<>]?=)(.*?)\\)\\)?");
- private static final String LESS_EQ_OP = "<=";
- private static final String GREATER_EQ_OP = ">=";
-
- /**
- * A simple class to associate two types.
- *
- */
- public static class NameValuePair {
- private String name;
- private Map<String,String> attributes;
-
- public NameValuePair(String name, Map<String,String> value)
- {
- this.name = name;
- this.attributes = value;
- }
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
-
- public Map<String,String> getAttributes()
- {
- return attributes;
- }
- public void setAttributes(Map<String,String> value)
- {
- this.attributes = value;
- }
-
- @Override
- public String toString(){
- return "{"+name.toString()+"::"+attributes.toString()+"}";
- }
- @Override
- public int hashCode()
- {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj)
- {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- final NameValuePair other = (NameValuePair) obj;
- if (name == null) {
- if (other.name != null) return false;
- } else if (!name.equals(other.name)) return false;
- if (attributes == null) {
- if (other.attributes != null) return false;
- } else if (!attributes.equals(other.attributes)) return false;
- return true;
- }
- }
-
- /**
- * Intended to provide a standard way to add Name/Value's to
- * aggregations of Name/Value's.
- *
- */
- public static interface NameValueCollection {
- /**
- * Add this Name & Value to the collection.
- * @param n
- * @param v
- */
- public void addToCollection(String n, Map<String,String> v);
- }
-
- /**
- * Map of Name -> Value.
- *
- */
- public static class NameValueMap extends HashMap<String, Map<String,String>> implements NameValueCollection, Map<String, Map<String,String>>{
- private static final long serialVersionUID = -6446338858542599141L;
-
- public void addToCollection(String n, Map<String,String> v){
- this.put(n,v);
- }
-
- @Override
- public String toString(){
- StringBuilder sb = new StringBuilder();
- sb.append("{");
- boolean first=true;
- for(Map.Entry<String, Map<String,String>> entry : this.entrySet()){
- if(!first)sb.append(",");
- first=false;
- sb.append(entry.getKey()+"->"+entry.getValue());
- }
- sb.append("}");
- return sb.toString();
- }
- }
-
- /**
- * List of Name/Value
- *
- */
- public static class NameValueList extends ArrayList<NameValuePair> implements NameValueCollection, List<NameValuePair> {
- private static final long serialVersionUID = 1808636823825029983L;
-
- public void addToCollection(String n, Map<String,String> v){
- this.add(new NameValuePair(n,v));
- }
- @Override
- public String toString(){
- StringBuffer sb = new StringBuffer();
- sb.append("{");
- boolean first = true;
- for(NameValuePair nvp : this){
- if(!first)sb.append(",");
- first=false;
- sb.append(nvp.toString());
- }
- sb.append("}");
- return sb.toString();
- }
- }
-
- /**
- *
- * Splits a delimiter separated string, tolerating presence of non separator commas
- * within double quoted segments.
- *
- * Eg.
- * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
- * com.ibm.ws.eba.helloWorldService;version="1.0.0"
- * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
- * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
- * @param value the value to be split
- * @param delimiter the delimiter string such as ',' etc.
- * @return List<String> the components of the split String in a list
- */
- public static List<String> split(String value, String delimiter)
- {
- return ManifestHeaderUtils.split(value, delimiter);
- }
-
-
- /**
- * Internal method to parse headers with the format<p>
- * [Name](;[Name])*(;[attribute-name]=[attribute-value])*<br>
- * Eg.<br>
- * rumplestiltskin;thing=value;other=something<br>
- * littleredridinghood
- * bundle1;bundle2;other=things
- * bundle1;bundle2
- *
- * @param s data to parse
- * @return a list of NameValuePair, with the Name being the name component,
- * and the Value being a NameValueMap of key->value mappings.
- */
- private static List<NameValuePair> genericNameWithNameValuePairProcess(String s){
- String name;
- Map<String,String> params = null;
- List<NameValuePair> nameValues = new ArrayList<NameValuePair>();
- List<String> pkgs = new ArrayList<String>();
- int index = s.indexOf(";");
- if(index==-1){
- name = s;
- params = new HashMap<String, String>();
- pkgs.add(name);
- }else{
- name = s.substring(0,index).trim();
- String tail = s.substring(index+1).trim();
-
- pkgs.add(name); // add the first package
- StringBuilder parameters = new StringBuilder();
-
-
- // take into consideration of multiple packages separated by ';'
- // while they share the same attributes or directives
- List<String> tailParts = split(tail, ";");
- boolean firstParameter =false;
-
- for (String part : tailParts) {
- // if it is not a parameter and no parameter appears in front of it, it must a package
- if (!!!(part.contains("="))) {
- // Need to make sure no parameter appears before the package, otherwise ignore this string
- // as this syntax is invalid
- if (!!!(firstParameter))
- pkgs.add(part);
- } else {
- if (!!!(firstParameter))
- firstParameter = true;
-
- parameters.append(part + ";");
- }
- }
-
- if (parameters.length() != 0) {
- //remove the final ';' if there is one
- if (parameters.toString().endsWith(";")) {
-
- parameters = parameters.deleteCharAt(parameters.length() -1);
- }
-
- params = genericNameValueProcess(parameters.toString());
- }
-
- }
- for (String pkg : pkgs) {
- nameValues.add(new NameValuePair(pkg,params));
- }
-
- return nameValues;
-
- }
-
- /**
- * Internal method to parse headers with the format<p>
- * [attribute-name]=[attribute-value](;[attribute-name]=[attribute-value])*<br>
- * Eg.<br>
- * thing=value;other=something<br>
- * <p>
- * Note. Directives (name:=value) are represented in the map with name suffixed by ':'
- *
- * @param s data to parse
- * @return a NameValueMap, with attribute-name -> attribute-value.
- */
- private static Map<String,String> genericNameValueProcess(String s){
- Map<String,String> params = new HashMap<String,String>();
- List<String> parameters = split(s, ";");
- for(String parameter : parameters) {
- List<String> parts = split(parameter,"=");
- // do a check, otherwise we might get NPE
- if (parts.size() ==2) {
- String second = parts.get(1).trim();
- if (second.startsWith("\"") && second.endsWith("\""))
- second = second.substring(1,second.length()-1);
-
- String first = parts.get(0).trim();
-
- // make sure for directives we clear out any space as in "directive :=value"
- if (first.endsWith(":")) {
- first = first.substring(0, first.length()-1).trim()+":";
- }
-
- params.put(first, second);
- }
- }
-
- return params;
- }
-
- /**
- * Processes an import/export style header.. <p>
- * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
- *
- * @param out The collection to add each package name + attrib map to.
- * @param s The data to parse
- */
- private static void genericImportExportProcess(NameValueCollection out, String s){
- List<String> packages = split(s, ",");
- for(String pkg : packages){
- List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
- for (NameValuePair p : ps) {
- out.addToCollection(p.getName(), p.getAttributes());
- }
- }
- }
-
- /**
- * Parse an export style header.<p>
- * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value2
- * <p>
- * Result is returned as a list, as export does allow duplicate package exports.
- *
- * @param s The data to parse.
- * @return List of NameValuePairs, where each Name in the list is an exported package,
- * with its associated Value being a NameValueMap of any attributes declared.
- */
- public static List<NameValuePair> parseExportString(String s){
- NameValueList retval = new NameValueList();
- genericImportExportProcess(retval, s);
- return retval;
- }
-
- /**
- * Parse an export style header in a list.<p>
- * pkg1;attrib=value;attrib=value
- * pkg2;attrib=value
- * pkg3;attrib=value2
- * <p>
- * Result is returned as a list, as export does allow duplicate package exports.
- *
- * @param list The data to parse.
- * @return List of NameValuePairs, where each Name in the list is an exported package,
- * with its associated Value being a NameValueMap of any attributes declared.
- */
- public static List<NameValuePair> parseExportList(List<String> list){
- NameValueList retval = new NameValueList();
- for(String pkg : list){
- List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
- for (NameValuePair p : ps) {
- retval.addToCollection(p.getName(), p.getAttributes());
- }
- }
- return retval;
- }
-
- /**
- * Parse an import style header.<p>
- * pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
- * <p>
- * Result is returned as a set, as import does not allow duplicate package imports.
- *
- * @param s The data to parse.
- * @return Map of NameValuePairs, where each Key in the Map is an imported package,
- * with its associated Value being a NameValueMap of any attributes declared.
- */
- public static Map<String, Map<String, String>> parseImportString(String s){
- NameValueMap retval = new NameValueMap();
- genericImportExportProcess(retval, s);
- return retval;
- }
-
- /**
- * Parse a bundle symbolic name.<p>
- * bundlesymbolicname;attrib=value;attrib=value
- * <p>
- *
- * @param s The data to parse.
- * @return NameValuePair with Name being the BundleSymbolicName,
- * and Value being any attribs declared for the name.
- */
- public static NameValuePair parseBundleSymbolicName(String s){
- return genericNameWithNameValuePairProcess(s).get(0); // should just return the first one
- }
-
- /**
- * Parse a version range..
- *
- * @param s
- * @return VersionRange object.
- * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
- */
- public static VersionRange parseVersionRange(String s) throws IllegalArgumentException{
- return new VersionRange(s);
- }
-
- /**
- * Parse a version range and indicate if the version is an exact version
- *
- * @param s
- * @param exactVersion
- * @return VersionRange object.
- * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
- */
- public static VersionRange parseVersionRange(String s, boolean exactVersion) throws IllegalArgumentException{
- return new VersionRange(s, exactVersion);
- }
-
- /**
- * Generate a filter from a set of attributes. This filter will be suitable
- * for presentation to OBR This means that, due to the way OBR works, it
- * will include a stanza of the form, (mandatory:<*mandatoryAttribute)
- * Filter strings generated by this method will therefore tend to break the
- * standard OSGi Filter class. The OBR stanza can be stripped out later if
- * required.
- *
- * @param attribs
- * @return filter string
- */
- public static String generateFilter(Map<String, Object> attribs) {
- StringBuilder filter = new StringBuilder("(&");
- boolean realAttrib = false;
- StringBuffer realAttribs = new StringBuffer();
-
- if (attribs == null) {
- attribs = new HashMap<String, Object>();
- }
-
- for (Map.Entry<String, Object> attrib : attribs.entrySet()) {
- String attribName = attrib.getKey();
-
- if (attribName.endsWith(":")) {
- // skip all directives. It is used to affect the attribs on the
- // filter xml.
- } else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
- || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
- // version and bundle-version attrib requires special
- // conversion.
- realAttrib = true;
-
- VersionRange vr = ManifestHeaderProcessor
- .parseVersionRange(attrib.getValue().toString());
-
- filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
-
- if (vr.getMaximumVersion() != null) {
- filter.append(")(" + attribName + "<=");
- filter.append(vr.getMaximumVersion());
- }
-
- if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
- filter.append(")(!(" + attribName + "=");
- filter.append(vr.getMinimumVersion());
- filter.append(")");
- }
-
- if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
- filter.append(")(!(" + attribName + "=");
- filter.append(vr.getMaximumVersion());
- filter.append(")");
- }
- filter.append(")");
-
- } else if (NESTED_FILTER_ATTRIBUTE.equals(attribName)) {
- // Filters go in whole, no formatting needed
- realAttrib = true;
- filter.append(attrib.getValue());
-
- } else if (Constants.OBJECTCLASS.equals(attribName)) {
- realAttrib = true;
- // objectClass has a "," separated list of interfaces
- String[] values = attrib.getValue().toString().split(",");
- for (String s : values)
- filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
-
- } else {
- // attribName was not version..
- realAttrib = true;
-
- filter.append("(" + attribName + "=" + attrib.getValue() + ")");
- // store all attributes in order to build up the mandatory
- // filter and separate them with ", "
- // skip bundle-symbolic-name in the mandatory directive query
- if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
- .equals(attribName)) {
- realAttribs.append(attribName);
- realAttribs.append(", ");
- }
- }
- }
-// /*
-// * The following is how OBR makes mandatory attributes work, we require
-// * that the set of mandatory attributes on the export is a subset of (or
-// * equal to) the set of the attributes we supply.
-// */
-//
-// if (realAttribs.length() > 0) {
-// String attribStr = (realAttribs.toString()).trim();
-// // remove the final ,
-// if ((attribStr.length() > 0) && (attribStr.endsWith(","))) {
-// attribStr = attribStr.substring(0, attribStr.length() - 1);
-// }
-// // build the mandatory filter, e.g.(mandatory:<*company, local)
-// filter.append("(" + Constants.MANDATORY_DIRECTIVE + ":" + "<*"
-// + attribStr + ")");
-// }
-
- // Prune (& off the front and ) off end
- String filterString = filter.toString();
- int openBraces = 0;
- for (int i = 0; openBraces < 3; i++) {
- i = filterString.indexOf('(', i);
- if (i == -1) {
- break;
- } else {
- openBraces++;
- }
- }
- if (openBraces < 3 && filterString.length() > 2) {
- filter.delete(0, 2);
- } else {
- filter.append(")");
- }
-
- String result = "";
- if (realAttrib != false) {
- result = filter.toString();
- }
- return result;
- }
-
- /**
- * Generate a filter from a set of attributes. This filter will be suitable
- * for presentation to OBR. This means that, due to the way OBR works, it will
- * include a stanza of the form, (mandatory:<*mandatoryAttribute) Filter
- * strings generated by this method will therefore tend to break the standard
- * OSGi Filter class. The OBR stanza can be stripped out later if required.
- *
- * We may wish to consider relocating this method since VersionRange has its
- * own top level class.
- *
- * @param type
- * @param name
- * @param attribs
- * @return filter string
- */
- public static String generateFilter(String type, String name,
- Map<String, Object> attribs) {
- StringBuffer filter = new StringBuffer();
- String result;
- // shortcut for the simple case with no attribs.
-
- if (attribs == null || attribs.isEmpty())
- filter.append("(" + type + "=" + name + ")");
- else {
- // process all the attribs passed.
- // find out whether there are attributes on the filter
-
- filter.append("(&(" + type + "=" + name + ")");
-
- String filterString = generateFilter(attribs);
-
- int start = 0;
- int end = filterString.length();
- if (filterString.startsWith("(&")) {
- start = 2;
- end--;
- }
-
- if ("".equals(filterString)) {
- filter.delete(0, 2);
- } else {
- filter.append(filterString, start, end);
- filter.append(")");
- }
- }
-
- result = filter.toString();
-
- return result;
- }
-
- private static Map<String, String> parseFilterList(String filter) {
-
- Map<String, String> result = new HashMap<String, String>();
- Set<String> negatedVersions = new HashSet<String>();
- Set<String> negatedBundleVersions = new HashSet<String>();
-
- String lowerVersion = null;
- String upperVersion = null;
- String lowerBundleVersion = null;
- String upperBundleVersion = null;
-
- Matcher m = FILTER_ATTR.matcher(filter);
- while (m.find()) {
- boolean negation = m.group(1) != null;
- String attr = m.group(2);
- String op = m.group(3);
- String value = m.group(4);
-
- if (Constants.VERSION_ATTRIBUTE.equals(attr)) {
- if (negation) {
- negatedVersions.add(value);
- } else {
- if (GREATER_EQ_OP.equals(op))
- lowerVersion = value;
- else if (LESS_EQ_OP.equals(op))
- upperVersion = value;
- else
- throw new IllegalArgumentException();
- }
- } else if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attr)) {
- // bundle-version is like version, but may be specified at the
- // same time
- // therefore we have similar code with separate variables
- if (negation) {
- negatedBundleVersions.add(value);
- } else {
- if (GREATER_EQ_OP.equals(op))
- lowerBundleVersion = value;
- else if (LESS_EQ_OP.equals(op))
- upperBundleVersion = value;
- else
- throw new IllegalArgumentException();
- }
- } else {
- result.put(attr, value);
- }
- }
-
- if (lowerVersion != null) {
- StringBuilder versionAttr = new StringBuilder(lowerVersion);
- if (upperVersion != null) {
- versionAttr.append(",").append(upperVersion).insert(0,
- negatedVersions.contains(lowerVersion) ? '(' : '[').append(
- negatedVersions.contains(upperVersion) ? ')' : ']');
- }
-
- result.put(Constants.VERSION_ATTRIBUTE, versionAttr.toString());
- }
- // Do it again for bundle-version
- if (lowerBundleVersion != null) {
- StringBuilder versionAttr = new StringBuilder(lowerBundleVersion);
- if (upperBundleVersion != null) {
- versionAttr.append(",").append(upperBundleVersion).insert(0,
- negatedBundleVersions.contains(lowerBundleVersion) ? '(' : '[')
- .append(
- negatedBundleVersions.contains(upperBundleVersion) ? ')' : ']');
- }
-
- result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, versionAttr.toString());
- }
-
- return result;
- }
-
- public static Map<String,String> parseFilter(String filter)
- {
- Map<String,String> result;
- if (filter.startsWith("(&")) {
- result = parseFilterList(filter.substring(2, filter.length()-1));
- } else {
- result = parseFilterList(filter);
- }
- return result;
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
deleted file mode 100644
index 8c87616..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
+++ /dev/null
@@ -1,85 +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.region.persist.internal.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ManifestHeaderUtils {
-
- /**
- *
- * Splits a delimiter separated string, tolerating presence of non separator commas
- * within double quoted segments.
- *
- * Eg.
- * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
- * com.ibm.ws.eba.helloWorldService;version="1.0.0"
- * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
- * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
- * @param value the value to be split
- * @param delimiter the delimiter string such as ',' etc.
- * @return List<String> the components of the split String in a list
- */
- public static List<String> split(String value, String delimiter)
- {
- List<String> result = new ArrayList<String>();
- if (value != null) {
- String[] packages = value.split(delimiter);
-
- for (int i = 0; i < packages.length; ) {
- String tmp = packages[i++].trim();
- // if there is a odd number of " in a string, we need to append
- while (count(tmp, "\"") % 2 != 0) {
- // check to see if we need to append the next package[i++]
- if (i<packages.length)
- tmp = tmp + delimiter + packages[i++].trim();
- else
- // oops. The double quotes are not paired up. We have reached to the end of the string.
- throw new IllegalArgumentException("Unmatched double quotes: " + tmp);
- }
-
- result.add(tmp);
-
- }
- }
- return result;
- }
-
- /**
- * count the number of characters in a string
- * @param parent The string to be searched
- * @param subString The substring to be found
- * @return the number of occurrence of the subString
- */
- private static int count(String parent, String subString) {
-
- int count = 0 ;
- int i = parent.indexOf(subString);
- while (i > -1) {
- if (parent.length() >= i+1)
- parent = parent.substring(i+1);
- count ++;
- i = parent.indexOf(subString);
- }
- return count;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
deleted file mode 100644
index 19bbc77..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
+++ /dev/null
@@ -1,456 +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.region.persist.internal.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.osgi.framework.Version;
-
-public final class VersionRange {
-
- /** A string representation of the version. */
- private String version;
-
- /** The minimum desired version for the bundle */
- private Version minimumVersion;
-
- /** The maximum desired version for the bundle */
- private Version maximumVersion;
-
- /** True if the match is exclusive of the minimum version */
- private boolean minimumExclusive;
-
- /** True if the match is exclusive of the maximum version */
- private boolean maximumExclusive;
-
- /** A regexp to select the version */
- private static final Pattern versionCapture = Pattern.compile("\"?(.*?)\"?$");
-
- /**
- *
- * @param version
- * version for the verioninfo
- */
- public VersionRange(String version) {
- this.version = version;
- processVersionAttribute(version);
- }
-
- /**
- * This method should be used to create a version range from a single
- * version string.
- * @param version
- * version for the versioninfo
- * @param exactVersion
- * whether this is an exact version {@code true} or goes to infinity
- * {@code false}
- */
- public VersionRange(String version, boolean exactVersion) {
-
- if (exactVersion) {
- // Do not store this string as it might be just a version, or a range!
- processExactVersionAttribute(version);
- } else {
- this.version = version;
- processVersionAttribute(this.version);
- }
-
- assertInvariants();
- }
-
- /**
- * Constructor designed for internal use only.
- *
- * @param maximumVersion
- * @param maximumExclusive
- * @param minimumVersion
- * @param minimumExclusive
- * @throws IllegalArgumentException
- * if parameters are not valid.
- */
- private VersionRange(Version maximumVersion,
- boolean maximumExclusive,
- Version minimumVersion,
- boolean minimumExclusive) {
- this.maximumVersion = maximumVersion;
- this.maximumExclusive = maximumExclusive;
- this.minimumVersion = minimumVersion;
- this.minimumExclusive = minimumExclusive;
-
- assertInvariants();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.apache.aries.application.impl.VersionRange#toString()
- */
- @Override
- public String toString() {
- // Some constructors don't take in a string that we can return directly,
- // so construct one if needed
- if (version == null) {
- if (maximumVersion == null) {
- version = minimumVersion.toString();
- } else {
- version = (minimumExclusive ? "(" : "[") + minimumVersion + "," + maximumVersion
- + (maximumExclusive ? ")" : "]");
- }
- }
- return this.version;
- }
-
- @Override
- public int hashCode() {
- int result = 17;
- result = 31 * result + minimumVersion.hashCode();
- result = 31 * result + (minimumExclusive ? 1 : 0);
- result = 31 * result + (maximumVersion != null ? maximumVersion.hashCode() : 0);
- result = 31 * result + (maximumExclusive ? 1 : 0);
- return result;
- }
-
- @Override
- public boolean equals(Object other) {
- boolean result = false;
- if (this == other) {
- result = true;
- } else if (other instanceof VersionRange) {
- VersionRange vr = (VersionRange) other;
- result = minimumVersion.equals(vr.minimumVersion)
- && minimumExclusive == vr.minimumExclusive
- && (maximumVersion == null ? vr.maximumVersion == null : maximumVersion
- .equals(vr.maximumVersion)) && maximumExclusive == vr.maximumExclusive;
- }
-
- return result;
- }
-
- /**
- * this method returns the exact version from the versionInfo obj.
- * this is used for DeploymentContent only to return a valid exact version
- * otherwise, null is returned.
- * @return the exact version
- */
- public Version getExactVersion() {
- Version v = null;
- if (isExactVersion()) {
- v = getMinimumVersion();
- }
- return v;
- }
-
- /**
- * get the maximum version
- * @return the maximum version
- */
- public Version getMaximumVersion() {
- return maximumVersion;
- }
-
- /**
- * get the minimum version
- * @return the minimum version
- */
- public Version getMinimumVersion() {
- return minimumVersion;
- }
-
- /**
- * is the maximum version exclusive
- * @return is the max version in the range.
- */
- public boolean isMaximumExclusive() {
- return maximumExclusive;
- }
-
- /**
- * is the maximum version unbounded
- * @return true if no upper bound was specified.
- */
- public boolean isMaximumUnbounded() {
- boolean unbounded = maximumVersion == null;
- return unbounded;
- }
-
- /**
- * is the minimum version exclusive
- * @return true if the min version is in range.
- */
- public boolean isMinimumExclusive() {
- return minimumExclusive;
- }
-
- /**
- * this is designed for deployed-version as that is the exact version.
- *
- * @param version
- * @return
- * @throws IllegalArgumentException
- */
- private boolean processExactVersionAttribute(String version) throws IllegalArgumentException {
- boolean success = processVersionAttribute(version);
-
- if (maximumVersion == null) {
- maximumVersion = minimumVersion;
- }
-
- if (!minimumVersion.equals(maximumVersion)) {
- throw new IllegalArgumentException("Version is not exact: " + version);
- }
-
- if (!!!isExactVersion()) {
- throw new IllegalArgumentException("Version is not exact: " + version);
- }
-
- return success;
- }
-
- /**
- * process the version attribute,
- *
- * @param version
- * the value to be processed
- * @return
- * @throws IllegalArgumentException
- */
- private boolean processVersionAttribute(String version) throws IllegalArgumentException {
- boolean success = false;
-
- if (version == null) {
- throw new IllegalArgumentException("Version is null");
- }
-
- Matcher matches = versionCapture.matcher(version);
-
- if (matches.matches()) {
- String versions = matches.group(1);
-
- if ((versions.startsWith("[") || versions.startsWith("("))
- && (versions.endsWith("]") || versions.endsWith(")"))) {
- if (versions.startsWith("["))
- minimumExclusive = false;
- else if (versions.startsWith("("))
- minimumExclusive = true;
-
- if (versions.endsWith("]"))
- maximumExclusive = false;
- else if (versions.endsWith(")"))
- maximumExclusive = true;
-
- int index = versions.indexOf(',');
- String minVersion = versions.substring(1, index);
- String maxVersion = versions.substring(index + 1, versions.length() - 1);
-
- try {
- minimumVersion = new Version(minVersion.trim());
- maximumVersion = new Version(maxVersion.trim());
- success = true;
- } catch (NumberFormatException nfe) {
- throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
- }
- } else {
- try {
- if (versions.trim().length() == 0)
- minimumVersion = new Version(0, 0, 0);
- else
- minimumVersion = new Version(versions.trim());
- success = true;
- } catch (NumberFormatException nfe) {
- throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
- }
- }
- } else {
- throw new IllegalArgumentException("Version cannot be decoded: " + version);
- }
-
- return success;
- }
-
- /**
- * Assert object invariants. Called by constructors to verify that arguments
- * were valid.
- *
- * @throws IllegalArgumentException
- * if invariants are violated.
- */
- private void assertInvariants() {
- if (minimumVersion == null
- || !isRangeValid(minimumVersion, minimumExclusive, maximumVersion, maximumExclusive)) {
- IllegalArgumentException e = new IllegalArgumentException();
- throw e;
- }
- }
-
- /**
- * Check if the supplied parameters describe a valid version range.
- *
- * @param min
- * the minimum version.
- * @param minExclusive
- * whether the minimum version is exclusive.
- * @param max
- * the maximum version.
- * @param maxExclusive
- * whether the maximum version is exclusive.
- * @return true is the range is valid; otherwise false.
- */
- private boolean isRangeValid(Version min,
- boolean minExclusive,
- Version max,
- boolean maxExclusive) {
- boolean result;
-
- // A null maximum version is unbounded so means that minimum is smaller
- // than
- // maximum.
- int minMaxCompare = (max == null ? -1 : min.compareTo(max));
- if (minMaxCompare > 0) {
- // Minimum larger than maximum is invalid.
- result = false;
- } else if (minMaxCompare == 0 && (minExclusive || maxExclusive)) {
- // If min and max are the same, and either are exclusive, no valid
- // range
- // exists.
- result = false;
- } else {
- // Range is valid.
- result = true;
- }
-
- return result;
- }
-
- /**
- * This method checks that the provided version matches the desired version.
- *
- * @param version
- * the version.
- * @return true if the version matches, false otherwise.
- */
- public boolean matches(Version version) {
- boolean result;
- if (this.getMaximumVersion() == null) {
- result = this.getMinimumVersion().compareTo(version) <= 0;
- } else {
- int minN = this.isMinimumExclusive() ? 0 : 1;
- int maxN = this.isMaximumExclusive() ? 0 : 1;
-
- result = (this.getMinimumVersion().compareTo(version) < minN)
- && (version.compareTo(this.getMaximumVersion()) < maxN);
- }
- return result;
- }
-
- /**
- * check if the versioninfo is the exact version
- * @return true if the range will match 1 exact version.
- */
- public boolean isExactVersion() {
- return minimumVersion.equals(maximumVersion) && minimumExclusive == maximumExclusive
- && !!!minimumExclusive;
- }
-
- /**
- * Create a new version range that is the intersection of {@code this} and the argument.
- * In other words, the largest version range that lies within both {@code this} and
- * the parameter.
- * @param r a version range to be intersected with {@code this}.
- * @return a new version range, or {@code null} if no intersection is possible.
- */
- public VersionRange intersect(VersionRange r) {
- // Use the highest minimum version.
- final Version newMinimumVersion;
- final boolean newMinimumExclusive;
- int minCompare = minimumVersion.compareTo(r.getMinimumVersion());
- if (minCompare > 0) {
- newMinimumVersion = minimumVersion;
- newMinimumExclusive = minimumExclusive;
- } else if (minCompare < 0) {
- newMinimumVersion = r.getMinimumVersion();
- newMinimumExclusive = r.isMinimumExclusive();
- } else {
- newMinimumVersion = minimumVersion;
- newMinimumExclusive = (minimumExclusive || r.isMinimumExclusive());
- }
-
- // Use the lowest maximum version.
- final Version newMaximumVersion;
- final boolean newMaximumExclusive;
- // null maximum version means unbounded, so the highest possible value.
- if (maximumVersion == null) {
- newMaximumVersion = r.getMaximumVersion();
- newMaximumExclusive = r.isMaximumExclusive();
- } else if (r.getMaximumVersion() == null) {
- newMaximumVersion = maximumVersion;
- newMaximumExclusive = maximumExclusive;
- } else {
- int maxCompare = maximumVersion.compareTo(r.getMaximumVersion());
- if (maxCompare < 0) {
- newMaximumVersion = maximumVersion;
- newMaximumExclusive = maximumExclusive;
- } else if (maxCompare > 0) {
- newMaximumVersion = r.getMaximumVersion();
- newMaximumExclusive = r.isMaximumExclusive();
- } else {
- newMaximumVersion = maximumVersion;
- newMaximumExclusive = (maximumExclusive || r.isMaximumExclusive());
- }
- }
-
- VersionRange result;
- if (isRangeValid(newMinimumVersion, newMinimumExclusive, newMaximumVersion,
- newMaximumExclusive)) {
- result = new VersionRange(newMaximumVersion, newMaximumExclusive, newMinimumVersion,
- newMinimumExclusive);
- } else {
- result = null;
- }
- return result;
- }
-
- /**
- * Parse a version range..
- *
- * @param s
- * @return VersionRange object.
- * @throws IllegalArgumentException
- * if the String could not be parsed as a VersionRange
- */
- public static VersionRange parseVersionRange(String s) throws IllegalArgumentException {
- return new VersionRange(s);
- }
-
- /**
- * Parse a version range and indicate if the version is an exact version
- *
- * @param s
- * @param exactVersion
- * @return VersionRange object.
- * @throws IllegalArgumentException
- * if the String could not be parsed as a VersionRange
- */
- public static VersionRange parseVersionRange(String s, boolean exactVersion)
- throws IllegalArgumentException {
- return new VersionRange(s, exactVersion);
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
----------------------------------------------------------------------
diff --git a/region/src/main/resources/org/apache/karaf/region/persist/region.xsd b/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
deleted file mode 100644
index 8ca26e7..0000000
--- a/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
+++ /dev/null
@@ -1,109 +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.
--->
-
-<!-- $Rev$ $Date$ -->
-
-<xsd:schema xmlns="http://karaf.apache.org/xmlns/region/v1.0.0"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- targetNamespace="http://karaf.apache.org/xmlns/region/v1.0.0"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified">
-
-
- <xsd:annotation>
- <xsd:documentation>
- Defines the configuration elements for Apache Karaf region xml configuration.
- </xsd:documentation>
- </xsd:annotation>
-
- <xsd:element name="regions" type="regionsType"/>
-
-
- <xsd:complexType name="regionsType">
- <xsd:annotation>
- <xsd:documentation>
- Regions element
- </xsd:documentation>
- </xsd:annotation>
- <xsd:sequence>
- <xsd:element name="region" type="regionType" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="filter" type="filterType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- </xsd:complexType>
-
- <xsd:complexType name="regionType">
- <xsd:annotation>
- <xsd:documentation>
- Region element
- </xsd:documentation>
- </xsd:annotation>
- <xsd:sequence>
- <xsd:element name="bundle" type="regionBundleType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- </xsd:complexType>
-
-
- <xsd:complexType name="regionBundleType">
- <xsd:sequence/>
- <xsd:attribute name="id" type="xsd:long"/>
- <xsd:attribute name="location" type="xsd:string"/>
- </xsd:complexType>
-
- <xsd:complexType name="filterBundleType">
- <xsd:sequence>
- <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="id" type="xsd:long"/>
- <xsd:attribute name="symbolic-name" type="xsd:string"/>
- <xsd:attribute name="version" type="xsd:string"/>
- </xsd:complexType>
-
- <xsd:complexType name="filterType">
- <xsd:sequence>
- <xsd:element name="bundle" type="filterBundleType" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="package" type="filterPackageType" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="namespace" type="filterNamespaceType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="from" type="xsd:string" use="required"/>
- <xsd:attribute name="to" type="xsd:string" use="required"/>
- </xsd:complexType>
-
- <xsd:complexType name="filterPackageType">
- <xsd:sequence>
- <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- <xsd:attribute name="version" type="xsd:string"/>
- </xsd:complexType>
-
- <xsd:complexType name="filterAttributeType">
- <xsd:sequence/>
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- <xsd:attribute name="value" type="xsd:string" use="required"/>
- </xsd:complexType>
-
- <xsd:complexType name="filterNamespaceType">
- <xsd:sequence>
- <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- </xsd:complexType>
-</xsd:schema>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
----------------------------------------------------------------------
diff --git a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
index 47052ab..890c510 100644
--- a/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
+++ b/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
@@ -26,6 +26,7 @@ import org.apache.karaf.features.ConfigFileInfo;
import org.apache.karaf.features.Dependency;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.Requirement;
+import org.apache.karaf.features.Scoping;
public class ExtendedFeature implements Feature {
@@ -139,8 +140,7 @@ public class ExtendedFeature implements Feature {
}
@Override
- public String getRegion() {
- return feature.getRegion();
+ public Scoping getScoping() {
+ return feature.getScoping();
}
-
}
[3/6] [KARAF-2923] Region support in features service
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 0243dc0..84b9529 100644
--- 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
@@ -48,14 +48,16 @@ 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.download.StreamProvider;
+import org.apache.karaf.features.internal.region.ResourceComparator;
+import org.apache.karaf.features.internal.region.SubsystemResolver;
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.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilterBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
@@ -64,6 +66,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.IdentityNamespace;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
@@ -76,12 +79,18 @@ import org.slf4j.LoggerFactory;
import static org.apache.felix.resolver.Util.getSymbolicName;
import static org.apache.felix.resolver.Util.getVersion;
+import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet;
+import static org.apache.karaf.features.internal.util.MapUtils.copyMapSet;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.*;
+import static org.apache.karaf.features.internal.util.MapUtils.removeFromMapSet;
/**
*
*/
public class FeaturesServiceImpl implements FeaturesService {
+ public static final String ROOT_REGION = "root";
+
public static final String UPDATE_SNAPSHOTS_NONE = "none";
public static final String UPDATE_SNAPSHOTS_CRC = "crc";
public static final String UPDATE_SNAPSHOTS_ALWAYS = "always";
@@ -114,6 +123,7 @@ public class FeaturesServiceImpl implements FeaturesService {
private final FeatureFinder featureFinder;
private final EventAdminListener eventAdminListener;
private final FeatureConfigInstaller configInstaller;
+ private final RegionDigraph digraph;
private final String overrides;
/**
* Range to use when a version is specified on a feature dependency.
@@ -150,6 +160,7 @@ public class FeaturesServiceImpl implements FeaturesService {
FeatureFinder featureFinder,
EventAdminListener eventAdminListener,
FeatureConfigInstaller configInstaller,
+ RegionDigraph digraph,
String overrides,
String featureResolutionRange,
String bundleUpdateRange,
@@ -160,6 +171,7 @@ public class FeaturesServiceImpl implements FeaturesService {
this.featureFinder = featureFinder;
this.eventAdminListener = eventAdminListener;
this.configInstaller = configInstaller;
+ this.digraph = digraph;
this.overrides = overrides;
this.featureResolutionRange = featureResolutionRange;
this.bundleUpdateRange = bundleUpdateRange;
@@ -221,7 +233,7 @@ public class FeaturesServiceImpl implements FeaturesService {
Set<String> installedFeatures = new TreeSet<String>();
synchronized (lock) {
repositories.addAll(state.repositories);
- installedFeatures.addAll(state.installedFeatures);
+ installedFeatures.addAll(state.installedFeatures.keySet());
}
for (String uri : repositories) {
Repository repository = new RepositoryImpl(URI.create(uri));
@@ -547,15 +559,17 @@ public class FeaturesServiceImpl implements FeaturesService {
public boolean isInstalled(Feature f) {
String id = normalize(f.getId());
synchronized (lock) {
- return state.installedFeatures.contains(id);
+ Set<String> installed = state.installedFeatures.get(ROOT_REGION);
+ return installed != null && installed.contains(id);
}
}
@Override
public boolean isRequired(Feature f) {
- String id = normalize(f.getId());
+ String id = f.getName() + "/" + new VersionRange(f.getVersion(), true);
synchronized (lock) {
- return state.features.contains(id);
+ Set<String> features = state.features.get(ROOT_REGION);
+ return features != null && features.contains(id);
}
}
@@ -563,27 +577,37 @@ public class FeaturesServiceImpl implements FeaturesService {
// Installation and uninstallation of features
//
+ @Override
public void installFeature(String name) throws Exception {
installFeature(name, EnumSet.noneOf(Option.class));
}
+ @Override
public void installFeature(String name, String version) throws Exception {
installFeature(version != null ? name + "/" + version : name, EnumSet.noneOf(Option.class));
}
+ @Override
public void installFeature(String name, EnumSet<Option> options) throws Exception {
installFeatures(Collections.singleton(name), options);
}
+ @Override
public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
installFeature(version != null ? name + "/" + version : name, options);
}
+ @Override
public void installFeature(Feature feature, EnumSet<Option> options) throws Exception {
installFeature(feature.getId());
}
@Override
+ public void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+ installFeatures(features, ROOT_REGION, options);
+ }
+
+ @Override
public void uninstallFeature(String name, String version) throws Exception {
uninstallFeature(version != null ? name + "/" + version : name);
}
@@ -603,6 +627,11 @@ public class FeaturesServiceImpl implements FeaturesService {
uninstallFeatures(Collections.singleton(name), options);
}
+ @Override
+ public void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+ uninstallFeatures(features, ROOT_REGION, options);
+ }
+
//
//
@@ -613,18 +642,12 @@ public class FeaturesServiceImpl implements FeaturesService {
//
-
-
-
-
- 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);
+ @Override
+ public void installFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception {
+ State state = copyState();
+ Map<String, Set<String>> required = copyMapSet(state.features);
+ if (region == null || region.isEmpty()) {
+ region = ROOT_REGION;
}
List<String> featuresToAdd = new ArrayList<String>();
Map<String, Map<String, Feature>> featuresMap = getFeatures();
@@ -638,7 +661,8 @@ public class FeaturesServiceImpl implements FeaturesService {
throw new IllegalArgumentException("No matching features for " + feature);
}
} else {
- featuresToAdd.add(normalize(f.getId()));
+ String req = f.getName() + "/" + new VersionRange(f.getVersion(), true);
+ featuresToAdd.add(req);
}
}
featuresToAdd = new ArrayList<String>(new LinkedHashSet<String>(featuresToAdd));
@@ -651,18 +675,25 @@ public class FeaturesServiceImpl implements FeaturesService {
sb.append(featuresToAdd.get(i));
}
print(sb.toString(), options.contains(Option.Verbose));
- required.addAll(featuresToAdd);
- doInstallFeaturesInThread(required, installed, managed, options);
+ Set<String> fl = required.get(region);
+ if (fl == null) {
+ fl = new HashSet<String>();
+ required.put(region,fl);
+ }
+ fl.addAll(featuresToAdd);
+ doInstallFeaturesInThread(required, state, 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);
+ public void uninstallFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception {
+ State state = copyState();
+ Map<String, Set<String>> required = copyMapSet(state.features);
+ if (region == null || region.isEmpty()) {
+ region = ROOT_REGION;
+ }
+ Set<String> fl = required.get(region);
+ if (fl == null) {
+ fl = new HashSet<String>();
+ required.put(region,fl);
}
List<String> featuresToRemove = new ArrayList<String>();
for (String feature : new HashSet<String>(features)) {
@@ -670,15 +701,18 @@ public class FeaturesServiceImpl implements FeaturesService {
feature = normalize(feature);
if (feature.endsWith("/0.0.0")) {
String nameSep = feature.substring(0, feature.indexOf("/") + 1);
- for (String f : required) {
+ for (String f : fl) {
if (normalize(f).startsWith(nameSep)) {
toRemove.add(f);
}
}
} else {
- toRemove.add(feature);
+ String name = feature.substring(0, feature.indexOf("/"));
+ String version = feature.substring(feature.indexOf("/") + 1);
+ String req = name + "/" + new VersionRange(version, true);
+ toRemove.add(req);
}
- toRemove.retainAll(required);
+ toRemove.retainAll(fl);
if (toRemove.isEmpty()) {
throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
} else if (toRemove.size() > 1) {
@@ -706,8 +740,17 @@ public class FeaturesServiceImpl implements FeaturesService {
sb.append(featuresToRemove.get(i));
}
print(sb.toString(), options.contains(Option.Verbose));
- required.removeAll(featuresToRemove);
- doInstallFeaturesInThread(required, installed, managed, options);
+ fl.removeAll(featuresToRemove);
+ if (fl.isEmpty()) {
+ required.remove(fl);
+ }
+ doInstallFeaturesInThread(required, state, options);
+ }
+
+ private State copyState() {
+ synchronized (lock) {
+ return this.state.copy();
+ }
}
protected String normalize(String feature) {
@@ -726,16 +769,15 @@ public class FeaturesServiceImpl implements FeaturesService {
* 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,
+ public void doInstallFeaturesInThread(final Map<String, Set<String>> features,
+ final State state,
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);
+ doInstallFeatures(features, state, options);
return null;
}
}).get();
@@ -755,10 +797,9 @@ public class FeaturesServiceImpl implements FeaturesService {
}
}
- 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
+ public void doInstallFeatures(Map<String, Set<String>> features, // all request features
+ State state, // current state
+ EnumSet<Option> options // installation options
) throws Exception {
boolean noRefreshUnmanaged = options.contains(Option.NoAutoRefreshUnmanagedBundles);
@@ -768,43 +809,56 @@ public class FeaturesServiceImpl implements FeaturesService {
boolean verbose = options.contains(Option.Verbose);
boolean simulate = options.contains(Option.Simulate);
+ Map<String, Set<String>> installed = state.installedFeatures;
+ Map<String, Set<Long>> managed = state.managedBundles;
+
// Get a list of resolved and unmanaged bundles to use as capabilities during resolution
- List<Resource> systemBundles = new ArrayList<Resource>();
+ List<BundleRevision> systemBundles = new ArrayList<BundleRevision>();
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);
+ if (bundle.getState() >= Bundle.RESOLVED) {
+ boolean bm = false;
+ for (Set<Long> m : managed.values()) {
+ bm |= m.contains(bundle.getBundleId());
+ }
+ if (!bm) {
+ BundleRevision 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
+ // TODO: overrides
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);
+
+ if (!installed.containsKey(ROOT_REGION)) {
+ installed.put(ROOT_REGION, new HashSet<String>());
+ }
+
+ SubsystemResolver resolver = new SubsystemResolver();
+ Map<Resource, List<Wire>> resolution = resolver.resolve(
+ Arrays.asList(repositories),
+ features,
+ systemBundles,
+ featureResolutionRange);
Collection<Resource> allResources = resolution.keySet();
- Map<String, StreamProvider> providers = builder.getProviders();
+ Map<String, StreamProvider> providers = resolver.getProviders();
+
+ Map<String, Set<String>> installedFeatures = getInstalledFeatures(resolver);
- // Install conditionals
List<String> installedFeatureIds = getFeatureIds(allResources);
List<String> newFeatures = new ArrayList<String>(installedFeatureIds);
- newFeatures.removeAll(installed);
- List<String> delFeatures = new ArrayList<String>(installed);
+ newFeatures.removeAll(installed.get(ROOT_REGION));
+ List<String> delFeatures = new ArrayList<String>(installed.get(ROOT_REGION));
delFeatures.removeAll(installedFeatureIds);
//
// Compute list of installable resources (those with uris)
//
- List<Resource> resources = getBundles(allResources);
+ Map<Resource, String> resources = resolver.getBundles();
// Compute information for each bundle
Map<String, BundleInfo> bundleInfos = new HashMap<String, BundleInfo>();
@@ -823,14 +877,10 @@ public class FeaturesServiceImpl implements FeaturesService {
// 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);
- }
+ for (Resource resource : resolver.getFeatures().keySet()) {
+ String id = getFeatureId(resource);
+ if (installed.get(ROOT_REGION).contains(id)) {
+ addTransitive(resource, resourceLinkedToOldFeatures, resolution);
}
}
}
@@ -838,15 +888,10 @@ public class FeaturesServiceImpl implements FeaturesService {
//
// Compute deployment
//
- Map<String, Long> bundleChecksums = new HashMap<String, Long>();
- synchronized (lock) {
- bundleChecksums.putAll(state.bundleChecksums);
- }
- Deployment deployment = computeDeployment(managed, bundles, providers, resources, bundleChecksums);
+ // TODO: compute bundles/region mapping to support multiple bundles and bunde moving into a different region
+ Deployment deployment = computeDeployment(resolver, state);
- if (deployment.toDelete.isEmpty() &&
- deployment.toUpdate.isEmpty() &&
- deployment.toInstall.isEmpty()) {
+ if (deployment.regions.isEmpty()) {
print("No deployment change.", verbose);
return;
}
@@ -859,8 +904,10 @@ public class FeaturesServiceImpl implements FeaturesService {
// Compute the set of bundles to refresh
//
Set<Bundle> toRefresh = new HashSet<Bundle>();
- toRefresh.addAll(deployment.toDelete);
- toRefresh.addAll(deployment.toUpdate.keySet());
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ toRefresh.addAll(regionDeployment.toDelete);
+ toRefresh.addAll(regionDeployment.toUpdate.keySet());
+ }
if (!noRefreshManaged) {
int size;
@@ -907,8 +954,11 @@ public class FeaturesServiceImpl implements FeaturesService {
if (noRefreshUnmanaged) {
Set<Bundle> newSet = new HashSet<Bundle>();
for (Bundle bundle : toRefresh) {
- if (managed.contains(bundle.getBundleId())) {
- newSet.add(bundle);
+ for (Set<Long> m : managed.values()) {
+ if (m.contains(bundle.getBundleId())) {
+ newSet.add(bundle);
+ break;
+ }
}
}
toRefresh = newSet;
@@ -932,12 +982,14 @@ public class FeaturesServiceImpl implements FeaturesService {
//
// TODO: handle update on the features service itself
- if (deployment.toUpdate.containsKey(bundle) ||
- deployment.toDelete.contains(bundle)) {
+ RegionDeployment rootRegionDeployment = deployment.regions.get(ROOT_REGION);
+ if (rootRegionDeployment != null &&
+ (rootRegionDeployment.toUpdate.containsKey(bundle)
+ || rootRegionDeployment.toDelete.contains(bundle))) {
LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
- deployment.toUpdate.remove(bundle);
- deployment.toDelete.remove(bundle);
+ rootRegionDeployment.toUpdate.remove(bundle);
+ rootRegionDeployment.toDelete.remove(bundle);
}
@@ -945,10 +997,14 @@ public class FeaturesServiceImpl implements FeaturesService {
// Perform bundle operations
//
+ //
// Stop bundles by chunks
+ //
Set<Bundle> toStop = new HashSet<Bundle>();
- toStop.addAll(deployment.toUpdate.keySet());
- toStop.addAll(deployment.toDelete);
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ toStop.addAll(regionDeployment.toUpdate.keySet());
+ toStop.addAll(regionDeployment.toDelete);
+ }
removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
if (!toStop.isEmpty()) {
print("Stopping bundles:", verbose);
@@ -961,67 +1017,162 @@ public class FeaturesServiceImpl implements FeaturesService {
}
}
}
- if (!deployment.toDelete.isEmpty()) {
+
+ //
+ // Delete bundles
+ //
+ boolean hasToDelete = false;
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ if ((hasToDelete = !regionDeployment.toDelete.isEmpty())) {
+ break;
+ }
+ }
+ if (hasToDelete) {
print("Uninstalling bundles:", verbose);
- for (Bundle bundle : deployment.toDelete) {
- print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
- bundle.uninstall();
- managed.remove(bundle.getBundleId());
+ for (Map.Entry<String, RegionDeployment> entry : deployment.regions.entrySet()) {
+ String name = entry.getKey();
+ RegionDeployment regionDeployment = entry.getValue();
+ for (Bundle bundle : regionDeployment.toDelete) {
+ print(" " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+ bundle.uninstall();
+ removeFromMapSet(managed, name, 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());
+
+ //
+ // Update regions
+ //
+ // TODO: this replace the whole digraph with the computed one
+ // TODO: we need to be smarter and allow user modifications or
+ // TODO: externally managed regions such as the one managed
+ // TODO: by aries subsystems
+ RegionDigraph clone = this.digraph.copy();
+ RegionDigraph computedDigraph = resolver.getDigraph();
+ for (Region r : clone.getRegions()) {
+ clone.removeRegion(r);
+ }
+ Map<String, String> flats = resolver.getFlatSubsystemsMap();
+ for (Region r : computedDigraph.getRegions()) {
+ if (r.getName().equals(flats.get(r.getName()))) {
+ clone.createRegion(r.getName());
+ }
+ }
+ for (Region r : computedDigraph.getRegions()) {
+ for (RegionDigraph.FilteredRegion fr : computedDigraph.getEdges(r)) {
+ String rt = flats.get(r.getName());
+ String rh = flats.get(fr.getRegion().getName());
+ if (!rh.equals(rt)) {
+ Region tail = clone.getRegion(rt);
+ Region head = clone.getRegion(rh);
+ RegionFilterBuilder rfb = clone.createRegionFilterBuilder();
+ for (Map.Entry<String, Collection<String>> entry : fr.getFilter().getSharingPolicy().entrySet()) {
+ // Discard osgi.identity namespace
+ if (!IdentityNamespace.IDENTITY_NAMESPACE.equals(entry.getKey())) {
+ for (String f : entry.getValue()) {
+ rfb.allow(entry.getKey(), f);
+ }
+ }
+ }
+ clone.connect(tail, rfb.build(), head);
}
- // 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)) {
+ // Spread bundles across regions
+ Region root = clone.getRegion(ROOT_REGION);
+ for (BundleRevision revision : systemBundles) {
+ root.addBundle(revision.getBundle());
+ }
+ for (Resource resource : resources.keySet()) {
+ Bundle bundle = deployment.resToBnd.get(resource);
+ if (bundle != null) {
+ String region = resources.get(resource);
+ clone.getRegion(region).addBundle(bundle);
+ }
+ }
+ this.digraph.replace(clone);
+
+ //
+ // Update bundles
+ //
+ boolean hasToUpdate = false;
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ if ((hasToUpdate = !regionDeployment.toUpdate.isEmpty())) {
+ break;
+ }
+ }
+ if (hasToUpdate) {
+ print("Updating bundles:", verbose);
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ for (Map.Entry<Bundle, Resource> entry : regionDeployment.toUpdate.entrySet()) {
+ Bundle bundle = entry.getKey();
+ Resource resource = entry.getValue();
+ String uri = 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());
+ }
}
- 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());
+ }
+ }
+ //
+ // Install bundles
+ //
+ boolean hasToInstall = false;
+ for (RegionDeployment regionDeployment : deployment.regions.values()) {
+ if ((hasToInstall = !regionDeployment.toInstall.isEmpty())) {
+ break;
+ }
+ }
+ if (hasToInstall) {
+ print("Installing bundles:", verbose);
+ for (Map.Entry<String, RegionDeployment> entry : deployment.regions.entrySet()) {
+ String name = entry.getKey();
+ Region region = digraph.getRegion(name);
+ RegionDeployment regionDeployment = entry.getValue();
+ for (Resource resource : regionDeployment.toInstall) {
+ String uri = getUri(resource);
+ print(" " + uri, verbose);
+ InputStream is = getBundleInputStream(resource, providers);
+ Bundle bundle;
+ if (ROOT_REGION.equals(name)) {
+ bundle = region.installBundleAtLocation(uri, is);
+ } else {
+ bundle = region.installBundle(uri, is);
+ }
+ addToMapSet(managed, name, 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.getBundleId())) {
+ deployment.newCheckums.put(bundle.getBundleId(), 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);
+ this.state.bundleChecksums.putAll(deployment.newCheckums);
+ this.state.features.clear();
+ this.state.features.putAll(features);
+ this.state.installedFeatures.clear();
+ this.state.installedFeatures.putAll(installedFeatures);
+ this.state.managedBundles.clear();
+ this.state.managedBundles.putAll(managed);
saveState();
}
@@ -1134,122 +1285,145 @@ public class FeaturesServiceImpl implements FeaturesService {
}
}
- protected void logDeployment(Deployment deployment, boolean verbose) {
+ protected void logDeployment(Deployment overallDeployment, 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);
+ for (Map.Entry<String, RegionDeployment> region : overallDeployment.regions.entrySet()) {
+ RegionDeployment deployment = region.getValue();
+ print(" Region: " + region.getKey(), 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.toUpdate.isEmpty()) {
+ print(" Bundles to update:", verbose);
+ for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
+ print(" " + entry.getKey().getSymbolicName() + " / " + entry.getKey().getVersion() + " with " + getUri(entry.getValue()), verbose);
+ }
}
- }
- if (!deployment.toInstall.isEmpty()) {
- print(" Bundles to install:", verbose);
- for (Resource resource : deployment.toInstall) {
- print(" " + UriNamespace.getUri(resource), verbose);
+ if (!deployment.toInstall.isEmpty()) {
+ print(" Bundles to install:", verbose);
+ for (Resource resource : deployment.toInstall) {
+ print(" " + 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;
+ SubsystemResolver resolver,
+ State state) throws IOException {
+
+ Deployment result = new Deployment();
+
+ Map<String, Set<Resource>> bundlesPerRegions = resolver.getBundlesPerRegions();
+
+ // Gather all regions, including old ones and new ones
+ Set<String> regions = new HashSet<String>();
+ regions.addAll(state.managedBundles.keySet());
+ regions.addAll(bundlesPerRegions.keySet());
+
+ for (String region : regions) {
+
+ RegionDeployment deployment = new RegionDeployment();
+
+ // Get the list of bundles currently assigned in the region
+ Set<Long> managed = state.managedBundles.get(region);
+ if (managed == null) {
+ managed = Collections.emptySet();
+ }
+
+ // Compute the list of resources to deploy in the region
+ Set<Resource> bundlesInRegion = bundlesPerRegions.get(region);
+ List<Resource> toDeploy = bundlesInRegion != null
+ ? new ArrayList<Resource>(bundlesInRegion) : new ArrayList<Resource>();
+
+ // First pass: go through all installed bundles and mark them
+ // as either to ignore or delete
+ for (long bundleId : managed) {
+ // Look for the installed bundle
+ Bundle bundle = systemBundleContext.getBundle(bundleId);
+ // Bundle has been manually uninstalled ?
+ if (bundle != null) {
+ // Look for a matching resource
+ 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 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 (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, resolver.getProviders());
+ long newCrc = ChecksumUtils.checksum(is);
+ long oldCrc = state.bundleChecksums.containsKey(bundle.getBundleId()) ? state.bundleChecksums.get(bundle.getBundleId()) : 0l;
+ if (newCrc != oldCrc) {
+ LOGGER.debug("New snapshot available for " + bundle.getLocation());
+ deployment.toUpdate.put(bundle, resource);
+ result.newCheckums.put(bundle.getBundleId(), newCrc);
+ }
+ } finally {
+ if (is != null) {
+ is.close();
+ }
}
}
}
+ // We're done for this resource
+ toDeploy.remove(resource);
+ result.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);
}
- // 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);
+ // 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);
+ result.resToBnd.put(resource, bundle);
+ } else {
+ deployment.toInstall.add(resource);
}
}
- 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;
- }
+ Collections.sort(deployment.toInstall, new ResourceComparator());
- 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);
+ // Add this region if there is something to do
+ if (!deployment.toDelete.isEmpty()
+ || !deployment.toUpdate.isEmpty()
+ || !deployment.toInstall.isEmpty()) {
+ result.regions.put(region, deployment);
}
}
- return new ArrayList<Resource>(deploy.values());
+
+ return result;
}
protected List<Feature> getFeatures(Repository[] repositories, List<String> featureIds) throws Exception {
@@ -1265,28 +1439,33 @@ public class FeaturesServiceImpl implements FeaturesService {
return installedFeatures;
}
+ protected Map<String, Set<String>> getInstalledFeatures(SubsystemResolver resolver) {
+ Map<String, Set<String>> installed = new HashMap<String, Set<String>>();
+ Map<String, Set<Resource>> mapping = resolver.getFeaturesPerRegions();
+ for (Map.Entry<String, Set<Resource>> entry : mapping.entrySet()) {
+ for (Resource resource : entry.getValue()) {
+ addToMapSet(installed, entry.getKey(), getFeatureId(resource));
+ }
+ }
+ return installed;
+ }
+
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;
+ String id = getFeatureId(resource);
+ if (id != null) {
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));
+ String uri = getUri(resource);
+ return getVersion(resource).getQualifier().endsWith(SNAPSHOT)
+ || uri.contains(SNAPSHOT)
+ || !uri.contains(MAVEN);
}
protected List<Bundle> getBundlesToStart(Collection<Bundle> bundles) {
@@ -1378,7 +1557,7 @@ public class FeaturesServiceImpl implements FeaturesService {
}
protected InputStream getBundleInputStream(Resource resource, Map<String, StreamProvider> providers) throws IOException {
- String uri = UriNamespace.getUri(resource);
+ String uri = getUri(resource);
if (uri == null) {
throw new IllegalStateException("Resource has no uri");
}
@@ -1406,8 +1585,12 @@ public class FeaturesServiceImpl implements FeaturesService {
static class Deployment {
- Map<String, Long> newCheckums = new HashMap<String, Long>();
+ Map<Long, Long> newCheckums = new HashMap<Long, Long>();
Map<Resource, Bundle> resToBnd = new HashMap<Resource, Bundle>();
+ Map<String, RegionDeployment> regions = new HashMap<String, RegionDeployment>();
+ }
+
+ static class RegionDeployment {
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/2705ad88/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
index 56e5102..9c2f2b6 100644
--- 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
@@ -47,7 +47,7 @@ public class RepositoryImpl implements Repository {
return features.getName();
}
- public URI[] getRepositories() throws Exception {
+ public URI[] getRepositories() throws IOException {
load();
URI[] result = new URI[features.getRepository().size()];
for (int i = 0; i < features.getRepository().size(); i++) {
@@ -58,7 +58,7 @@ public class RepositoryImpl implements Repository {
return result;
}
- public org.apache.karaf.features.Feature[] getFeatures() throws Exception {
+ public org.apache.karaf.features.Feature[] getFeatures() throws IOException {
load();
return features.getFeature().toArray(new org.apache.karaf.features.Feature[features.getFeature().size()]);
}
@@ -94,9 +94,5 @@ public class RepositoryImpl implements Repository {
}
}
- @Override
- public boolean isValid() {
- throw new UnsupportedOperationException();
- }
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index d1f16b9..0000000
--- a/features/core/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/2705ad88/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
index c84f4e0..df4d901 100644
--- 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
@@ -22,13 +22,34 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import static org.apache.karaf.features.internal.util.MapUtils.copyMapSet;
+
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>();
+ public final Map<String, Set<String>> features = new HashMap<String, Set<String>>();
+ public final Map<String, Set<String>> installedFeatures = new HashMap<String, Set<String>>();
+ public final Map<String, Set<Long>> managedBundles = new HashMap<String, Set<Long>>();
+ public final Map<Long, Long> bundleChecksums = new HashMap<Long, Long>();
+
+ public State copy() {
+ State state = new State();
+ state.bootDone.set(bootDone.get());
+ copySet(repositories, state.repositories);
+ copyMapSet(features, state.features);
+ copyMapSet(installedFeatures, state.installedFeatures);
+ copyMapSet(managedBundles, state.managedBundles);
+ copyMap(bundleChecksums, state.bundleChecksums);
+ return state;
+ }
+
+ static <T> void copySet(Set<T> from, Set<T> to) {
+ to.addAll(from);
+ }
+
+ static <S, T> void copyMap(Map<S, T> from, Map<S, T> to) {
+ to.putAll(from);
+ }
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index ac54ab0..3b3424f 100644
--- 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
@@ -20,17 +20,14 @@ 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.Collection;
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;
+import org.apache.karaf.features.internal.util.JsonReader;
+import org.apache.karaf.features.internal.util.JsonWriter;
public abstract class StateStorage {
@@ -42,14 +39,13 @@ public abstract class StateStorage {
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.")));
+ Map json = (Map) JsonReader.read(is);
+ state.bootDone.set((Boolean) json.get("bootDone"));
+ state.repositories.addAll(toStringSet((Collection) json.get("repositories")));
+ state.features.putAll(toStringStringSetMap((Map) json.get("features")));
+ state.installedFeatures.putAll(toStringStringSetMap((Map) json.get("installed")));
+ state.managedBundles.putAll(toStringLongSetMap((Map) json.get("managed")));
+ state.bundleChecksums.putAll(toLongLongMap((Map) json.get("checksums")));
} finally {
close(is);
}
@@ -60,14 +56,14 @@ public abstract class StateStorage {
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");
+ Map<String, Object> json = new HashMap<String, Object>();
+ json.put("bootDone", state.bootDone.get());
+ json.put("repositories", state.repositories);
+ json.put("features", state.features);
+ json.put("installed", state.installedFeatures);
+ json.put("managed", state.managedBundles);
+ json.put("checksums", toStringLongMap(state.bundleChecksums));
+ JsonWriter.write(os, json);
} finally {
close(os);
}
@@ -77,92 +73,63 @@ public abstract class StateStorage {
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 Map<String, Set<String>> toStringStringSetMap(Map<?,?> map) {
+ Map<String, Set<String>> nm = new HashMap<String, Set<String>>();
+ for (Map.Entry entry : map.entrySet()) {
+ nm.put(entry.getKey().toString(), toStringSet((Collection) entry.getValue()));
+ }
+ return nm;
}
- protected void saveBool(Properties props, String key, boolean val) {
- props.setProperty(key, Boolean.toString(val));
+ protected Map<String, Set<Long>> toStringLongSetMap(Map<?,?> map) {
+ Map<String, Set<Long>> nm = new HashMap<String, Set<Long>>();
+ for (Map.Entry entry : map.entrySet()) {
+ nm.put(entry.getKey().toString(), toLongSet((Collection) entry.getValue()));
+ }
+ return nm;
}
- protected Set<String> toStringSet(Set<Long> set) {
+ protected Set<String> toStringSet(Collection<?> col) {
Set<String> ns = new TreeSet<String>();
- for (long l : set) {
- ns.add(Long.toString(l));
+ for (Object o : col) {
+ ns.add(o.toString());
}
return ns;
}
- protected Set<Long> toLongSet(Set<String> set) {
+ protected Set<Long> toLongSet(Collection<?> set) {
Set<Long> ns = new TreeSet<Long>();
- for (String s : set) {
- ns.add(Long.parseLong(s));
+ for (Object o : set) {
+ ns.add(toLong(o));
}
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()));
+ protected Map<Long, Long> toLongLongMap(Map<?,?> map) {
+ Map<Long, Long> nm = new HashMap<Long, Long>();
+ for (Map.Entry entry : map.entrySet()) {
+ nm.put(toLong(entry.getKey()), toLong(entry.getValue()));
}
return nm;
}
- protected Map<String, Long> toStringLongMap(Map<String, String> map) {
+ protected Map<String, Long> toStringLongMap(Map<?,?> 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()));
+ for (Map.Entry entry : map.entrySet()) {
+ nm.put(entry.getKey().toString(), toLong(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);
- }
+ static long toLong(Object o) {
+ if (o instanceof Number) {
+ return ((Number) o).longValue();
+ } else {
+ return Long.parseLong(o.toString());
}
- return l;
}
-
- protected void close(Closeable closeable) {
+ static void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index cba27fb..78a85dc 100644
--- 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
@@ -17,6 +17,8 @@
package org.apache.karaf.features.internal.util;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.Map;
@@ -25,6 +27,12 @@ import java.util.Map;
*/
public class JsonWriter {
+ public static void write(OutputStream stream, Object value) throws IOException {
+ Writer writer = new OutputStreamWriter(stream);
+ write(writer, value);
+ writer.flush();
+ }
+
public static void write(Writer writer, Object value) throws IOException {
if (value instanceof Map) {
writeObject(writer, (Map) value);
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/util/MapUtils.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/MapUtils.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/MapUtils.java
new file mode 100644
index 0000000..455ceda
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/MapUtils.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.internal.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class MapUtils {
+
+ public static <S, T> Map<S, Set<T>> invert(Map<T, S> map) {
+ Map<S, Set<T>> inverted = new HashMap<S, Set<T>>();
+ for (Map.Entry<T, S> entry : map.entrySet()) {
+ addToMapSet(inverted, entry.getValue(), entry.getKey());
+ }
+ return inverted;
+ }
+
+ public static <S, T> Map<S, Set<T>> copyMapSet(Map<S, Set<T>> from) {
+ Map<S, Set<T>> to = new HashMap<S, Set<T>>();
+ copyMapSet(from, to);
+ return to;
+ }
+
+ public static <S, T> void copyMapSet(Map<S, Set<T>> from, Map<S, Set<T>> to) {
+ for (Map.Entry<S, Set<T>> entry : from.entrySet()) {
+ to.put(entry.getKey(), new HashSet<T>(entry.getValue()));
+ }
+ }
+
+ public static <S, T> void addToMapSet(Map<S, Set<T>> map, S key, T value) {
+ Set<T> values = map.get(key);
+ if (values == null) {
+ values = new HashSet<T>();
+ map.put(key, values);
+ }
+ values.add(value);
+ }
+
+ public static <S, T> void removeFromMapSet(Map<S, Set<T>> map, S key, T value) {
+ Set<T> values = map.get(key);
+ if (values != null) {
+ values.remove(value);
+ if (values.isEmpty()) {
+ map.remove(key);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/eclipse/equinox/internal/region/DigraphHelper.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/eclipse/equinox/internal/region/DigraphHelper.java b/features/core/src/main/java/org/eclipse/equinox/internal/region/DigraphHelper.java
new file mode 100644
index 0000000..cd874b6
--- /dev/null
+++ b/features/core/src/main/java/org/eclipse/equinox/internal/region/DigraphHelper.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.eclipse.equinox.internal.region;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.util.JsonReader;
+import org.apache.karaf.features.internal.util.JsonWriter;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.hooks.bundle.CollisionHook;
+
+public class DigraphHelper {
+
+ private static final String DIGRAPH_FILE = "digraph.json";
+
+ private static final String REGIONS = "regions";
+ private static final String EDGES = "edges";
+ private static final String TAIL = "tail";
+ private static final String HEAD = "head";
+ private static final String POLICY = "policy";
+
+ public static StandardRegionDigraph loadDigraph(BundleContext bundleContext) throws BundleException, IOException, InvalidSyntaxException {
+ StandardRegionDigraph digraph;
+ ThreadLocal<Region> threadLocal = new ThreadLocal<Region>();
+ File digraphFile = bundleContext.getDataFile(DIGRAPH_FILE);
+ if (digraphFile == null || !digraphFile.exists()) {
+ digraph = new StandardRegionDigraph(bundleContext, threadLocal);
+ Region root = digraph.createRegion(FeaturesServiceImpl.ROOT_REGION);
+ for (Bundle bundle : bundleContext.getBundles()) {
+ root.addBundle(bundle);
+ }
+ } else {
+ InputStream in = new FileInputStream(digraphFile);
+ try {
+ digraph = readDigraph(new DataInputStream(in), bundleContext, threadLocal);
+ } finally {
+ in.close();
+ }
+ }
+ return digraph;
+ }
+
+ public static void saveDigraph(BundleContext bundleContext, RegionDigraph digraph) throws IOException {
+ File digraphFile = bundleContext.getDataFile(DIGRAPH_FILE);
+ FileOutputStream out = new FileOutputStream(digraphFile);
+ try {
+ saveDigraph(digraph, out);
+ } catch (Exception e) {
+ // Ignore
+ } finally {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // ignore;
+ }
+ }
+ }
+
+ public static CollisionHook getCollisionHook(StandardRegionDigraph digraph) {
+ return (CollisionHook) digraph.getBundleCollisionHook();
+ }
+
+
+ @SuppressWarnings("unchecked")
+ static StandardRegionDigraph readDigraph(InputStream in, BundleContext bundleContext, ThreadLocal<Region> threadLocal) throws IOException, BundleException, InvalidSyntaxException {
+ StandardRegionDigraph digraph = new StandardRegionDigraph(bundleContext, threadLocal);
+ Map json = (Map) JsonReader.read(in);
+ Map<String, Collection<Number>> regions = (Map<String, Collection<Number>>) json.get(REGIONS);
+ for (Map.Entry<String, Collection<Number>> rmap : regions.entrySet()) {
+ String name = rmap.getKey();
+ Region region = digraph.createRegion(name);
+ for (Number b : rmap.getValue()) {
+ region.addBundle(b.longValue());
+ }
+ }
+ List<Map<String, Object>> edges = (List<Map<String, Object>>) json.get(EDGES);
+ for (Map<String, Object> e : edges) {
+ String tail = (String) e.get(TAIL);
+ String head = (String) e.get(HEAD);
+ Map<String, Collection<String>> policy = (Map<String, Collection<String>>) e.get(POLICY);
+ RegionFilterBuilder builder = digraph.createRegionFilterBuilder();
+ for (Map.Entry<String,Collection<String>> rf : policy.entrySet()) {
+ String ns = rf.getKey();
+ for (String f : rf.getValue()) {
+ builder.allow(ns, f);
+ }
+ }
+ digraph.connect(digraph.getRegion(tail), builder.build(), digraph.getRegion(head));
+ }
+ return digraph;
+ }
+
+ static void saveDigraph(RegionDigraph digraph, OutputStream out) throws IOException {
+ Map<String, Object> json = new LinkedHashMap<String, Object>();
+ Map<String, Set<Long>> regions = new LinkedHashMap<String, Set<Long>>();
+ json.put(REGIONS, regions);
+ for (Region region : digraph.getRegions()) {
+ regions.put(region.getName(), region.getBundleIds());
+ }
+ List<Map<String, Object>> edges = new ArrayList<Map<String, Object>>();
+ json.put(EDGES, edges);
+ for (Region tail : digraph.getRegions()) {
+ for (RegionDigraph.FilteredRegion fr : digraph.getEdges(tail)) {
+ Map<String, Object> edge = new HashMap<String, Object>();
+ edge.put(TAIL, tail.getName());
+ edge.put(HEAD, fr.getRegion().getName());
+ edge.put(POLICY, fr.getFilter().getSharingPolicy());
+ edges.add(edge);
+
+ }
+ }
+ JsonWriter.write(out, json);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index b68b1bb..e28f05f 100644
--- 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
@@ -61,23 +61,26 @@ Feature definition.
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:sequence>
+ <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:element name="scoping" minOccurs="0" maxOccurs="1" type="tns:scoping" />
+ </xs:sequence>
<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" />
@@ -232,6 +235,27 @@ Additional capability of this feature.
</xs:simpleContent>
</xs:complexType>
+ <xs:complexType name="scoping">
+ <xs:annotation>
+ <xs:documentation><![CDATA[
+Scoping definition for this feature.
+ ]]></xs:documentation>
+ </xs:annotation>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="import" type="tns:scopeFilter"/>
+ <xs:element name="export" type="tns:scopeFilter"/>
+ </xs:choice>
+ <xs:attribute name="acceptDependencies" type="xs:boolean"/>
+ </xs:complexType>
+
+ <xs:complexType name="scopeFilter">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="namespace" type="xs:string" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
<xs:simpleType name="featureName">
<xs:annotation>
<xs:documentation><![CDATA[
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 9f7e67b..d94d9b7 100644
--- a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -346,7 +346,7 @@ public class FeaturesServiceTest extends TestBase {
+ " <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);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null, null);
svc.addRepository(uri);
assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "[0.1,0.3)"));
@@ -366,7 +366,7 @@ public class FeaturesServiceTest extends TestBase {
expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
replay(bundleContext);
- FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null, null);
svc.addRepository(uri);
try {
List<String> features = new ArrayList<String>();
@@ -377,7 +377,8 @@ public class FeaturesServiceTest extends TestBase {
svc.installFeatures(new CopyOnWriteArraySet<String>(features),
EnumSet.noneOf(FeaturesService.Option.class));
fail("Call should have thrown an exception");
- } catch (MalformedURLException e) {
+ } catch (Exception t) {
+ // Expected
}
verify(bundleContext);
}
@@ -390,7 +391,7 @@ public class FeaturesServiceTest extends TestBase {
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);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null, null);
try {
svc.addRepository(uri);
fail("exception expected");
@@ -408,7 +409,7 @@ public class FeaturesServiceTest extends TestBase {
+ " <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);
+ FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null, null);
svc.addRepository(uri);
Feature feature = svc.getFeature("f1");
Assert.assertNotNull("No feature named fi found", feature);
[4/6] [KARAF-2923] Region support in features service
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/CandidateComparator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/CandidateComparator.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/CandidateComparator.java
new file mode 100644
index 0000000..74c014b
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/CandidateComparator.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.region;
+
+import java.util.Comparator;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+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(IdentityNamespace.IDENTITY_NAMESPACE))
+ {
+ c = ((Comparable) cap1.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE))
+ .compareTo(cap2.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ if (c == 0)
+ {
+ Version v1 = (!cap1.getAttributes().containsKey(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap1.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ Version v2 = (!cap2.getAttributes().containsKey(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+ ? Version.emptyVersion
+ : (Version) cap2.getAttributes().get(IdentityNamespace.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;
+ }
+ return v1.getQualifier().compareTo(v2.getQualifier());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/ResourceComparator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/ResourceComparator.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/ResourceComparator.java
new file mode 100644
index 0000000..19ba529
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/ResourceComparator.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.region;
+
+import java.util.Comparator;
+
+import org.apache.felix.resolver.Util;
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+
+public class ResourceComparator implements Comparator<Resource> {
+
+ @Override
+ public int compare(Resource o1, Resource o2) {
+ String bsn1 = Util.getSymbolicName(o1);
+ String bsn2 = Util.getSymbolicName(o2);
+ int c = bsn1.compareTo(bsn2);
+ if (c == 0) {
+ Version v1 = Util.getVersion(o1);
+ Version v2 = Util.getVersion(o2);
+ c = v1.compareTo(v2);
+ if (c == 0) {
+ c = o1.hashCode() - o2.hashCode();
+ }
+ }
+ return c;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
new file mode 100644
index 0000000..8d55317
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.region;
+
+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 java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.felix.resolver.Util;
+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.ScopeFilter;
+import org.apache.karaf.features.internal.download.DownloadCallback;
+import org.apache.karaf.features.internal.download.DownloadManager;
+import org.apache.karaf.features.internal.download.Downloader;
+import org.apache.karaf.features.internal.download.StreamProvider;
+import org.apache.karaf.features.internal.resolver.FeatureResource;
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.resolver.ResourceImpl;
+import org.apache.karaf.features.internal.resolver.ResourceUtils;
+import org.eclipse.equinox.region.RegionFilter;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_FEATURE;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_SUBSYSTEM;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.addIdentityRequirement;
+import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet;
+import static org.osgi.framework.namespace.IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE;
+import static org.osgi.framework.namespace.IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+import static org.osgi.framework.namespace.IdentityNamespace.IDENTITY_NAMESPACE;
+
+public class Subsystem extends ResourceImpl {
+
+ private static final String ALL_FILTER = "(|(!(all=*))(all=*))";
+
+ private static final String SUBSYSTEM_FILTER = String.format("(%s=%s)", CAPABILITY_TYPE_ATTRIBUTE, TYPE_SUBSYSTEM);
+
+ private static final String FEATURE_FILTER = String.format("(%s=%s)", CAPABILITY_TYPE_ATTRIBUTE, TYPE_FEATURE);
+
+ private static final String SUBSYSTEM_OR_FEATURE_FILTER = String.format("(|%s%s)", SUBSYSTEM_FILTER, FEATURE_FILTER);
+
+ // Everything is visible
+ private static final Map<String, Set<String>> SHARE_ALL_POLICY =
+ Collections.singletonMap(
+ RegionFilter.VISIBLE_ALL_NAMESPACE,
+ Collections.singleton(ALL_FILTER));
+
+ // Nothing (but systems) is visible
+ private static final Map<String, Set<String>> SHARE_NONE_POLICY =
+ Collections.singletonMap(
+ IDENTITY_NAMESPACE,
+ Collections.singleton(SUBSYSTEM_FILTER));
+
+ private final String name;
+ private final boolean acceptDependencies;
+ private final Subsystem parent;
+ private final Feature feature;
+ private final List<Subsystem> children = new ArrayList<Subsystem>();
+ private final Map<String, Set<String>> importPolicy;
+ private final Map<String, Set<String>> exportPolicy;
+ private final List<Resource> installable = new ArrayList<Resource>();
+ private final Map<String, DependencyInfo> dependencies = new HashMap<String, DependencyInfo>();
+
+ public Subsystem(String name) {
+ super(name, TYPE_SUBSYSTEM, Version.emptyVersion);
+ this.name = name;
+ this.parent = null;
+ this.acceptDependencies = true;
+ this.feature = null;
+ this.importPolicy = SHARE_NONE_POLICY;
+ this.exportPolicy = SHARE_NONE_POLICY;
+ }
+
+ public Subsystem(String name, Feature feature, Subsystem parent) {
+ super(name, TYPE_SUBSYSTEM, Version.emptyVersion);
+ this.name = name;
+ this.parent = parent;
+ this.acceptDependencies = feature.getScoping() != null && feature.getScoping().acceptDependencies();
+ this.feature = feature;
+ if (feature.getScoping() != null) {
+ this.importPolicy = createPolicy(feature.getScoping().getImports());
+ this.importPolicy.put(IDENTITY_NAMESPACE, Collections.singleton(SUBSYSTEM_OR_FEATURE_FILTER));
+ this.exportPolicy = createPolicy(feature.getScoping().getExports());
+ this.exportPolicy.put(IDENTITY_NAMESPACE, Collections.singleton(SUBSYSTEM_OR_FEATURE_FILTER));
+ } else {
+ this.importPolicy = SHARE_ALL_POLICY;
+ this.exportPolicy = SHARE_ALL_POLICY;
+ }
+
+ Map<String, String> dirs = new HashMap<String, String>();
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(IDENTITY_NAMESPACE, feature.getName());
+ attrs.put(CAPABILITY_TYPE_ATTRIBUTE, TYPE_FEATURE);
+ attrs.put(CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(VersionTable.getVersion(feature.getVersion()), true));
+ Requirement requirement = new RequirementImpl(this, IDENTITY_NAMESPACE, dirs, attrs);
+ addRequirement(requirement);
+ }
+
+ public Subsystem(String name, Subsystem parent, boolean acceptDependencies) {
+ super(name, TYPE_SUBSYSTEM, Version.emptyVersion);
+ this.name = name;
+ this.parent = parent;
+ this.acceptDependencies = acceptDependencies;
+ this.feature = null;
+ this.importPolicy = SHARE_ALL_POLICY;
+ this.exportPolicy = SHARE_NONE_POLICY;
+ }
+
+ public List<Resource> getInstallable() {
+ return installable;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Subsystem getParent() {
+ return parent;
+ }
+
+ public Collection<Subsystem> getChildren() {
+ return children;
+ }
+
+ public Subsystem getChild(String name) {
+ for (Subsystem child : children) {
+ if (child.getName().equals(name)) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ public boolean isAcceptDependencies() {
+ return acceptDependencies;
+ }
+
+ public Map<String, Set<String>> getImportPolicy() {
+ return importPolicy;
+ }
+
+ public Map<String, Set<String>> getExportPolicy() {
+ return exportPolicy;
+ }
+
+ public Feature getFeature() {
+ return feature;
+ }
+
+ public Subsystem createSubsystem(String name, boolean acceptDependencies) {
+ if (feature != null) {
+ throw new UnsupportedOperationException("Can not create application subsystems inside a feature subsystem");
+ }
+ // Create subsystem
+ Subsystem as = new Subsystem(getName() + "/" + name, this, acceptDependencies);
+ children.add(as);
+ // Add a requirement to force its resolution
+ Capability identity = as.getCapabilities(IDENTITY_NAMESPACE).iterator().next();
+ Object bsn = identity.getAttributes().get(IDENTITY_NAMESPACE);
+ Requirement requirement = new RequirementImpl(this, IDENTITY_NAMESPACE,
+ Collections.<String,String>emptyMap(),
+ Collections.singletonMap(IDENTITY_NAMESPACE, bsn));
+ addRequirement(requirement);
+ // Add it to repo
+ installable.add(as);
+ return as;
+ }
+
+ public void addSystemResource(Resource resource) {
+ installable.add(resource);
+ }
+
+ public void requireFeature(String name, String range) {
+ ResourceUtils.addIdentityRequirement(this, name, TYPE_FEATURE, range);
+ }
+
+ @SuppressWarnings("InfiniteLoopStatement")
+ public void preResolve(Collection<Feature> features,
+ DownloadManager manager,
+ String featureResolutionRange) throws Exception {
+ for (Subsystem child : children) {
+ child.preResolve(features, manager, featureResolutionRange);
+ }
+ List<Requirement> processed = new ArrayList<Requirement>();
+ while (true) {
+ List<Requirement> requirements = getRequirements(IDENTITY_NAMESPACE);
+ requirements.removeAll(processed);
+ if (requirements.isEmpty()) {
+ break;
+ }
+ for (Requirement requirement : requirements) {
+ String name = (String) requirement.getAttributes().get(IDENTITY_NAMESPACE);
+ String type = (String) requirement.getAttributes().get(CAPABILITY_TYPE_ATTRIBUTE);
+ VersionRange range = (VersionRange) requirement.getAttributes().get(CAPABILITY_VERSION_ATTRIBUTE);
+ if (TYPE_FEATURE.equals(type)) {
+ for (Feature feature : features) {
+ if (feature.getName().equals(name)
+ && (range == null || range.contains(VersionTable.getVersion(feature.getVersion())))) {
+ if (feature != this.feature) {
+ String ssName = this.name + "#" + (feature.hasVersion() ? feature.getName() + "-" + feature.getVersion() : feature.getName());
+ Subsystem fs = getChild(ssName);
+ if (fs == null) {
+ fs = new Subsystem(ssName, feature, this);
+ fs.preResolve(features, manager, featureResolutionRange);
+ installable.add(fs);
+ children.add(fs);
+ }
+ }
+ }
+ }
+ }
+ processed.add(requirement);
+ }
+ }
+ if (feature != null) {
+ final Map<String, Resource> bundles = new ConcurrentHashMap<String, Resource>();
+ final Downloader downloader = manager.createDownloader();
+ final Map<BundleInfo, Boolean> infos = new HashMap<BundleInfo, Boolean>();
+ for (Conditional cond : feature.getConditional()) {
+ for (final BundleInfo bi : cond.getBundles()) {
+ infos.put(bi, false);
+ }
+ }
+ for (BundleInfo bi : feature.getBundles()) {
+ infos.put(bi, true);
+ }
+ for (Map.Entry<BundleInfo, Boolean> entry : infos.entrySet()) {
+ final BundleInfo bi = entry.getKey();
+ final String loc = bi.getLocation();
+ final boolean mandatory = entry.getValue();
+ downloader.download(loc, new DownloadCallback() {
+ @Override
+ public void downloaded(StreamProvider provider) throws Exception {
+ ResourceImpl res = createResource(loc, provider.getMetadata());
+ bundles.put(loc, res);
+ if (bi.isDependency()) {
+ addDependency(res, false);
+ } else {
+ doAddDependency(res, mandatory);
+ }
+ }
+ });
+ }
+ downloader.await();
+ for (Dependency dep : feature.getDependencies()) {
+ Subsystem ss = this;
+ while (!ss.isAcceptDependencies()) {
+ ss = ss.getParent();
+ }
+ ss.requireFeature(dep.getName(), dep.getVersion());
+ }
+ for (Conditional cond : feature.getConditional()) {
+ FeatureResource resCond = FeatureResource.build(feature, cond, featureResolutionRange, bundles);
+ addIdentityRequirement(this, resCond, false);
+ installable.add(resCond);
+ }
+
+ FeatureResource res = FeatureResource.build(feature, featureResolutionRange, bundles);
+ addIdentityRequirement(res, this);
+ installable.add(res);
+ }
+ // Compute dependencies
+ for (DependencyInfo info : dependencies.values()) {
+ installable.add(info.resource);
+ addIdentityRequirement(info.resource, this, info.mandatory);
+ }
+ }
+
+ void addDependency(ResourceImpl resource, boolean mandatory) {
+ if (isAcceptDependencies()) {
+ doAddDependency(resource, mandatory);
+ } else {
+ parent.addDependency(resource, mandatory);
+ }
+ }
+
+ private void doAddDependency(ResourceImpl resource, boolean mandatory) {
+ String id = Util.getSymbolicName(resource) + "|" + Util.getVersion(resource);
+ DependencyInfo info = dependencies.get(id);
+ if (info == null) {
+ info = new DependencyInfo();
+ dependencies.put(id, info);
+ }
+ info.resource = resource;
+ info.mandatory |= mandatory;
+ }
+
+ class DependencyInfo {
+ ResourceImpl resource;
+ boolean mandatory;
+ }
+
+ Map<String, Set<String>> createPolicy(List<? extends ScopeFilter> filters) {
+ Map<String, Set<String>> policy = new HashMap<String, Set<String>>();
+ for (ScopeFilter filter : filters) {
+ addToMapSet(policy, filter.getNamespace(), filter.getFilter());
+ }
+ return policy;
+ }
+
+ ResourceImpl createResource(String uri, Map<String, String> headers) throws Exception {
+ try {
+ return ResourceBuilder.build(uri, headers);
+ } catch (BundleException e) {
+ throw new Exception("Unable to create resource for bundle " + uri, e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
new file mode 100644
index 0000000..e5c6532
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolveContext.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.region;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.resolver.Util;
+import org.apache.karaf.features.internal.repository.StaticRepository;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilter;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+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.Wiring;
+import org.osgi.service.repository.Repository;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolveContext;
+
+public class SubsystemResolveContext extends ResolveContext {
+
+ private final Subsystem root;
+ private final RegionDigraph digraph;
+ private final CandidateComparator candidateComparator = new CandidateComparator();
+
+ private final Map<Resource, Subsystem> resToSub = new HashMap<Resource, Subsystem>();
+ private final Repository repository;
+
+
+ public SubsystemResolveContext(Subsystem root, RegionDigraph digraph) throws BundleException {
+ this.root = root;
+ this.digraph = digraph;
+
+ prepare(root);
+ repository = new StaticRepository(resToSub.keySet());
+ }
+
+ void prepare(Subsystem subsystem) {
+ resToSub.put(subsystem, subsystem);
+ for (Resource res : subsystem.getInstallable()) {
+ resToSub.put(res, subsystem);
+ }
+ for (Subsystem child : subsystem.getChildren()) {
+ prepare(child);
+ }
+ }
+
+ @Override
+ public Collection<Resource> getMandatoryResources() {
+ return Collections.<Resource>singleton(root);
+ }
+
+ @Override
+ public List<Capability> findProviders(Requirement requirement) {
+ List<Capability> caps = new ArrayList<Capability>();
+ Region requirerRegion = getRegion(requirement.getResource());
+ if (requirerRegion != null) {
+ 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);
+ }
+ // Use the digraph to prune non visible capabilities
+ Visitor visitor = new Visitor(caps);
+ requirerRegion.visitSubgraph(visitor);
+ Collection<Capability> allowed = visitor.getAllowed();
+ caps.retainAll(allowed);
+ // Handle cases where the same bundle is requested from both
+ // a subsystem and one of its ascendant. In such cases, we
+ // need to remove the one from the child if it can view
+ // the parent one
+ if (caps.size() > 1) {
+ Map<String, Resource> providers = new HashMap<String, Resource>();
+ for (Capability cap : caps) {
+ Resource resource = cap.getResource();
+ String id = Util.getSymbolicName(resource) + "|" + Util.getVersion(resource);
+ Resource prev = providers.get(id);
+ if (prev != null && prev != resource) {
+ String r1 = getRegion(prev).getName();
+ String r2 = getRegion(resource).getName();
+ int c = r1.compareTo(r2);
+ if (c == 0) {
+ // This should never happen because resource have been
+ // de-duplicated during the pre-resolution phase.
+ throw new IllegalStateException();
+ }
+ resource = c < 0 ? prev : resource;
+ }
+ providers.put(id, resource);
+ }
+ for (Iterator<Capability> it = caps.iterator(); it.hasNext();) {
+ Capability cap = it.next();
+ if (!providers.values().contains(cap.getResource())) {
+ it.remove();
+ }
+ }
+ }
+ // Sort caps
+ Collections.sort(caps, candidateComparator);
+ }
+ return caps;
+ }
+
+ private Subsystem getSubsystem(Resource resource) {
+ return resToSub.get(resource);
+ }
+
+ private Region getRegion(Resource resource) {
+ return digraph.getRegion(getSubsystem(resource).getName());
+ }
+
+ @Override
+ public int insertHostedCapability(List<Capability> capabilities, HostedCapability hostedCapability) {
+ int idx = Collections.binarySearch(capabilities, hostedCapability, candidateComparator);
+ if (idx < 0) {
+ idx = Math.abs(idx + 1);
+ }
+ capabilities.add(idx, hostedCapability);
+ return idx;
+ }
+
+ @Override
+ public boolean isEffective(Requirement requirement) {
+ String resolution = requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE);
+ return requirement.getNamespace().equals(IdentityNamespace.IDENTITY_NAMESPACE)
+ || !Constants.RESOLUTION_OPTIONAL.equals(resolution);
+ }
+
+ @Override
+ public Map<Resource, Wiring> getWirings() {
+ return Collections.emptyMap();
+ }
+
+ class Visitor extends AbstractRegionDigraphVisitor<Capability> {
+
+ Visitor(Collection<Capability> candidates) {
+ super(candidates);
+ }
+
+ @Override
+ protected boolean contains(Region region, Capability candidate) {
+ return region.equals(getRegion(candidate.getResource()));
+ }
+
+ @Override
+ protected boolean isAllowed(Capability candidate, RegionFilter filter) {
+ if (filter.isAllowed(candidate.getNamespace(), candidate.getAttributes())) {
+ return true;
+ }
+ Resource resource = candidate.getResource();
+ List<Capability> identities = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+ if (identities != null && !identities.isEmpty()) {
+ Capability identity = identities.iterator().next();
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, identity.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, identity.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ return filter.isAllowed(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, attrs);
+ }
+ return false;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
new file mode 100644
index 0000000..8a98328
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.region;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+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 java.util.TreeMap;
+
+import org.apache.felix.resolver.ResolverImpl;
+import org.apache.felix.resolver.Util;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.download.DownloadManager;
+import org.apache.karaf.features.internal.download.StreamProvider;
+import org.apache.karaf.features.internal.download.simple.SimpleDownloader;
+import org.apache.karaf.features.internal.resolver.CapabilitySet;
+import org.apache.karaf.features.internal.resolver.SimpleFilter;
+import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
+import org.eclipse.equinox.internal.region.StandardRegionDigraph;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+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.Resolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_FEATURE;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_SUBSYSTEM;
+import static org.apache.karaf.features.internal.util.MapUtils.invert;
+import static org.osgi.framework.namespace.IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE;
+import static org.osgi.framework.namespace.IdentityNamespace.IDENTITY_NAMESPACE;
+import static org.osgi.framework.namespace.IdentityNamespace.TYPE_BUNDLE;
+import static org.osgi.framework.namespace.IdentityNamespace.TYPE_FRAGMENT;
+
+public class SubsystemResolver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SubsystemResolver.class);
+
+ private DownloadManager manager;
+ private RegionDigraph digraph;
+ private Subsystem root;
+ private Map<Resource, List<Wire>> wiring;
+
+ public SubsystemResolver() {
+ this(new SimpleDownloader());
+ }
+
+ public SubsystemResolver(DownloadManager manager) {
+ this.manager = manager;
+ }
+
+ public Map<Resource, List<Wire>> resolve(
+ List<Repository> repositories,
+ Map<String, Set<String>> features,
+ Collection<? extends Resource> system,
+ String featureResolutionRange
+ ) throws Exception {
+ // Build subsystems on the fly
+ for (Map.Entry<String, Set<String>> entry : features.entrySet()) {
+ String[] parts = entry.getKey().split("/");
+ if (root == null) {
+ root = new Subsystem(parts[0]);
+ } else if (!root.getName().equals(parts[0])) {
+ throw new IllegalArgumentException("Can not use multiple roots: " + root.getName() + ", " + parts[0]);
+ }
+ Subsystem ss = root;
+ for (int i = 1; i < parts.length; i++) {
+ ss = getOrCreateChild(ss, parts[i]);
+ }
+ for (String feature : entry.getValue()) {
+ String name, range;
+ int idx = feature.indexOf('/');
+ if (idx >= 0) {
+ name = feature.substring(0, idx);
+ range = feature.substring(idx + 1);
+ } else {
+ name = feature;
+ range = null;
+ }
+ ss.requireFeature(name, range);
+ }
+ }
+ if (root == null) {
+ return Collections.emptyMap();
+ }
+ // Pre-resolve
+ List<Feature> allFeatures = new ArrayList<Feature>();
+ for (Repository repo : repositories) {
+ allFeatures.addAll(Arrays.asList(repo.getFeatures()));
+ }
+ root.preResolve(allFeatures, manager, featureResolutionRange);
+
+ // Add system resources
+ for (Resource res : system) {
+ root.addSystemResource(res);
+ }
+
+ // Populate digraph and resolve
+ digraph = new StandardRegionDigraph(null, null);
+ populateDigraph(digraph, root);
+
+ Resolver resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
+ wiring = resolver.resolve(new SubsystemResolveContext(root, digraph));
+
+ // Fragments are always wired to their host only, so create fake wiring to
+ // the subsystem the host is wired to
+ associateFragments();
+
+ return wiring;
+ }
+
+ public Map<String, StreamProvider> getProviders() {
+ return manager.getProviders();
+ }
+
+ public RegionDigraph getDigraph() {
+ return digraph;
+ }
+
+ public Map<Resource, List<Wire>> getWiring() {
+ return wiring;
+ }
+
+ public Map<String, String> getFlatSubsystemsMap() {
+ Map<String, String> toFlatten = new HashMap<String, String>();
+ findSubsystemsToFlatten(root, toFlatten);
+ return toFlatten;
+ }
+
+ public Map<String, Set<Resource>> getBundlesPerRegions() {
+ return invert(getBundles());
+ }
+
+ public Map<Resource, String> getBundles() {
+ String filter = String.format("(&(%s=*)(|(%s=%s)(%s=%s)))",
+ IDENTITY_NAMESPACE,
+ CAPABILITY_TYPE_ATTRIBUTE, TYPE_BUNDLE,
+ CAPABILITY_TYPE_ATTRIBUTE, TYPE_FRAGMENT);
+ SimpleFilter sf = SimpleFilter.parse(filter);
+ return getResourceMapping(sf);
+ }
+
+ public Map<String, Set<Resource>> getFeaturesPerRegions() {
+ return invert(getFeatures());
+ }
+
+ public Map<Resource, String> getFeatures() {
+ SimpleFilter sf = createFilter(IDENTITY_NAMESPACE, "*",
+ CAPABILITY_TYPE_ATTRIBUTE, TYPE_FEATURE);
+ return getResourceMapping(sf);
+ }
+
+ public Map<String, Set<Resource>> getResourcesPerRegion(SimpleFilter resourceFilter) {
+ return invert(getResourceMapping(resourceFilter));
+ }
+
+ public Map<Resource, String> getResourceMapping(SimpleFilter resourceFilter) {
+ Map<String, String> flats = getFlatSubsystemsMap();
+ Map<Resource, List<Wire>> wiring = getWiring();
+ Map<Resource, String> resources = new HashMap<Resource, String>();
+ SimpleFilter sf = createFilter(IDENTITY_NAMESPACE, "*",
+ CAPABILITY_TYPE_ATTRIBUTE, TYPE_SUBSYSTEM);
+ for (Resource resource : wiring.keySet()) {
+ if (findMatchingCapability(resourceFilter, resource.getCapabilities(null)) != null) {
+ // Find the subsystem where this feature is installed
+ Wire wire = findMatchingWire(sf, wiring.get(resource));
+ if (wire != null) {
+ String region = (String) wire.getCapability().getAttributes().get(IDENTITY_NAMESPACE);
+ region = flats.get(region);
+ resources.put(resource, region);
+ }
+ }
+ }
+ return resources;
+ }
+
+ private void associateFragments() {
+ SimpleFilter sf = createFilter(IDENTITY_NAMESPACE, "*", CAPABILITY_TYPE_ATTRIBUTE, TYPE_SUBSYSTEM);
+ for (Map.Entry<Resource, List<Wire>> entry : wiring.entrySet()) {
+ final Resource resource = entry.getKey();
+ final Requirement requirement = getSubsystemRequirement(resource);
+ if (Util.isFragment(resource)) {
+ List<Wire> wires = entry.getValue();
+ final Resource host = wires.get(0).getProvider();
+ final Wire wire = findMatchingWire(sf, wiring.get(host));
+ if (wire != null) {
+ wires.add(new Wire() {
+ @Override
+ public Capability getCapability() {
+ return wire.getCapability();
+ }
+
+ @Override
+ public Requirement getRequirement() {
+ return requirement;
+ }
+
+ @Override
+ public Resource getProvider() {
+ return wire.getProvider();
+ }
+
+ @Override
+ public Resource getRequirer() {
+ return resource;
+ }
+ });
+ }
+ }
+ }
+ }
+
+ private Requirement getSubsystemRequirement(Resource resource) {
+ for (Requirement requirement : resource.getRequirements(null)) {
+ if (IDENTITY_NAMESPACE.equals(requirement.getNamespace())
+ && TYPE_SUBSYSTEM.equals(requirement.getAttributes().get(CAPABILITY_TYPE_ATTRIBUTE))) {
+ return requirement;
+ }
+ }
+ return null;
+ }
+
+ private Capability findMatchingCapability(SimpleFilter filter, Collection<Capability> caps) {
+ for (Capability cap : caps) {
+ if (CapabilitySet.matches(cap, filter)) {
+ return cap;
+ }
+ }
+ return null;
+ }
+
+ private Wire findMatchingWire(SimpleFilter filter, Collection<Wire> wires) {
+ for (Wire wire : wires) {
+ Capability cap = wire.getCapability();
+ if (CapabilitySet.matches(cap, filter)) {
+ return wire;
+ }
+ }
+ return null;
+ }
+
+ private SimpleFilter createFilter(String... s) {
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ for (int i = 0; i < s.length - 1; i += 2) {
+ attrs.put(s[i], s[i+1]);
+ }
+ return SimpleFilter.convert(attrs);
+
+ }
+
+ private void findSubsystemsToFlatten(Subsystem subsystem, Map<String, String> toFlatten) {
+ Subsystem nonFlat = subsystem;
+ while (isFlat(nonFlat)) {
+ nonFlat = nonFlat.getParent();
+ }
+ toFlatten.put(subsystem.getName(), nonFlat.getName());
+ for (Subsystem child : subsystem.getChildren()) {
+ findSubsystemsToFlatten(child, toFlatten);
+ }
+ }
+
+ private boolean isFlat(Subsystem subsystem) {
+ return subsystem.getFeature() != null && subsystem.getFeature().getScoping() == null;
+ }
+
+ private Subsystem getOrCreateChild(Subsystem ss, String name) {
+ Subsystem child = ss.getChild(name);
+ return child != null ? child : ss.createSubsystem(name, true);
+ }
+
+ private void populateDigraph(RegionDigraph digraph, Subsystem subsystem) throws BundleException, InvalidSyntaxException {
+ Region region = digraph.createRegion(subsystem.getName());
+ if (subsystem.getParent() != null) {
+ Region parent = digraph.getRegion(subsystem.getParent().getName());
+ digraph.connect(region, createRegionFilterBuilder(digraph, subsystem.getImportPolicy()).build(), parent);
+ digraph.connect(parent, createRegionFilterBuilder(digraph, subsystem.getExportPolicy()).build(), region);
+ }
+ for (Subsystem child : subsystem.getChildren()) {
+ populateDigraph(digraph, child);
+ }
+ }
+
+ private RegionFilterBuilder createRegionFilterBuilder(RegionDigraph digraph, Map<String, Set<String>> sharingPolicy) throws InvalidSyntaxException {
+ RegionFilterBuilder result = digraph.createRegionFilterBuilder();
+ for (Map.Entry<String, Set<String>> entry : sharingPolicy.entrySet())
+ for (String filter : entry.getValue())
+ result.allow(entry.getKey(), filter);
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index ad4cc85..0000000
--- a/features/core/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/2705ad88/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
deleted file mode 100644
index e211618..0000000
--- a/features/core/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/2705ad88/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
index e3b0101..99e1253 100644
--- 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
@@ -16,11 +16,9 @@
*/
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;
@@ -28,22 +26,21 @@ 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;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_FEATURE;
+import static org.apache.karaf.features.internal.resolver.ResourceUtils.addIdentityRequirement;
+
/**
*/
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 {
+ public static FeatureResource 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);
+ FeatureResource resource = build(fcond, featureRange, locToRes);
for (String cond : conditional.getCondition()) {
if (cond.startsWith("req:")) {
cond = cond.substring("req:".length());
@@ -66,29 +63,15 @@ public class FeatureResource extends ResourceImpl {
return resource;
}
- public static Resource build(Feature feature, String featureRange, Map<String, Resource> locToRes) throws BundleException {
+ public static FeatureResource 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));
+ addIdentityRequirement(resource, res);
}
}
for (Dependency dep : feature.getDependencies()) {
@@ -104,8 +87,6 @@ public class FeatureResource extends ResourceImpl {
}
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")) {
@@ -113,17 +94,11 @@ public class FeatureResource extends ResourceImpl {
} 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));
+ addIdentityRequirement(resource, name, TYPE_FEATURE, version);
}
public FeatureResource(Feature feature) {
- super(feature.getName(), FeatureNamespace.TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
+ super(feature.getName(), TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
this.feature = feature;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index cdc00d1..20e94fa 100644
--- 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
@@ -24,7 +24,7 @@ import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Resource;
-class IdentityCapability extends BaseClause implements Capability
+public class IdentityCapability extends BaseClause implements Capability
{
private final Resource m_resource;
private final Map<String, String> m_dirs;
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index e2ff793..0000000
--- a/features/core/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/2705ad88/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
index cb2c36a..941ed8c 100644
--- 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
@@ -35,12 +35,13 @@ import org.osgi.framework.wiring.BundleRevision;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
+import org.osgi.service.repository.ContentNamespace;
public class ResourceBuilder {
public static final String RESOLUTION_DYNAMIC = "dynamic";
- public static Resource build(String uri, Map<String, String> headerMap)
+ public static ResourceImpl build(String uri, Map<String, String> headerMap)
throws BundleException {
// Verify that only manifest version 2 is specified.
@@ -74,8 +75,8 @@ public class ResourceBuilder {
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));
+ attrs.put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, uri);
+ resource.addCapability(new CapabilityImpl(resource, ContentNamespace.CONTENT_NAMESPACE, Collections.<String, String>emptyMap(), attrs));
}
// Add a bundle and host capability to all
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceUtils.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceUtils.java
new file mode 100644
index 0000000..03d4fd9
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceUtils.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+import static org.osgi.framework.namespace.IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE;
+import static org.osgi.framework.namespace.IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+import static org.osgi.framework.namespace.IdentityNamespace.IDENTITY_NAMESPACE;
+import static org.osgi.service.repository.ContentNamespace.CAPABILITY_URL_ATTRIBUTE;
+import static org.osgi.service.repository.ContentNamespace.CONTENT_NAMESPACE;
+
+public class ResourceUtils {
+
+ public static final String TYPE_SUBSYSTEM = "karaf.subsystem";
+
+ public static final String TYPE_FEATURE = "karaf.feature";
+
+ public static String getUri(Resource resource) {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps) {
+ if (cap.getNamespace().equals(CONTENT_NAMESPACE)) {
+ return cap.getAttributes().get(CAPABILITY_URL_ATTRIBUTE).toString();
+ }
+ }
+ return null;
+ }
+
+ public static String getFeatureId(Resource resource) {
+ List<Capability> caps = resource.getCapabilities(null);
+ for (Capability cap : caps) {
+ if (cap.getNamespace().equals(IDENTITY_NAMESPACE)) {
+ Map<String, Object> attributes = cap.getAttributes();
+ if (TYPE_FEATURE.equals(attributes.get(CAPABILITY_TYPE_ATTRIBUTE))) {
+ String name = (String) attributes.get(IDENTITY_NAMESPACE);
+ Version version = (Version) attributes.get(CAPABILITY_VERSION_ATTRIBUTE);
+ return version != null ? name + "/" + version : name;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static void addIdentityRequirement(ResourceImpl resource, String name, String type, String range) {
+ Map<String, String> dirs = new HashMap<String, String>();
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ if (name != null) {
+ attrs.put(IDENTITY_NAMESPACE, name);
+ }
+ if (type != null) {
+ attrs.put(CAPABILITY_TYPE_ATTRIBUTE, type);
+ }
+ if (range != null) {
+ attrs.put(CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(range));
+ }
+ resource.addRequirement(new RequirementImpl(resource, IDENTITY_NAMESPACE, dirs, attrs));
+ }
+
+ public static void addIdentityRequirement(ResourceImpl resource, Resource required) {
+ addIdentityRequirement(resource, required, true);
+ }
+
+ public static void addIdentityRequirement(ResourceImpl resource, Resource required, boolean mandatory) {
+ for (Capability cap : required.getCapabilities(null)) {
+ if (cap.getNamespace().equals(IDENTITY_NAMESPACE)) {
+ Map<String, Object> attributes = cap.getAttributes();
+ Map<String, String> dirs = new HashMap<String, String>();
+ dirs.put(Constants.RESOLUTION_DIRECTIVE, mandatory ? Constants.RESOLUTION_MANDATORY : Constants.RESOLUTION_OPTIONAL);
+ Map<String, Object> attrs = new HashMap<String, Object>();
+ attrs.put(IDENTITY_NAMESPACE, attributes.get(IDENTITY_NAMESPACE));
+ attrs.put(CAPABILITY_TYPE_ATTRIBUTE, attributes.get(CAPABILITY_TYPE_ATTRIBUTE));
+ Version version = (Version) attributes.get(CAPABILITY_VERSION_ATTRIBUTE);
+ if (version != null) {
+ attrs.put(CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(version, true));
+ }
+ resource.addRequirement(new RequirementImpl(resource, IDENTITY_NAMESPACE, dirs, attrs));
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index b5158bf..0000000
--- a/features/core/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() {
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 0e9038d..258b44b 100644
--- 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
@@ -45,6 +45,26 @@ public class FeatureConfigInstaller {
this.configAdmin = configAdmin;
}
+ public 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[] parsePid(String pid) {
int n = pid.indexOf('-');
if (n > 0) {
@@ -81,26 +101,6 @@ public class FeatureConfigInstaller {
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;
}
[6/6] git commit: [KARAF-2911] Small fixes to subsystem commands
Posted by gn...@apache.org.
[KARAF-2911] Small fixes to subsystem commands
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/486ad3ac
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/486ad3ac
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/486ad3ac
Branch: refs/heads/master
Commit: 486ad3aca57b364940f8d71d8f520b877ee614e2
Parents: 53ad48f
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 17 16:07:14 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 18 23:33:51 2014 +0200
----------------------------------------------------------------------
.../org/apache/karaf/subsystem/commands/ListAction.java | 10 ++++++++++
.../apache/karaf/subsystem/commands/SubsystemSupport.java | 6 +++++-
2 files changed, 15 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/486ad3ac/subsystem/src/main/java/org/apache/karaf/subsystem/commands/ListAction.java
----------------------------------------------------------------------
diff --git a/subsystem/src/main/java/org/apache/karaf/subsystem/commands/ListAction.java b/subsystem/src/main/java/org/apache/karaf/subsystem/commands/ListAction.java
index 458ff5b..8b7ee12 100644
--- a/subsystem/src/main/java/org/apache/karaf/subsystem/commands/ListAction.java
+++ b/subsystem/src/main/java/org/apache/karaf/subsystem/commands/ListAction.java
@@ -36,6 +36,7 @@ public class ListAction extends SubsystemSupport implements Action {
table.column("SymbolicName");
table.column("Version");
table.column("State");
+ table.column("Type");
table.column("Parents");
table.column("Children");
@@ -45,6 +46,7 @@ public class ListAction extends SubsystemSupport implements Action {
ss.getSymbolicName(),
ss.getVersion(),
ss.getState().toString(),
+ getType(ss),
getSubsytemIds(ss.getParents()),
getSubsytemIds(ss.getChildren())
);
@@ -53,4 +55,12 @@ public class ListAction extends SubsystemSupport implements Action {
return null;
}
+ private String getType(Subsystem subsystem) {
+ String type = subsystem.getType();
+ if (type.startsWith("osgi.subsystem.")) {
+ type = type.substring("osgi.subsystem.".length());
+ }
+ return type;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/486ad3ac/subsystem/src/main/java/org/apache/karaf/subsystem/commands/SubsystemSupport.java
----------------------------------------------------------------------
diff --git a/subsystem/src/main/java/org/apache/karaf/subsystem/commands/SubsystemSupport.java b/subsystem/src/main/java/org/apache/karaf/subsystem/commands/SubsystemSupport.java
index e91461e..c19ebfe 100644
--- a/subsystem/src/main/java/org/apache/karaf/subsystem/commands/SubsystemSupport.java
+++ b/subsystem/src/main/java/org/apache/karaf/subsystem/commands/SubsystemSupport.java
@@ -104,8 +104,12 @@ public abstract class SubsystemSupport {
protected List<Long> getSubsytemIds(Collection<Subsystem> subsystems) {
List<Long> ids = new ArrayList<Long>();
for (Subsystem ss : subsystems) {
- ids.add(ss.getSubsystemId());
+ long id = ss.getSubsystemId();
+ if (!ids.contains(id)) {
+ ids.add(id);
+ }
}
+ Collections.sort(ids);
return ids;
}
[2/6] [KARAF-2923] Region support in features service
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
new file mode 100644
index 0000000..0ef26cb
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/region/SubsystemTest.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.region;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.download.StreamProvider;
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.service.RepositoryImpl;
+import org.apache.karaf.features.internal.download.simple.SimpleDownloader;
+import org.junit.Test;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+
+import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet;
+import static org.junit.Assert.assertEquals;
+
+public class SubsystemTest {
+
+ @Test
+ public void test1() throws Exception {
+ RepositoryImpl repo = new RepositoryImpl(getClass().getResource("data1/features.xml").toURI());
+
+ Map<String, Set<String>> features = new HashMap<String, Set<String>>();
+ addToMapSet(features, "root", "f1");
+ addToMapSet(features, "root/apps1", "f2");
+
+ Map<String, Set<String>> expected = new HashMap<String, Set<String>>();
+ addToMapSet(expected, "root", "a/1.0.0");
+ addToMapSet(expected, "root", "c/1.0.0");
+ addToMapSet(expected, "root/apps1", "b/1.0.0");
+
+ SubsystemResolver resolver = new SubsystemResolver(new TestDownloadManager("data1"));
+ resolver.resolve(Collections.<Repository>singletonList(repo),
+ features,
+ Collections.<Resource>emptyList(),
+ FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
+
+ verify(resolver, expected);
+ }
+
+ @Test
+ public void test2() throws Exception {
+
+ RepositoryImpl repo = new RepositoryImpl(getClass().getResource("data2/features.xml").toURI());
+
+ Map<String, Set<String>> features = new HashMap<String, Set<String>>();
+ addToMapSet(features, "root/apps1", "f1");
+ addToMapSet(features, "root/apps1", "f3");
+ addToMapSet(features, "root/apps2", "f1");
+
+ Map<String, Set<String>> expected = new HashMap<String, Set<String>>();
+ addToMapSet(expected, "root/apps1", "c/1.0.0");
+ addToMapSet(expected, "root/apps1", "b/1.0.0");
+ addToMapSet(expected, "root/apps1", "e/1.0.0");
+ addToMapSet(expected, "root/apps1#f1", "a/1.0.0");
+ addToMapSet(expected, "root/apps1#f1", "d/1.0.0");
+ addToMapSet(expected, "root/apps2", "b/1.0.0");
+ addToMapSet(expected, "root/apps2", "c/1.0.0");
+ addToMapSet(expected, "root/apps2#f1", "a/1.0.0");
+
+ SubsystemResolver resolver = new SubsystemResolver(new TestDownloadManager("data2"));
+ resolver.resolve(Collections.<Repository>singletonList(repo),
+ features,
+ Collections.<Resource>emptyList(),
+ FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
+
+ verify(resolver, expected);
+ }
+
+ private void verify(SubsystemResolver resolver, Map<String, Set<String>> expected) {
+ Map<String, Set<String>> mapping = getBundleNamesPerRegions(resolver);
+ if (!expected.equals(mapping)) {
+ dumpBundles(resolver);
+ dumpWiring(resolver);
+ assertEquals("Resolution failed", expected, mapping);
+ }
+ }
+
+ private void dumpBundles(SubsystemResolver resolver) {
+ System.out.println("Bundle mapping");
+ Map<String, Set<Resource>> bundles = resolver.getBundlesPerRegions();
+ for (Map.Entry<String, Set<Resource>> entry : bundles.entrySet()) {
+ System.out.println(" " + entry.getKey());
+ for (Resource b : entry.getValue()) {
+ System.out.println(" " + b);
+ }
+ }
+ }
+
+ private Map<String, Set<String>> getBundleNamesPerRegions(SubsystemResolver resolver) {
+ Map<String, Set<String>> mapping = new HashMap<String, Set<String>>();
+ Map<String, Set<Resource>> bundles = resolver.getBundlesPerRegions();
+ for (Map.Entry<String,Set<Resource>> entry : bundles.entrySet()) {
+ for (Resource r : entry.getValue()) {
+ addToMapSet(mapping, entry.getKey(), r.toString());
+ }
+ }
+ return mapping;
+ }
+
+
+ private void dumpWiring(SubsystemResolver resolver) {
+ System.out.println("Wiring");
+ Map<Resource, List<Wire>> wiring = resolver.getWiring();
+ List<Resource> resources = new ArrayList<Resource>(wiring.keySet());
+ Collections.sort(resources, new Comparator<Resource>() {
+ @Override
+ public int compare(Resource o1, Resource o2) {
+ return getName(o1).compareTo(getName(o2));
+ }
+ });
+ for (Resource resource : resources) {
+ System.out.println(" " + getName(resource));
+ for (Wire wire : wiring.get(resource)) {
+ System.out.println(" " + wire);
+ }
+ }
+ }
+
+ private String getName(Resource resource) {
+ Capability cap = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
+ return cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE) + ": "
+ + cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/"
+ + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ }
+
+ class TestDownloadManager extends SimpleDownloader {
+
+ private final String dir;
+
+ TestDownloadManager(String dir) {
+ this.dir = dir;
+ }
+
+ @Override
+ protected StreamProvider createProvider(String location) throws MalformedURLException {
+ return new TestProvider(location);
+ }
+
+ class TestProvider implements StreamProvider {
+ private final IOException exception;
+ private final Map<String, String> headers;
+ private final byte[] data;
+
+ TestProvider(String location) {
+ Map<String, String> headers = null;
+ byte[] data = null;
+ IOException exception = null;
+ try {
+ Manifest man = new Manifest(getClass().getResourceAsStream(dir +"/" + location + ".mf"));
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ JarOutputStream jos = new JarOutputStream(baos, man);
+ jos.close();
+ data = baos.toByteArray();
+ headers = new HashMap<String, String>();
+ for (Map.Entry attr : man.getMainAttributes().entrySet()) {
+ headers.put(attr.getKey().toString(), attr.getValue().toString());
+ }
+ } catch (IOException e) {
+ exception = e;
+ }
+ this.headers = headers;
+ this.data = data;
+ this.exception = exception;
+ }
+
+ @Override
+ public InputStream open() throws IOException {
+ if (exception != null)
+ throw exception;
+ return new ByteArrayInputStream(data);
+ }
+
+ @Override
+ public Map<String, String> getMetadata() throws IOException {
+ if (exception != null)
+ throw exception;
+ return headers;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index b8b5fc0..3627c0f 100644
--- 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
@@ -49,7 +49,7 @@ public class FeaturesServiceImplTest extends TestBase {
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) {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, "", null, null, null) {
protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
return features;
}
@@ -60,7 +60,7 @@ public class FeaturesServiceImplTest extends TestBase {
@Test
public void testGetFeatureStripVersion() throws Exception {
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, "", null, null, null) {
protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
return features(feature("transaction", "1.0.0"));
}
@@ -72,7 +72,7 @@ public class FeaturesServiceImplTest extends TestBase {
@Test
public void testGetFeatureNotAvailable() throws Exception {
- final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, "", null, null, null) {
protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
return features(feature("transaction", "1.0.0"));
}
@@ -86,7 +86,7 @@ public class FeaturesServiceImplTest extends TestBase {
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) {
+ final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, "", null, null, null) {
protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
return features;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index c4976cf..2d4d4ae 100644
--- 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
@@ -16,36 +16,25 @@
*/
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.apache.karaf.features.internal.resolver.ResourceUtils.getUri;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
public class OverridesTest {
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/java/org/apache/karaf/features/internal/service/StateStorageTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/StateStorageTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/StateStorageTest.java
new file mode 100644
index 0000000..5bee904
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/StateStorageTest.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.service;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class StateStorageTest {
+
+ @Test
+ public void testStoreLoad() throws Exception {
+
+ State oldState = new State();
+ oldState.bootDone.set(true);
+ oldState.bundleChecksums.put(4l, 32794l);
+ oldState.features.put("bar", Collections.singleton("f1"));
+ oldState.managedBundles.put("reg", Collections.singleton(32l));
+ oldState.managedBundles.put("reg2", new HashSet<Long>(Arrays.asList(24l, 43l)));
+ oldState.repositories.add("repo");
+
+ TestStorage storage = new TestStorage();
+
+ storage.save(oldState);
+
+ System.out.println(storage.baos.toString());
+
+ State newState = new State();
+ storage.load(newState);
+
+ assertEquals(oldState.bootDone.get(), newState.bootDone.get());
+ assertEquals(oldState.bundleChecksums, newState.bundleChecksums);
+ assertEquals(oldState.features, newState.features);
+ assertEquals(oldState.managedBundles, newState.managedBundles);
+ assertEquals(oldState.repositories, newState.repositories);
+ }
+
+ static class TestStorage extends StateStorage {
+ ByteArrayOutputStream baos;
+
+ @Override
+ protected InputStream getInputStream() throws IOException {
+ if (baos != null) {
+ return new ByteArrayInputStream(baos.toByteArray());
+ }
+ return null;
+ }
+
+ @Override
+ protected OutputStream getOutputStream() throws IOException {
+ baos = new ByteArrayOutputStream();
+ return baos;
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/a.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/a.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/a.mf
new file mode 100644
index 0000000..b5e522b
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/a.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: a
+Bundle-Version: 1.0.0
+Require-Capability: ns;filter:="(ns=c)"
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/b.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/b.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/b.mf
new file mode 100644
index 0000000..2ee6678
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/b.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: b
+Bundle-Version: 1.0.0
+Require-Capability: ns;filter:="(ns=c)"
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/c.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/c.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/c.mf
new file mode 100644
index 0000000..8c731fb
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/c.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: c
+Bundle-Version: 1.0.0
+Provide-Capability: ns;ns=c
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/features.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/features.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/features.xml
new file mode 100644
index 0000000..72c261c
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data1/features.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.
+
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+
+ <feature name="f1">
+ <bundle dependency="true">c</bundle>
+ <bundle>a</bundle>
+ </feature>
+
+ <feature name="f2">
+ <bundle dependency="true">c</bundle>
+ <bundle>b</bundle>
+ </feature>
+
+</features>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/a.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/a.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/a.mf
new file mode 100644
index 0000000..99ed0c4
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/a.mf
@@ -0,0 +1,7 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: a
+Bundle-Version: 1.0.0
+Provide-Capability: ns;ns=a
+Require-Capability: ns;filter:="(ns=b)"
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/b.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/b.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/b.mf
new file mode 100644
index 0000000..f66fd1e
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/b.mf
@@ -0,0 +1,7 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: b
+Bundle-Version: 1.0.0
+Provide-Capability: ns;ns=b
+Require-Capability: ns;filter:="(ns=c)"
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/c.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/c.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/c.mf
new file mode 100644
index 0000000..8c731fb
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/c.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: c
+Bundle-Version: 1.0.0
+Provide-Capability: ns;ns=c
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/d.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/d.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/d.mf
new file mode 100644
index 0000000..b1172fa
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/d.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: d
+Bundle-Version: 1.0.0
+
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/e.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/e.mf b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/e.mf
new file mode 100644
index 0000000..42b5ff9
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/e.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: e
+Bundle-Version: 1.0.0
+
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/features.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/features.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/features.xml
new file mode 100644
index 0000000..b1cc8d6
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/region/data2/features.xml
@@ -0,0 +1,42 @@
+<?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">
+ <feature>f2</feature>
+ <bundle dependency="true">b</bundle>
+ <bundle>a</bundle>
+ <conditional>
+ <condition>f3</condition>
+ <bundle>d</bundle>
+ </conditional>
+ <scoping acceptDependencies="false">
+ <import namespace="ns">(ns=b)</import>
+ <export namespace="ns">(ns=a)</export>
+ </scoping>
+ </feature>
+
+ <feature name="f2">
+ <bundle>c</bundle>
+ </feature>
+
+ <feature name="f3">
+ <bundle>e</bundle>
+ </feature>
+
+</features>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index b62ffda..8165d14 100644
--- 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
@@ -30,6 +30,17 @@
<capability>
service-reference;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
</capability>
+ <scoping>
+ <export namespace="osgi.service">
+ (objectClass=org.apache.aries.proxy.ProxyManager)
+ </export>
+ <export namespace="osgi.wiring.package">
+ (|(osgi.wiring.package=org.apache.aries.proxy)(osgi.wiring.package=org.apache.aries.proxy.*))
+ </export>
+ <import namespace="org.eclipse.equinox.allow.all">
+ (|(!(all=*))(all=*))
+ </import>
+ </scoping>
</feature>
</features>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/itests/src/test/java/org/apache/karaf/itests/RegionTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/RegionTest.java b/itests/src/test/java/org/apache/karaf/itests/RegionTest.java
deleted file mode 100644
index 0af20fe..0000000
--- a/itests/src/test/java/org/apache/karaf/itests/RegionTest.java
+++ /dev/null
@@ -1,48 +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.itests;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
-import org.ops4j.pax.exam.spi.reactors.PerClass;
-
-@RunWith(PaxExam.class)
-@ExamReactorStrategy(PerClass.class)
-public class RegionTest extends KarafTestSupport {
-
- @Test
- public void infoCommand() throws Exception {
- installAndAssertFeature("region");
-
- String infoOutput = executeCommand("region:info");
- System.out.println(infoOutput);
- assertTrue("Region org.eclipse.equinox.region.kernel should be present", infoOutput.contains("org.eclipse.equinox.region.kernel"));
- assertTrue("Region org.apache.karaf.region.application should be present", infoOutput.contains("org.apache.karaf.region.application"));
- }
-
- @Test
- public void addRegionCommand() throws Exception {
- installAndAssertFeature("region");
-
- System.out.println(executeCommand("region:region-add itest"));
- String infoOutput = executeCommand("region:info");
- System.out.println(infoOutput);
- assertTrue("Region itest should be present", infoOutput.contains("itest"));
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/itests/src/test/java/org/apache/karaf/itests/features/StandardFeaturesTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/features/StandardFeaturesTest.java b/itests/src/test/java/org/apache/karaf/itests/features/StandardFeaturesTest.java
index c0e2086..3a1e741 100644
--- a/itests/src/test/java/org/apache/karaf/itests/features/StandardFeaturesTest.java
+++ b/itests/src/test/java/org/apache/karaf/itests/features/StandardFeaturesTest.java
@@ -60,11 +60,6 @@ public class StandardFeaturesTest extends KarafTestSupport {
}
@Test
- public void installRegionFeature() throws Exception {
- installAssertAndUninstallFeatures("region");
- }
-
- @Test
public void installPackageFeature() throws Exception {
installAssertAndUninstallFeatures("package");
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2ef129f..0cc1447 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,7 +40,6 @@
<module>main</module>
<module>features</module>
<module>kar</module>
- <module>region</module>
<module>bundle</module>
<module>config</module>
<module>instance</module>
@@ -526,11 +525,6 @@
<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>
<dependency>
<groupId>org.apache.karaf.diagnostic</groupId>
@@ -563,12 +557,6 @@
</dependency>
<dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.core</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>${project.version}</version>
@@ -2248,6 +2236,8 @@
<exclude>manual/**/*.css</exclude>
<exclude>manual/**/*.ssp</exclude>
<exclude>manual/**/*.conf</exclude>
+ <!-- test manifests -->
+ <exclude>**/*.mf</exclude>
</excludes>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/NOTICE
----------------------------------------------------------------------
diff --git a/region/NOTICE b/region/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/region/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/2705ad88/region/pom.xml
----------------------------------------------------------------------
diff --git a/region/pom.xml b/region/pom.xml
deleted file mode 100644
index 2375fcc..0000000
--- a/region/pom.xml
+++ /dev/null
@@ -1,136 +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</groupId>
- <artifactId>karaf</artifactId>
- <version>4.0.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.core</artifactId>
- <packaging>bundle</packaging>
- <name>Apache Karaf :: Region :: Persistence</name>
- <description>This bundle provides an xml regions model and install/dump actions.</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>
- <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-api</artifactId>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.core</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.eclipse.equinox</groupId>
- <artifactId>region</artifactId>
- <version>1.0.0.v20110506</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.core</artifactId>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.apache.aries</groupId>
- <artifactId>org.apache.aries.util</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymock</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-jdk14</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>
- <Bundle-Activator>
- org.apache.karaf.region.persist.internal.Activator
- </Bundle-Activator>
- <Private-Package>
- org.apache.karaf.region.commands,
- org.apache.karaf.region.commands.util,
- org.apache.karaf.region.persist.internal.*,
- org.apache.karaf.util.tracker
- </Private-Package>
- <Karaf-Commands>*</Karaf-Commands>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
deleted file mode 100644
index 30af1e0..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
+++ /dev/null
@@ -1,52 +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.region.commands;
-
-import java.util.List;
-
-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.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "region", name = "bundle-add", description = "Adds a list of known bundles by id to a specified region.")
-@Service
-public class AddBundleCommand extends RegionCommandSupport {
-
- @Argument(index = 0, name = "region", description = "Region to add the bundles to", required = true, multiValued = false)
- String region;
-
- @Argument(index = 1, name = "bundles", description = "Bundles by id to add to the region", required = true, multiValued = true)
- List<Long> ids;
-
- protected void doExecute(RegionDigraph regionDigraph) throws Exception {
- Region r = getRegion(regionDigraph, region);
- for (Long id : ids) {
- for (Region existing: regionDigraph.getRegions()) {
- if (existing.contains(id)) {
- Bundle b = bundleContext.getBundle(id);
- System.out.println("Removing bundle " + id + " from region " + existing.getName());
- existing.removeBundle(b);
- break;
- }
- }
- r.addBundle(id);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
deleted file mode 100644
index ec3766d..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
+++ /dev/null
@@ -1,169 +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.region.commands;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.aries.util.VersionRange;
-import org.apache.aries.util.manifest.ManifestHeaderProcessor;
-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.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilter;
-import org.eclipse.equinox.region.RegionFilterBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-
-@Command(scope = "region", name = "filter-add", description = "Adds a filter between two regions.")
-@Service
-public class AddFilterCommand extends RegionCommandSupport {
-
- @Argument(index = 0, name = "from", description = "The from region.", required = true, multiValued = false)
- String fromRegion;
-
- @Argument(index = 1, name = "to", description = "The to region.", required = true, multiValued = false)
- String toRegion;
-
- @Argument(index = 2, name = "items", description = "The bundles by id and packages with version to allow.", required = false, multiValued = true)
- List<String> items;
-
- protected void doExecute(RegionDigraph regionDigraph) throws Exception {
- Region rFrom = getRegion(regionDigraph, fromRegion);
- Region rTo = getRegion(regionDigraph, toRegion);
- RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
- BundleContext framework = bundleContext.getBundle(0).getBundleContext();
- if (items != null) {
- for (String item : items) {
- try {
- long id = Long.parseLong(item);
- Bundle b = framework.getBundle(id);
- builder.allow("osgi.wiring.bundle", "(osgi.wiring.bundle=" + b.getSymbolicName() + ")");
- } catch (NumberFormatException e) {
- for (Map.Entry<String, Map<String, String>> parsed: ManifestHeaderProcessor.parseImportString(item).entrySet()) {
- String packageName = parsed.getKey();
- Map<String, String> attributes = new HashMap<String, String>(parsed.getValue());
- attributes.put("osgi.wiring.package", packageName);
- String filter = generateFilter(attributes);
- System.out.println("adding filter " + filter);
- builder.allow("osgi.wiring.package", filter);
- }
- }
-
- }
- }
- RegionFilter f = builder.build();
- regionDigraph.connect(rFrom, f, rTo);
- }
-
- //from aries util, with obr specific weirdness removed
- public static String generateFilter(Map<String, String> attribs) {
- StringBuilder filter = new StringBuilder("(&");
- boolean realAttrib = false;
- StringBuffer realAttribs = new StringBuffer();
-
- if (attribs == null) {
- attribs = new HashMap<String, String>();
- }
-
- for (Map.Entry<String, String> attrib : attribs.entrySet()) {
- String attribName = attrib.getKey();
-
- if (attribName.endsWith(":")) {
- // skip all directives. It is used to affect the attribs on the
- // filter xml.
- } else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
- || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
- // version and bundle-version attrib requires special
- // conversion.
- realAttrib = true;
-
- VersionRange vr = ManifestHeaderProcessor
- .parseVersionRange(attrib.getValue());
-
- filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
-
- if (vr.getMaximumVersion() != null) {
- filter.append(")(" + attribName + "<=");
- filter.append(vr.getMaximumVersion());
- }
-
- if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
- filter.append(")(!(" + attribName + "=");
- filter.append(vr.getMinimumVersion());
- filter.append(")");
- }
-
- if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
- filter.append(")(!(" + attribName + "=");
- filter.append(vr.getMaximumVersion());
- filter.append(")");
- }
- filter.append(")");
-
- } else if (Constants.OBJECTCLASS.equals(attribName)) {
- realAttrib = true;
- // objectClass has a "," separated list of interfaces
- String[] values = attrib.getValue().split(",");
- for (String s : values)
- filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
-
- } else {
- // attribName was not version..
- realAttrib = true;
-
- filter.append("(" + attribName + "=" + attrib.getValue() + ")");
- // store all attributes in order to build up the mandatory
- // filter and separate them with ", "
- // skip bundle-symbolic-name in the mandatory directive query
- if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
- .equals(attribName)) {
- realAttribs.append(attribName);
- realAttribs.append(", ");
- }
- }
- }
-
- // Prune (& off the front and ) off end
- String filterString = filter.toString();
- int openBraces = 0;
- for (int i = 0; openBraces < 3; i++) {
- i = filterString.indexOf('(', i);
- if (i == -1) {
- break;
- } else {
- openBraces++;
- }
- }
- if (openBraces < 3 && filterString.length() > 2) {
- filter.delete(0, 2);
- } else {
- filter.append(")");
- }
-
- String result = "";
- if (realAttrib != false) {
- result = filter.toString();
- }
- return result;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
deleted file mode 100644
index 22c817b..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
+++ /dev/null
@@ -1,38 +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.region.commands;
-
-import java.util.List;
-
-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.eclipse.equinox.region.RegionDigraph;
-
-@Command(scope = "region", name = "region-add", description = "Adds a list of regions to the region digraph service.")
-@Service
-public class AddRegionCommand extends RegionCommandSupport {
-
- @Argument(index = 0, name = "name", description = "Regions to add to the region digraph service separated by whitespaces.", required = true, multiValued = true)
- List<String> regions;
-
- protected void doExecute(RegionDigraph regionDigraph) throws Exception {
- for (String region : regions) {
- regionDigraph.createRegion(region);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java b/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
deleted file mode 100644
index 7c71e36..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
+++ /dev/null
@@ -1,117 +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.region.commands;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-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.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilter;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "region", name = "info", description = "Prints information about region digraph.")
-@Service
-public class InfoCommand extends RegionCommandSupport {
-
- @Option(name = "-v", aliases = "--verbose", required = false, description = "Show all info.")
- boolean verbose;
-
- @Option(name = "-b", aliases = "--bundles", required = false, description = "Show bundles in each region.")
- boolean bundles;
-
- @Option(name = "-f", aliases = "--filters", required = false, description = "Show filters.")
- boolean filters;
-
- @Option(name = "-n", aliases = "--namespaces", required = false, description = "Show namespaces in each filter.")
- boolean namespaces;
-
- @Argument(index = 0, name = "regions", description = "Regions to provide detailed info for.", required = false, multiValued = true)
- List<String> regions;
-
- protected void doExecute(RegionDigraph regionDigraph) throws Exception {
- System.out.println("Regions");
- if (regions == null) {
- for (Region region : regionDigraph.getRegions()) {
- showRegion(region);
- }
- } else {
- bundles = true;
- filters = true;
- namespaces = true;
- for (String regionName : regions) {
- Region region = regionDigraph.getRegion(regionName);
- if (region == null) {
- System.out.println("No region " + regionName);
- } else {
- showRegion(region);
- }
- }
- }
- }
-
- private void showRegion(Region region) {
- System.out.println(region.getName());
- if (verbose || bundles) {
- for (Long id : region.getBundleIds()) {
- Bundle b = bundleContext.getBundle(id);
- System.out.println(" " + id + " " + getStateString(b) + b);
- }
- }
- if (verbose || filters || namespaces) {
- for (RegionDigraph.FilteredRegion f : region.getEdges()) {
- System.out.println(" filter to " + f.getRegion().getName());
- if (verbose || namespaces) {
- RegionFilter rf = f.getFilter();
- for (Map.Entry<String, Collection<String>> policy : rf.getSharingPolicy().entrySet()) {
- String namespace = policy.getKey();
- System.out.println(" namespace: " + namespace);
- for (String e : policy.getValue()) {
- System.out.println(" " + e);
- }
- }
- }
- }
- }
- }
-
- public String getStateString(Bundle bundle) {
- if (bundle == null) {
- return "Bundle null";
- }
- int state = bundle.getState();
- if (state == Bundle.ACTIVE) {
- return "Active ";
- } else if (state == Bundle.INSTALLED) {
- return "Installed ";
- } else if (state == Bundle.RESOLVED) {
- return "Resolved ";
- } else if (state == Bundle.STARTING) {
- return "Starting ";
- } else if (state == Bundle.STOPPING) {
- return "Stopping ";
- } else {
- return "Unknown ";
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java b/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
deleted file mode 100644
index bcdfb6c..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
+++ /dev/null
@@ -1,79 +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.region.commands;
-
-import java.io.PrintStream;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-
-public abstract class RegionCommandSupport implements Action {
-
- protected static final char VERSION_DELIM = ',';
-
- @Reference
- BundleContext bundleContext;
-
- @Override
- public Object execute() throws Exception {
- // Get repository instance service.
- ServiceReference ref = bundleContext.getServiceReference(RegionDigraph.class.getName());
- if (ref == null) {
- System.out.println("RegionDigraph service is unavailable.");
- return null;
- }
- try {
- RegionDigraph admin = (RegionDigraph) bundleContext.getService(ref);
- if (admin == null) {
- System.out.println("RegionDigraph service is unavailable.");
- return null;
- }
-
- doExecute(admin);
- }
- finally {
- bundleContext.ungetService(ref);
- }
- return null;
- }
-
- abstract void doExecute(RegionDigraph admin) throws Exception;
-
- protected void printUnderline(PrintStream out, int length)
- {
- for (int i = 0; i < length; i++)
- {
- out.print('-');
- }
- out.println("");
- }
-
-
- protected Region getRegion(RegionDigraph regionDigraph, String region) throws BundleException {
- Region r = regionDigraph.getRegion(region);
- if (r == null) {
- System.out.println("No region: " + region + ", creating it");
- r = regionDigraph.createRegion(region);
- }
- return r;
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java b/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
deleted file mode 100644
index 07c39e9..0000000
--- a/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
+++ /dev/null
@@ -1,177 +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.region.commands.util;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
-public class FileUtil
-{
- public static void downloadSource(
- PrintStream out, PrintStream err,
- URL srcURL, String dirStr, boolean extract)
- {
- // Get the file name from the URL.
- String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
- ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
- : srcURL.getFile();
-
- try
- {
- out.println("Connecting...");
-
- File dir = new File(dirStr);
- if (!dir.exists())
- {
- err.println("Destination directory does not exist.");
- }
- File file = new File(dir, fileName);
-
- OutputStream os = new FileOutputStream(file);
- URLConnection conn = srcURL.openConnection();
- int total = conn.getContentLength();
- InputStream is = conn.getInputStream();
-
- if (total > 0)
- {
- out.println("Downloading " + fileName
- + " ( " + total + " bytes ).");
- }
- else
- {
- out.println("Downloading " + fileName + ".");
- }
- byte[] buffer = new byte[4096];
- int count = 0;
- for (int len = is.read(buffer); len > 0; len = is.read(buffer))
- {
- count += len;
- os.write(buffer, 0, len);
- }
-
- os.close();
- is.close();
-
- if (extract)
- {
- is = new FileInputStream(file);
- JarInputStream jis = new JarInputStream(is);
- out.println("Extracting...");
- unjar(jis, dir);
- jis.close();
- file.delete();
- }
- }
- catch (Exception ex)
- {
- err.println(ex);
- }
- }
-
- public static void unjar(JarInputStream jis, File dir)
- throws IOException
- {
- // Reusable buffer.
- byte[] buffer = new byte[4096];
-
- // Loop through JAR entries.
- for (JarEntry je = jis.getNextJarEntry();
- je != null;
- je = jis.getNextJarEntry())
- {
- if (je.getName().startsWith("/"))
- {
- throw new IOException("JAR resource cannot contain absolute paths.");
- }
-
- File target = new File(dir, je.getName());
-
- // Check to see if the JAR entry is a directory.
- if (je.isDirectory())
- {
- if (!target.exists())
- {
- if (!target.mkdirs())
- {
- throw new IOException("Unable to create target directory: "
- + target);
- }
- }
- // Just continue since directories do not have content to copy.
- continue;
- }
-
- int lastIndex = je.getName().lastIndexOf('/');
- String name = (lastIndex >= 0) ?
- je.getName().substring(lastIndex + 1) : je.getName();
- String destination = (lastIndex >= 0) ?
- je.getName().substring(0, lastIndex) : "";
-
- // JAR files use '/', so convert it to platform separator.
- destination = destination.replace('/', File.separatorChar);
- copy(jis, dir, name, destination, buffer);
- }
- }
-
- public static void copy(
- InputStream is, File dir, String destName, String destDir, byte[] buffer)
- throws IOException
- {
- if (destDir == null)
- {
- destDir = "";
- }
-
- // Make sure the target directory exists and
- // that is actually a directory.
- File targetDir = new File(dir, destDir);
- if (!targetDir.exists())
- {
- if (!targetDir.mkdirs())
- {
- throw new IOException("Unable to create target directory: "
- + targetDir);
- }
- }
- else if (!targetDir.isDirectory())
- {
- throw new IOException("Target is not a directory: "
- + targetDir);
- }
-
- BufferedOutputStream bos = new BufferedOutputStream(
- new FileOutputStream(new File(targetDir, destName)));
- int count = 0;
- while ((count = is.read(buffer)) > 0)
- {
- bos.write(buffer, 0, count);
- }
- bos.close();
- }
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java b/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
deleted file mode 100644
index aa7215f..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.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.region.persist.internal;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.util.tracker.SingleServiceTracker;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Activator implements BundleActivator {
-
- private static final Logger log = LoggerFactory.getLogger(Activator.class);
-
- private SingleServiceTracker<RegionDigraph> tracker;
- private final AtomicReference<RegionsPersistenceImpl> persistence = new AtomicReference<RegionsPersistenceImpl>();
- private final AtomicReference<RegionsBundleTracker> bundleTracker = new AtomicReference<RegionsBundleTracker>();
- private ServiceRegistration<RegionsPersistence> reg;
-
- @Override
- public void start(final BundleContext bundleContext) throws Exception {
- tracker = new SingleServiceTracker<RegionDigraph>(bundleContext, RegionDigraph.class, new SingleServiceTracker.SingleServiceListener() {
- public void serviceFound() {
- log.debug("Found RegionDigraph service, initializing");
- RegionDigraph regionDigraph = tracker.getService();
- Bundle framework = bundleContext.getBundle(0);
- RegionsPersistenceImpl persistence = null;
- try {
- persistence = new RegionsPersistenceImpl(regionDigraph, framework);
- reg = bundleContext.registerService(RegionsPersistence.class, persistence, null);
-
- RegionsBundleTracker bundleTracker = new RegionsBundleTracker();
- bundleTracker.start(bundleContext, persistence);
- Activator.this.bundleTracker.set(bundleTracker);
- } catch (Exception e) {
- log.info("Could not create RegionsPersistenceImpl", e);
- }
- Activator.this.persistence.set(persistence);
- }
-
- public void serviceLost() {
- if (reg != null) {
- reg.unregister();
- reg = null;
- }
- Activator.this.persistence.set(null);
- Activator.this.bundleTracker.set(null);
- }
-
- public void serviceReplaced() {
- //??
- }
- });
- tracker.open();
- }
-
- @Override
- public void stop(BundleContext bundleContext) throws Exception {
- tracker.close();
- persistence.set(null);
- RegionsBundleTracker tracker = bundleTracker.getAndSet(null);
- if (tracker != null) {
- tracker.stop();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
deleted file mode 100644
index 7035303..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.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.region.persist.internal;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleException;
-import org.osgi.util.tracker.BundleTracker;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RegionsBundleTracker {
- private static final Logger log = LoggerFactory.getLogger(RegionsBundleTracker.class);
-
- private BundleTracker bundleTracker;
- private RegionsPersistence regionsPersistence;
-
- void start(BundleContext bundleContext, RegionsPersistence regionsPersistence) {
- this.regionsPersistence = regionsPersistence;
- int stateMask = Bundle.INSTALLED;
- bundleTracker = new BundleTracker<Bundle>(bundleContext, stateMask, new BundleTrackerCustomizer<Bundle>() {
- @Override
- public Bundle addingBundle(Bundle bundle, BundleEvent bundleEvent) {
- return RegionsBundleTracker.this.addingBundle(bundle);
- }
-
- @Override
- public void modifiedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
- }
-
- @Override
- public void removedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
- }
- });
- bundleTracker.open();
- }
-
- private Bundle addingBundle(Bundle bundle) {
- String region = bundle.getHeaders().get("Region");
- if (region != null) {
- try {
- regionsPersistence.install(bundle, region);
- log.debug("Installed bundle " + bundle + " in region " + region);
- return bundle;
- } catch (BundleException e) {
- log.info("Could not install bundle " + bundle + " in region " + region, e);
- }
- }
- return null;
- }
-
- void stop() {
- bundleTracker.close();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
deleted file mode 100644
index dcf5d26..0000000
--- a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
+++ /dev/null
@@ -1,203 +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.region.persist.internal;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.region.persist.internal.model.FilterAttributeType;
-import org.apache.karaf.region.persist.internal.model.FilterBundleType;
-import org.apache.karaf.region.persist.internal.model.FilterNamespaceType;
-import org.apache.karaf.region.persist.internal.model.FilterPackageType;
-import org.apache.karaf.region.persist.internal.model.FilterType;
-import org.apache.karaf.region.persist.internal.model.RegionBundleType;
-import org.apache.karaf.region.persist.internal.model.RegionType;
-import org.apache.karaf.region.persist.internal.model.RegionsType;
-import org.apache.karaf.region.persist.internal.util.ManifestHeaderProcessor;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilterBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RegionsPersistenceImpl implements RegionsPersistence {
-
- private static final Logger log = LoggerFactory.getLogger(RegionsPersistenceImpl.class);
-
- private JAXBContext jaxbContext;
- private RegionDigraph regionDigraph;
- private Region kernel;
- private Bundle framework;
-
- public RegionsPersistenceImpl(RegionDigraph regionDigraph, Bundle framework) throws JAXBException, BundleException, IOException, InvalidSyntaxException {
- log.info("Loading region digraph persistence");
- this.framework = framework;
- this.regionDigraph = regionDigraph;
- kernel = regionDigraph.getRegion(0);
- jaxbContext = JAXBContext.newInstance(RegionsType.class);
- load();
- }
-
- @Override
- public void install(Bundle b, String regionName) throws BundleException {
- Region region = regionDigraph.getRegion(regionName);
- if (region == null) {
- region = regionDigraph.createRegion(regionName);
- }
- kernel.removeBundle(b);
- region.addBundle(b);
- }
-
- void save(RegionsType regionsType, Writer out) throws JAXBException {
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.marshal(regionsType, out);
- }
-
- void load() throws IOException, BundleException, JAXBException, InvalidSyntaxException {
- if (this.regionDigraph.getRegions().size() <= 1) {
- File etc = new File(System.getProperty("karaf.etc"));
- File regionsConfig = new File(etc, "regions-config.xml");
- if (regionsConfig.exists()) {
- log.info("initializing region digraph from etc/regions-config.xml");
- Reader in = new FileReader(regionsConfig);
- try {
- load(this.regionDigraph, in);
- } finally {
- in.close();
- }
- } else {
- log.info("no regions config file");
- }
- }
-
- }
-
- void load(RegionDigraph regionDigraph, Reader in) throws JAXBException, BundleException, InvalidSyntaxException {
- RegionsType regionsType = load(in);
- load(regionsType, regionDigraph);
- }
-
- RegionsType load(Reader in) throws JAXBException {
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- return (RegionsType) unmarshaller.unmarshal(in);
- }
-
- void load(RegionsType regionsType, RegionDigraph regionDigraph) throws BundleException, InvalidSyntaxException {
- BundleContext frameworkContext = framework.getBundleContext();
- for (RegionType regionType: regionsType.getRegion()) {
- String name = regionType.getName();
- log.debug("Creating region: " + name);
- Region region = regionDigraph.createRegion(name);
- for (RegionBundleType bundleType: regionType.getBundle()) {
- if (bundleType.getId() != null) {
- region.addBundle(bundleType.getId());
- } else {
- Bundle b = frameworkContext.getBundle(bundleType.getLocation());
- region.addBundle(b);
- }
- }
- }
- for (FilterType filterType: regionsType.getFilter()) {
- Region from = regionDigraph.getRegion(filterType.getFrom());
- Region to = regionDigraph.getRegion(filterType.getTo());
- log.debug("Creating filter between " + from.getName() + " to " + to.getName());
- RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
- for (FilterBundleType bundleType: filterType.getBundle()) {
- String symbolicName = bundleType.getSymbolicName();
- String version = bundleType.getVersion();
- if (bundleType.getId() != null) {
- Bundle b = frameworkContext.getBundle(bundleType.getId());
- symbolicName = b.getSymbolicName();
- version = b.getVersion().toString();
- }
- String namespace = BundleRevision.BUNDLE_NAMESPACE;
- List<FilterAttributeType> attributeTypes = bundleType.getAttribute();
- buildFilter(symbolicName, version, namespace, attributeTypes, builder);
- }
- for (FilterPackageType packageType: filterType.getPackage()) {
- String packageName = packageType.getName();
- String version = packageType.getVersion();
- String namespace = BundleRevision.PACKAGE_NAMESPACE;
- List<FilterAttributeType> attributeTypes = packageType.getAttribute();
- buildFilter(packageName, version, namespace, attributeTypes, builder);
- }
- if (to == kernel) {
- //add framework exports
- BundleRevision rev = framework.adapt(BundleRevision.class);
- List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
- for (BundleCapability cap : caps) {
- String filter = ManifestHeaderProcessor.generateFilter(filter(cap.getAttributes()));
- builder.allow(BundleRevision.PACKAGE_NAMESPACE, filter);
- }
- }
- //TODO explicit services?
- for (FilterNamespaceType namespaceType: filterType.getNamespace()) {
- String namespace = namespaceType.getName();
- HashMap<String, Object> attributes = new HashMap<String, Object>();
- for (FilterAttributeType attributeType: namespaceType.getAttribute()) {
- attributes.put(attributeType.getName(), attributeType.getValue());
- }
- String filter = ManifestHeaderProcessor.generateFilter(attributes);
- builder.allow(namespace, filter);
- }
- regionDigraph.connect(from, builder.build(), to);
- }
- }
-
- private Map<String, Object> filter(Map<String, Object> attributes) {
- Map<String, Object> result = new HashMap<String, Object>(attributes);
- result.remove("bundle-version");
- result.remove("bundle-symbolic-name");
- return result;
- }
-
- private void buildFilter(String packageName, String version, String namespace, List<FilterAttributeType> attributeTypes, RegionFilterBuilder builder) throws InvalidSyntaxException {
- HashMap<String, Object> attributes = new HashMap<String, Object>();
- if (namespace != null) {
- attributes.put(namespace, packageName);
- }
- if (version != null) {
- attributes.put("version", version);
- }
- for (FilterAttributeType attributeType: attributeTypes) {
- attributes.put(attributeType.getName(), attributeType.getValue());
- }
- String filter = ManifestHeaderProcessor.generateFilter(attributes);
- builder.allow(namespace, filter);
- }
-
-}
[5/6] git commit: [KARAF-2923] Region support in features service
Posted by gn...@apache.org.
[KARAF-2923] Region support in features service
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/2705ad88
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/2705ad88
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/2705ad88
Branch: refs/heads/master
Commit: 2705ad8894a2af462487774c705066ef7de13f25
Parents: 486ad3a
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 18 21:16:02 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 18 23:33:51 2014 +0200
----------------------------------------------------------------------
assemblies/features/standard/pom.xml | 17 -
.../standard/src/main/feature/feature.xml | 6 -
features/command/pom.xml | 5 +
.../features/command/InstallFeatureCommand.java | 5 +-
.../features/command/RegionInfoCommand.java | 129 ++++
.../command/UninstallFeatureCommand.java | 5 +-
features/core/pom.xml | 18 +-
.../java/org/apache/karaf/features/Feature.java | 4 +-
.../apache/karaf/features/FeaturesService.java | 4 +
.../karaf/features/RegionsPersistence.java | 26 -
.../org/apache/karaf/features/Repository.java | 2 -
.../org/apache/karaf/features/Resolver.java | 25 -
.../org/apache/karaf/features/ScopeFilter.java | 25 +
.../java/org/apache/karaf/features/Scoping.java | 29 +
.../internal/deployment/DeploymentBuilder.java | 354 ----------
.../internal/deployment/Downloader.java | 35 -
.../internal/deployment/StreamProvider.java | 26 -
.../internal/download/DownloadCallback.java | 23 +
.../internal/download/DownloadManager.java | 27 +
.../features/internal/download/Downloader.java | 29 +
.../internal/download/StreamProvider.java | 29 +
.../download/simple/SimpleDownloader.java | 120 ++++
.../karaf/features/internal/model/Feature.java | 23 +-
.../karaf/features/internal/model/JaxbUtil.java | 33 +-
.../features/internal/model/ScopeFilter.java | 56 ++
.../karaf/features/internal/model/Scoping.java | 70 ++
.../karaf/features/internal/osgi/Activator.java | 73 +-
.../region/AbstractRegionDigraphVisitor.java | 121 ++++
.../internal/region/CandidateComparator.java | 125 ++++
.../internal/region/ResourceComparator.java | 43 ++
.../features/internal/region/Subsystem.java | 341 ++++++++++
.../region/SubsystemResolveContext.java | 188 ++++++
.../internal/region/SubsystemResolver.java | 317 +++++++++
.../internal/resolver/CandidateComparator.java | 129 ----
.../internal/resolver/FeatureNamespace.java | 72 --
.../internal/resolver/FeatureResource.java | 43 +-
.../internal/resolver/IdentityCapability.java | 2 +-
.../internal/resolver/ResolveContextImpl.java | 102 ---
.../internal/resolver/ResourceBuilder.java | 7 +-
.../internal/resolver/ResourceUtils.java | 103 +++
.../internal/resolver/UriNamespace.java | 47 --
.../service/FeatureConfigInstaller.java | 40 +-
.../internal/service/FeaturesServiceImpl.java | 667 ++++++++++++-------
.../internal/service/RepositoryImpl.java | 8 +-
.../internal/service/SimpleDownloader.java | 51 --
.../karaf/features/internal/service/State.java | 29 +-
.../features/internal/service/StateStorage.java | 131 ++--
.../features/internal/util/JsonWriter.java | 8 +
.../karaf/features/internal/util/MapUtils.java | 65 ++
.../equinox/internal/region/DigraphHelper.java | 149 +++++
.../karaf/features/karaf-features-1.3.0.xsd | 58 +-
.../karaf/features/FeaturesServiceTest.java | 11 +-
.../features/internal/region/SubsystemTest.java | 213 ++++++
.../service/FeaturesServiceImplTest.java | 8 +-
.../internal/service/OverridesTest.java | 13 +-
.../internal/service/StateStorageTest.java | 80 +++
.../karaf/features/internal/region/data1/a.mf | 6 +
.../karaf/features/internal/region/data1/b.mf | 6 +
.../karaf/features/internal/region/data1/c.mf | 6 +
.../features/internal/region/data1/features.xml | 31 +
.../karaf/features/internal/region/data2/a.mf | 7 +
.../karaf/features/internal/region/data2/b.mf | 7 +
.../karaf/features/internal/region/data2/c.mf | 6 +
.../karaf/features/internal/region/data2/d.mf | 6 +
.../karaf/features/internal/region/data2/e.mf | 6 +
.../features/internal/region/data2/features.xml | 42 ++
.../karaf/features/internal/service/f07.xml | 11 +
.../org/apache/karaf/itests/RegionTest.java | 48 --
.../itests/features/StandardFeaturesTest.java | 5 -
pom.xml | 14 +-
region/NOTICE | 71 --
region/pom.xml | 136 ----
.../karaf/region/commands/AddBundleCommand.java | 52 --
.../karaf/region/commands/AddFilterCommand.java | 169 -----
.../karaf/region/commands/AddRegionCommand.java | 38 --
.../karaf/region/commands/InfoCommand.java | 117 ----
.../region/commands/RegionCommandSupport.java | 79 ---
.../karaf/region/commands/util/FileUtil.java | 177 -----
.../region/persist/internal/Activator.java | 91 ---
.../persist/internal/RegionsBundleTracker.java | 77 ---
.../internal/RegionsPersistenceImpl.java | 203 ------
.../internal/model/FilterAttributeType.java | 94 ---
.../internal/model/FilterBundleType.java | 156 -----
.../internal/model/FilterNamespaceType.java | 102 ---
.../internal/model/FilterPackageType.java | 129 ----
.../persist/internal/model/FilterType.java | 195 ------
.../persist/internal/model/ObjectFactory.java | 116 ----
.../internal/model/RegionBundleType.java | 94 ---
.../persist/internal/model/RegionType.java | 106 ---
.../persist/internal/model/RegionsType.java | 112 ----
.../persist/internal/model/package-info.java | 9 -
.../internal/util/ManifestHeaderProcessor.java | 661 ------------------
.../internal/util/ManifestHeaderUtils.java | 85 ---
.../persist/internal/util/VersionRange.java | 456 -------------
.../org/apache/karaf/region/persist/region.xsd | 109 ---
.../webconsole/features/ExtendedFeature.java | 6 +-
96 files changed, 3127 insertions(+), 5083 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/assemblies/features/standard/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/pom.xml b/assemblies/features/standard/pom.xml
index f050441..bad1015 100644
--- a/assemblies/features/standard/pom.xml
+++ b/assemblies/features/standard/pom.xml
@@ -162,11 +162,6 @@
<classifier>uber</classifier>
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.apache.karaf.features</groupId>
- <artifactId>org.apache.karaf.features.obr</artifactId>
- <scope>provided</scope>
- </dependency>
<!-- config deps -->
<dependency>
@@ -175,18 +170,6 @@
<scope>provided</scope>
</dependency>
- <!-- region deps -->
- <dependency>
- <groupId>org.eclipse.equinox</groupId>
- <artifactId>org.eclipse.equinox.region</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.karaf.region</groupId>
- <artifactId>org.apache.karaf.region.core</artifactId>
- <scope>provided</scope>
- </dependency>
-
<!-- jetty deps -->
<dependency>
<groupId>org.apache.servicemix.specs</groupId>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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 f50cd65..e7d77c5 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -147,12 +147,6 @@
<bundle start-level="30" start="true">mvn:org.apache.karaf.log/org.apache.karaf.log.core/${project.version}</bundle>
</feature>
- <feature name="region" description="Provide Region Support" version="${project.version}">
- <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
- <bundle start-level="30">mvn:org.eclipse.equinox/org.eclipse.equinox.region/${equinox.region.version}</bundle>
- <bundle start-level="30">mvn:org.apache.karaf.region/org.apache.karaf.region.core/${project.version}</bundle>
- </feature>
-
<feature name="package" version="${project.version}" description="Package commands and mbeans">
<bundle start-level="30">mvn:org.apache.karaf.package/org.apache.karaf.package.core/${project.version}</bundle>
</feature>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/command/pom.xml
----------------------------------------------------------------------
diff --git a/features/command/pom.xml b/features/command/pom.xml
index 4f49bb1..5978b38 100644
--- a/features/command/pom.xml
+++ b/features/command/pom.xml
@@ -56,6 +56,11 @@
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.core</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.equinox</groupId>
+ <artifactId>org.eclipse.equinox.region</artifactId>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index b7f8184..ccd869a 100644
--- 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
@@ -50,6 +50,9 @@ public class InstallFeatureCommand extends FeaturesCommandSupport {
@Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
boolean simulate;
+ @Option(name = "-g", aliases = "--region", description = "Region to install to")
+ String region;
+
protected void doExecute(FeaturesService admin) throws Exception {
EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
if (simulate) {
@@ -64,6 +67,6 @@ public class InstallFeatureCommand extends FeaturesCommandSupport {
if (verbose) {
options.add(FeaturesService.Option.Verbose);
}
- admin.installFeatures(new HashSet<String>(features), options);
+ admin.installFeatures(new HashSet<String>(features), region, options);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/command/src/main/java/org/apache/karaf/features/command/RegionInfoCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RegionInfoCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RegionInfoCommand.java
new file mode 100644
index 0000000..8a3e73e
--- /dev/null
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RegionInfoCommand.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.command;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.karaf.shell.api.action.Action;
+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.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+@Command(scope = "feature", name = "regions", description = "Prints information about region digraph.")
+@Service
+public class RegionInfoCommand implements Action {
+
+ @Option(name = "-v", aliases = "--verbose", required = false, description = "Show all info.")
+ boolean verbose;
+
+ @Option(name = "-b", aliases = "--bundles", required = false, description = "Show bundles in each region.")
+ boolean bundles;
+
+ @Option(name = "-f", aliases = "--filters", required = false, description = "Show filters.")
+ boolean filters;
+
+ @Option(name = "-n", aliases = "--namespaces", required = false, description = "Show namespaces in each filter.")
+ boolean namespaces;
+
+ @Argument(index = 0, name = "regions", description = "Regions to provide detailed info for.", required = false, multiValued = true)
+ List<String> regions;
+
+ @Reference
+ RegionDigraph regionDigraph;
+
+ @Reference
+ BundleContext bundleContext;
+
+ public Object execute() throws Exception {
+ System.out.println("Regions");
+ if (regions == null) {
+ for (Region region : regionDigraph.getRegions()) {
+ showRegion(region);
+ }
+ } else {
+ bundles = true;
+ filters = true;
+ namespaces = true;
+ for (String regionName : regions) {
+ Region region = regionDigraph.getRegion(regionName);
+ if (region == null) {
+ System.out.println("No region " + regionName);
+ } else {
+ showRegion(region);
+ }
+ }
+ }
+ return null;
+ }
+
+ private void showRegion(Region region) {
+ BundleContext bundleContext = this.bundleContext.getBundle(0).getBundleContext();
+ System.out.println(region.getName());
+ if (verbose || bundles) {
+ for (Long id : new TreeSet<Long>(region.getBundleIds())) {
+ Bundle b = bundleContext.getBundle(id);
+ System.out.println(String.format(" %3d %s%s", id, getStateString(b), b));
+ }
+ }
+ if (verbose || filters || namespaces) {
+ for (RegionDigraph.FilteredRegion f : region.getEdges()) {
+ System.out.println(" filter to " + f.getRegion().getName());
+ if (verbose || namespaces) {
+ RegionFilter rf = f.getFilter();
+ for (Map.Entry<String, Collection<String>> policy : rf.getSharingPolicy().entrySet()) {
+ String namespace = policy.getKey();
+ System.out.println(" namespace: " + namespace);
+ for (String e : policy.getValue()) {
+ System.out.println(" " + e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public String getStateString(Bundle bundle) {
+ if (bundle == null) {
+ return "Bundle null ";
+ }
+ int state = bundle.getState();
+ if (state == Bundle.ACTIVE) {
+ return "Active ";
+ } else if (state == Bundle.INSTALLED) {
+ return "Installed ";
+ } else if (state == Bundle.RESOLVED) {
+ return "Resolved ";
+ } else if (state == Bundle.STARTING) {
+ return "Starting ";
+ } else if (state == Bundle.STOPPING) {
+ return "Stopping ";
+ } else {
+ return "Unknown ";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index e62f697..0fb7d14 100644
--- 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
@@ -45,6 +45,9 @@ public class UninstallFeatureCommand extends FeaturesCommandSupport {
@Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
boolean simulate;
+ @Option(name = "-g", aliases = "--region", description = "Region to install to")
+ String region;
+
protected void doExecute(FeaturesService admin) throws Exception {
// iterate in the provided feature
EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
@@ -57,6 +60,6 @@ public class UninstallFeatureCommand extends FeaturesCommandSupport {
if (verbose) {
options.add(FeaturesService.Option.Verbose);
}
- admin.uninstallFeatures(new HashSet<String>(features), options);
+ admin.uninstallFeatures(new HashSet<String>(features), region, options);
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/pom.xml
----------------------------------------------------------------------
diff --git a/features/core/pom.xml b/features/core/pom.xml
index d8a2620..8998ba9 100644
--- a/features/core/pom.xml
+++ b/features/core/pom.xml
@@ -72,6 +72,12 @@
</dependency>
<dependency>
+ <groupId>org.eclipse.equinox</groupId>
+ <artifactId>org.eclipse.equinox.region</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<scope>test</scope>
@@ -110,8 +116,15 @@
org.apache.karaf.features;
org.apache.karaf.features.management;
org.apache.karaf.features.management.codec;
- -noimport:=true
+ -noimport:=true,
+ org.osgi.service.resolver;-split-package:=merge-first,
+ org.osgi.service.repository,
+ org.eclipse.equinox.region.*
</Export-Package>
+ <Import-Package>
+ !org.eclipse.osgi.service.resolver,
+ *
+ </Import-Package>
<Provide-Capability>
service-reference;effective:=active;objectClass=org.apache.karaf.features.FeaturesService
</Provide-Capability>
@@ -123,8 +136,7 @@
org.apache.karaf.util.collections,
org.apache.karaf.util.json,
org.apache.karaf.util.tracker,
- org.osgi.service.resolver,
- org.osgi.service.repository
+ org.eclipse.equinox.internal.region.*;-split-package:=merge-first,
</Private-Package>
<Embed-Dependency>
org.apache.karaf.util;inline="org/apache/karaf/util/XmlUtils*.class"
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 2f9f001..06235e2 100644
--- a/features/core/src/main/java/org/apache/karaf/features/Feature.java
+++ b/features/core/src/main/java/org/apache/karaf/features/Feature.java
@@ -54,10 +54,10 @@ public interface Feature {
int getStartLevel();
- String getRegion();
-
List<? extends Capability> getCapabilities();
List<? extends Requirement> getRequirements();
+ Scoping getScoping();
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index ef3dbcf..7bb3cf8 100644
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -71,6 +71,8 @@ public interface FeaturesService {
void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+ void installFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception;
+
void uninstallFeature(String name, EnumSet<Option> options) throws Exception;
void uninstallFeature(String name) throws Exception;
@@ -81,6 +83,8 @@ public interface FeaturesService {
void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+ void uninstallFeatures(Set<String> features, String region, EnumSet<Option> options) throws Exception;
+
Feature[] listFeatures() throws Exception;
Feature[] listRequiredFeatures() throws Exception;
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index 96ca7da..0000000
--- a/features/core/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/2705ad88/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
index 3ea12ec..84d4a50 100644
--- a/features/core/src/main/java/org/apache/karaf/features/Repository.java
+++ b/features/core/src/main/java/org/apache/karaf/features/Repository.java
@@ -32,6 +32,4 @@ public interface Repository {
Feature[] getFeatures() throws Exception;
- boolean isValid();
-
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index d2fa941..0000000
--- a/features/core/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/2705ad88/features/core/src/main/java/org/apache/karaf/features/ScopeFilter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/ScopeFilter.java b/features/core/src/main/java/org/apache/karaf/features/ScopeFilter.java
new file mode 100644
index 0000000..c4ddbfe
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/ScopeFilter.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 ScopeFilter {
+
+ String getNamespace();
+
+ String getFilter();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/Scoping.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Scoping.java b/features/core/src/main/java/org/apache/karaf/features/Scoping.java
new file mode 100644
index 0000000..b97e6f2
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/Scoping.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;
+
+import java.util.List;
+
+public interface Scoping {
+
+ boolean acceptDependencies();
+
+ List<? extends ScopeFilter> getImports();
+
+ List<? extends ScopeFilter> getExports();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index c3ac2b7..0000000
--- a/features/core/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");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
deleted file mode 100644
index 2d5dd98..0000000
--- a/features/core/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/2705ad88/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
deleted file mode 100644
index 60a3dfc..0000000
--- a/features/core/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/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadCallback.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadCallback.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadCallback.java
new file mode 100644
index 0000000..b8fda6a
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadCallback.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.internal.download;
+
+public interface DownloadCallback {
+
+ void downloaded(StreamProvider provider) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadManager.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadManager.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadManager.java
new file mode 100644
index 0000000..0bac194
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/DownloadManager.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.internal.download;
+
+import java.util.Map;
+
+public interface DownloadManager {
+
+ Downloader createDownloader();
+
+ Map<String,StreamProvider> getProviders();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/download/Downloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/Downloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/Downloader.java
new file mode 100644
index 0000000..baf71a0
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/Downloader.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.download;
+
+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;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/download/StreamProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/StreamProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/StreamProvider.java
new file mode 100644
index 0000000..c25fa43
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/StreamProvider.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.download;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+public interface StreamProvider {
+
+ InputStream open() throws IOException;
+
+ Map<String, String> getMetadata() throws IOException;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/download/simple/SimpleDownloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/download/simple/SimpleDownloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/download/simple/SimpleDownloader.java
new file mode 100644
index 0000000..4569fe2
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/download/simple/SimpleDownloader.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.download.simple;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.karaf.features.internal.download.DownloadCallback;
+import org.apache.karaf.features.internal.download.DownloadManager;
+import org.apache.karaf.features.internal.download.Downloader;
+import org.apache.karaf.features.internal.download.StreamProvider;
+import org.apache.karaf.features.internal.util.MultiException;
+
+public class SimpleDownloader implements DownloadManager, Downloader {
+
+ protected final MultiException exception = new MultiException("Error");
+
+ protected final ConcurrentMap<String, StreamProvider> providers = new ConcurrentHashMap<String, StreamProvider>();
+
+ @Override
+ public Downloader createDownloader() {
+ return this;
+ }
+
+ @Override
+ public void await() throws InterruptedException, MultiException {
+ exception.throwIfExceptions();
+ }
+
+ @Override
+ public void download(final String location, final DownloadCallback downloadCallback) throws MalformedURLException {
+ if (!providers.containsKey(location)) {
+ providers.putIfAbsent(location, createProvider(location));
+ }
+ try {
+ downloadCallback.downloaded(providers.get(location));
+ } catch (Exception e) {
+ exception.addException(e);
+ }
+ }
+
+ protected StreamProvider createProvider(String location) throws MalformedURLException {
+ return new UrlProvider(new URL(location));
+ }
+
+ public Map<String, StreamProvider> getProviders() {
+ return providers;
+ }
+
+ static class UrlProvider implements StreamProvider {
+ private final URL url;
+ private volatile Map<String, String> metadata;
+
+ UrlProvider(URL url) {
+ this.url = url;
+ }
+
+ @Override
+ public InputStream open() throws IOException {
+ return url.openStream();
+ }
+
+ @Override
+ public Map<String, String> getMetadata() throws IOException {
+ if (metadata == null) {
+ synchronized (this) {
+ if (metadata == null) {
+ metadata = doGetMetadata();
+ }
+ }
+ }
+ return metadata;
+ }
+
+ protected Map<String, String> doGetMetadata() throws IOException {
+ InputStream is = open();
+ try {
+ ZipInputStream zis = new ZipInputStream(is);
+ ZipEntry entry;
+ while ((entry = zis.getNextEntry()) != null) {
+ if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
+ Attributes attributes = new Manifest(zis).getMainAttributes();
+ Map<String, String> headers = new HashMap<String, String>();
+ for (Map.Entry attr : attributes.entrySet()) {
+ headers.put(attr.getKey().toString(), attr.getValue().toString());
+ }
+ return headers;
+ }
+ }
+ } finally {
+ is.close();
+ }
+ throw new IllegalArgumentException("Resource " + url + " does not contain a manifest");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 46580da..0aa5eb5 100644
--- 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
@@ -75,7 +75,8 @@ import javax.xml.bind.annotation.XmlType;
"bundle",
"conditional",
"capability",
- "requirement"
+ "requirement",
+ "scoping"
})
public class Feature extends Content implements org.apache.karaf.features.Feature {
public static String SPLIT_FOR_NAME_AND_VERSION = "/";
@@ -95,11 +96,10 @@ public class Feature extends Content implements org.apache.karaf.features.Featur
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;
+ protected Scoping scoping;
public Feature() {
}
@@ -280,15 +280,6 @@ public class Feature extends Content implements org.apache.karaf.features.Featur
this.startLevel = value;
}
-
- public String getRegion() {
- return region;
- }
-
- public void setRegion(String region) {
- this.region = region;
- }
-
/**
* Gets the value of the conditional property.
* <p/>
@@ -330,6 +321,14 @@ public class Feature extends Content implements org.apache.karaf.features.Featur
return this.requirement;
}
+ public Scoping getScoping() {
+ return scoping;
+ }
+
+ public void setScoping(Scoping scoping) {
+ this.scoping = scoping;
+ }
+
public String toString() {
return getId();
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index 2036452..9b5d7b6 100644
--- 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
@@ -41,6 +41,8 @@ import javax.xml.validation.SchemaFactory;
import org.apache.karaf.features.FeaturesNamespaces;
import org.apache.karaf.util.XmlUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -53,6 +55,7 @@ import org.xml.sax.helpers.XMLFilterImpl;
public class JaxbUtil {
+ private static final Logger LOGGER = LoggerFactory.getLogger(JaxbUtil.class);
private static final JAXBContext FEATURES_CONTEXT;
static {
try {
@@ -112,11 +115,16 @@ public class JaxbUtil {
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);
+ String nsuri = doc.getDocumentElement().getNamespaceURI();
+ if (nsuri == null) {
+ LOGGER.warn("Old style feature file without namespace found (URI: {}). This format is deprecated and support for it will soon be removed", uri);
+ } else {
+ Schema schema = getSchema(nsuri);
+ try {
+ schema.newValidator().validate(new DOMSource(doc));
+ } catch (SAXException e) {
+ throw new IllegalArgumentException("Unable to validate " + uri, e);
+ }
}
fixDom(doc, doc.getDocumentElement());
@@ -162,12 +170,14 @@ public class JaxbUtil {
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));
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ if (!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));
+ }
}
}
@@ -177,7 +187,6 @@ public class JaxbUtil {
XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(XmlUtils.xmlReader());
xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
-
InputSource is = new InputSource(uri);
if (stream != null) {
is.setByteStream(stream);
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/model/ScopeFilter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/ScopeFilter.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/ScopeFilter.java
new file mode 100644
index 0000000..4b81fed
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/ScopeFilter.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.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;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "scopeFilter", propOrder = {
+ "value"
+})
+public class ScopeFilter implements org.apache.karaf.features.ScopeFilter {
+
+ @XmlAttribute(required = true)
+ protected String namespace;
+ @XmlValue
+ protected String value;
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String getFilter() {
+ return getValue();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/model/Scoping.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Scoping.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Scoping.java
new file mode 100644
index 0000000..6773995
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Scoping.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "scoping", propOrder = {
+ "imports",
+ "exports"
+})
+public class Scoping implements org.apache.karaf.features.Scoping {
+
+ @XmlAttribute
+ boolean acceptDependencies;
+ @XmlElement(name = "import")
+ List<ScopeFilter> imports;
+ @XmlElement(name = "export")
+ List<ScopeFilter> exports;
+
+ public List<ScopeFilter> getImport() {
+ if (imports == null) {
+ imports = new ArrayList<ScopeFilter>();
+ }
+ return imports;
+ }
+
+ public List<ScopeFilter> getExport() {
+ if (exports == null) {
+ exports = new ArrayList<ScopeFilter>();
+ }
+ return exports;
+ }
+
+ @Override
+ public boolean acceptDependencies() {
+ return acceptDependencies;
+ }
+
+ @Override
+ public List<? extends org.apache.karaf.features.ScopeFilter> getImports() {
+ return getImport();
+ }
+
+ @Override
+ public List<? extends org.apache.karaf.features.ScopeFilter> getExports() {
+ return getExport();
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/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
index be0da05..0551d21 100644
--- 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
@@ -27,8 +27,10 @@ import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Properties;
+import org.apache.felix.resolver.ResolverImpl;
import org.apache.karaf.features.FeaturesListener;
import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
import org.apache.karaf.features.internal.service.EventAdminListener;
import org.apache.karaf.features.internal.service.FeatureConfigInstaller;
import org.apache.karaf.features.internal.service.FeatureFinder;
@@ -36,25 +38,35 @@ 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.eclipse.equinox.internal.region.DigraphHelper;
+import org.eclipse.equinox.internal.region.StandardRegionDigraph;
+import org.eclipse.equinox.internal.region.management.StandardManageableRegionDigraph;
+import org.eclipse.equinox.region.RegionDigraph;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.bundle.CollisionHook;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ManagedService;
+import org.osgi.service.resolver.Resolver;
import org.osgi.service.url.URLStreamHandlerService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.LoggerFactory;
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 static final String STATE_FILE = "state.json";
+
private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
private FeaturesServiceImpl featuresService;
- private SingleServiceTracker<RegionsPersistence> regionsTracker;
+ private StandardRegionDigraph digraph;
+ private StandardManageableRegionDigraph digraphMBean;
public Activator() {
// Special case here, as we don't want the activator to wait for current job to finish,
@@ -87,32 +99,28 @@ public class Activator extends BaseActivator {
return;
}
+ // Resolver
+ register(Resolver.class, new ResolverImpl(new Slf4jResolverLog(LoggerFactory.getLogger(ResolverImpl.class))));
+
+ // RegionDigraph
+ digraph = DigraphHelper.loadDigraph(bundleContext);
+ register(ResolverHookFactory.class, digraph.getResolverHookFactory());
+ register(CollisionHook.class, DigraphHelper.getCollisionHook(digraph));
+ register(org.osgi.framework.hooks.bundle.FindHook.class, digraph.getBundleFindHook());
+ register(org.osgi.framework.hooks.bundle.EventHook.class, digraph.getBundleEventHook());
+ register(org.osgi.framework.hooks.service.FindHook.class, digraph.getServiceFindHook());
+ register(org.osgi.framework.hooks.service.EventHook.class, digraph.getServiceEventHook());
+ register(RegionDigraph.class, digraph);
+ digraphMBean = new StandardManageableRegionDigraph(digraph, "org.apache.karaf", bundleContext);
+ digraphMBean.registerMBean();
+
+
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);
+ FeatureConfigInstaller configInstaller = new FeatureConfigInstaller(configurationAdmin);
// TODO: honor respectStartLvlDuringFeatureStartup and respectStartLvlDuringFeatureUninstall
// boolean respectStartLvlDuringFeatureStartup = getBoolean("respectStartLvlDuringFeatureStartup", true);
// boolean respectStartLvlDuringFeatureUninstall = getBoolean("respectStartLvlDuringFeatureUninstall", true);
@@ -123,7 +131,7 @@ public class Activator extends BaseActivator {
StateStorage stateStorage = new StateStorage() {
@Override
protected InputStream getInputStream() throws IOException {
- File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+ File file = bundleContext.getDataFile(STATE_FILE);
if (file.exists()) {
return new FileInputStream(file);
} else {
@@ -133,7 +141,7 @@ public class Activator extends BaseActivator {
@Override
protected OutputStream getOutputStream() throws IOException {
- File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+ File file = bundleContext.getDataFile(STATE_FILE);
return new FileOutputStream(file);
}
};
@@ -150,6 +158,7 @@ public class Activator extends BaseActivator {
featureFinder,
eventAdminListener,
configInstaller,
+ digraph,
overrides,
featureResolutionRange,
bundleUpdateRange,
@@ -191,9 +200,9 @@ public class Activator extends BaseActivator {
}
protected void doStop() {
- if (regionsTracker != null) {
- regionsTracker.close();
- regionsTracker = null;
+ if (digraphMBean != null) {
+ digraphMBean.unregisterMbean();
+ digraphMBean = null;
}
if (featuresListenerTracker != null) {
featuresListenerTracker.close();
@@ -203,6 +212,14 @@ public class Activator extends BaseActivator {
if (featuresService != null) {
featuresService = null;
}
+ if (digraph != null) {
+ try {
+ DigraphHelper.saveDigraph(bundleContext, digraph);
+ } catch (Exception e) {
+ // Ignore
+ }
+ digraph = null;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/2705ad88/features/core/src/main/java/org/apache/karaf/features/internal/region/AbstractRegionDigraphVisitor.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/AbstractRegionDigraphVisitor.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/AbstractRegionDigraphVisitor.java
new file mode 100644
index 0000000..3ad2325
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/AbstractRegionDigraphVisitor.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.region;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraphVisitor;
+import org.eclipse.equinox.region.RegionFilter;
+
+/**
+ * {@link AbstractRegionDigraphVisitor} is an abstract base class for {@link RegionDigraphVisitor} implementations
+ */
+public abstract class AbstractRegionDigraphVisitor<C> implements RegionDigraphVisitor {
+
+ private final Collection<C> allCandidates;
+ private final Deque<Set<C>> allowedDeque = new ArrayDeque<Set<C>>();
+ private final Deque<Collection<C>> filteredDeque = new ArrayDeque<Collection<C>>();
+ private Set<C> allowed = new HashSet<C>();
+
+ public AbstractRegionDigraphVisitor(Collection<C> candidates) {
+ this.allCandidates = candidates;
+ }
+
+ public Collection<C> getAllowed() {
+ return allowed;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean visit(Region region) {
+ Collection<C> candidates = filteredDeque.isEmpty() ? allCandidates : filteredDeque.peek();
+ for (C candidate : candidates) {
+ if (contains(region, candidate)) {
+ allowed.add(candidate);
+ }
+ }
+ // there is no need to traverse edges of this region,
+ // it contains all the remaining filtered candidates
+ return !allowed.containsAll(candidates);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean preEdgeTraverse(RegionFilter regionFilter) {
+ // Find the candidates filtered by the previous edge
+ Collection<C> filtered = filteredDeque.isEmpty() ? allCandidates : filteredDeque.peek();
+ Collection<C> candidates = new ArrayList<C>(filtered);
+ // remove any candidates contained in the current region
+ candidates.removeAll(allowed);
+ // apply the filter across remaining candidates
+ Iterator<C> i = candidates.iterator();
+ while (i.hasNext()) {
+ C candidate = i.next();
+ if (!isAllowed(candidate, regionFilter)) {
+ i.remove();
+ }
+ }
+ if (candidates.isEmpty())
+ return false; // this filter does not apply; avoid traversing this edge
+ // push the filtered candidates for the next region
+ filteredDeque.push(candidates);
+ // push the allowed
+ allowedDeque.push(allowed);
+ allowed = new HashSet<C>();
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void postEdgeTraverse(RegionFilter regionFilter) {
+ filteredDeque.poll();
+ Collection<C> candidates = allowed;
+ allowed = allowedDeque.pop();
+ allowed.addAll(candidates);
+ }
+
+ /**
+ * Determines whether the given region contains the given candidate.
+ *
+ * @param region the {@link Region}
+ * @param candidate the candidate
+ * @return <code>true</code> if and only if the given region contains the given candidate
+ */
+ protected abstract boolean contains(Region region, C candidate);
+
+ /**
+ * Determines whether the given candidate is allowed by the given {@link RegionFilter}.
+ *
+ * @param candidate the candidate
+ * @param filter the filter
+ * @return <code>true</code> if and only if the given candidate is allowed by the given filter
+ */
+ protected abstract boolean isAllowed(C candidate, RegionFilter filter);
+}
\ No newline at end of file