diff --git a/.github/workflows/maven-ci.yml b/.github/workflows/maven-ci.yml index 68e223727d..d569185557 100644 --- a/.github/workflows/maven-ci.yml +++ b/.github/workflows/maven-ci.yml @@ -23,6 +23,7 @@ on: - 'log.extension/**' - 'examples/**' - 'configadmin/**' + - 'dependencymanager/**' pull_request: branches: [ "master", "feature/**", "maintenance/**" ] paths: @@ -45,6 +46,7 @@ on: - 'log.extension/**' - 'examples/**' - 'configadmin/**' + - 'dependencymanager/**' # Cancel superseded runs for the same branch. github.head_ref is only set for # pull_request events, so pushes fall back to github.ref, which groups per branch: @@ -118,6 +120,8 @@ jobs: - 'log.extension/**' examples: - 'examples/**' + dependencymanager: + - 'dependencymanager/**' - name: Felix Configuration JSON if: steps.changes.outputs.cm-json == 'true' || steps.changes.outputs.configurator == 'true' run: mvn -B -V -Dstyle.color=always --file cm.json/pom.xml clean install @@ -133,7 +137,7 @@ jobs: # code being changed rather than the last release. A producer is therefore built and # installed whenever it or one of its consumers changed. See FELIX-6870. - name: Resolve the versions built in this repository - if: steps.changes.outputs.framework == 'true' || steps.changes.outputs.http == 'true' || steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' || steps.changes.outputs.gogo == 'true' || steps.changes.outputs.utils == 'true' || steps.changes.outputs.resolver == 'true' + if: steps.changes.outputs.framework == 'true' || steps.changes.outputs.http == 'true' || steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' || steps.changes.outputs.gogo == 'true' || steps.changes.outputs.utils == 'true' || steps.changes.outputs.resolver == 'true' || steps.changes.outputs.dependencymanager == 'true' run: | record() { echo "$1=$2" >> "$GITHUB_ENV" @@ -147,10 +151,10 @@ jobs: record "GOGO_$(echo "$module" | tr 'a-z' 'A-Z')_VERSION" "$(mvn -B -q --file gogo/pom.xml -pl "$module" help:evaluate -Dexpression=project.version -DforceStdout)" done - name: Felix Framework - if: steps.changes.outputs.framework == 'true' || steps.changes.outputs.http == 'true' || steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' || steps.changes.outputs.gogo == 'true' + if: steps.changes.outputs.framework == 'true' || steps.changes.outputs.http == 'true' || steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' || steps.changes.outputs.gogo == 'true' || steps.changes.outputs.dependencymanager == 'true' run: mvn -B -V -Dstyle.color=always --file framework/pom.xml clean install - name: Felix Config Admin - if: steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' + if: steps.changes.outputs.configadmin == 'true' || steps.changes.outputs.scr == 'true' || steps.changes.outputs.dependencymanager == 'true' run: mvn -B -V -Dstyle.color=always --file configadmin/pom.xml clean install "-Dfelix.framework.version=$FRAMEWORK_VERSION" - name: Felix SCR if: steps.changes.outputs.scr == 'true' @@ -174,8 +178,8 @@ jobs: if: steps.changes.outputs.main == 'true' run: mvn -B -V -Dstyle.color=always --file main/pom.xml clean verify - name: Felix Gogo Shell - if: steps.changes.outputs.gogo == 'true' - run: mvn -B -V -Dstyle.color=always --file gogo/pom.xml clean verify "-Dfelix.gogo.command.version=$GOGO_COMMAND_VERSION" "-Dfelix.gogo.runtime.version=$GOGO_RUNTIME_VERSION" "-Dfelix.gogo.shell.version=$GOGO_SHELL_VERSION" "-Dfelix.gogo.jline.version=$GOGO_JLINE_VERSION" "-Dfelix.framework.version=$FRAMEWORK_VERSION" + if: steps.changes.outputs.gogo == 'true' || steps.changes.outputs.dependencymanager == 'true' + run: mvn -B -V -Dstyle.color=always --file gogo/pom.xml clean install "-Dfelix.gogo.command.version=$GOGO_COMMAND_VERSION" "-Dfelix.gogo.runtime.version=$GOGO_RUNTIME_VERSION" "-Dfelix.gogo.shell.version=$GOGO_SHELL_VERSION" "-Dfelix.gogo.jline.version=$GOGO_JLINE_VERSION" "-Dfelix.framework.version=$FRAMEWORK_VERSION" - name: Felix utils if: steps.changes.outputs.utils == 'true' || steps.changes.outputs.resolver == 'true' run: mvn -B -V -Dstyle.color=always --file utils/pom.xml clean install @@ -194,6 +198,17 @@ jobs: - name: Felix examples if: steps.changes.outputs.examples == 'true' run: mvn -B -V -Dstyle.color=always --file examples/pom.xml clean verify + # The Dependency Manager is built with Gradle and bnd rather than Maven. It runs last, + # on the framework, Gogo and Config Admin snapshots installed into the local Maven + # repository by the steps above. + - name: Felix Dependency Manager + if: steps.changes.outputs.dependencymanager == 'true' + working-directory: dependencymanager + run: | + # The annotation bundle is a bnd plugin used by the other projects. It has to exist + # before they are configured, so it is built in a separate Gradle invocation. + ./gradlew --no-daemon --console=plain org.apache.felix.dependencymanager.annotation:jar + ./gradlew --no-daemon --console=plain build - name: Upload Test Results if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 diff --git a/dependencymanager/.gitignore b/dependencymanager/.gitignore index de001d36b8..43e206aada 100644 --- a/dependencymanager/.gitignore +++ b/dependencymanager/.gitignore @@ -6,3 +6,6 @@ /RemoteSystemsTempFiles/ /rat-report.xml +/build/ +/cnf/localrepo/ +/cnf/releaserepo/ diff --git a/dependencymanager/.gradle-wrapper/gradle-wrapper.properties b/dependencymanager/.gradle-wrapper/gradle-wrapper.properties index e65df494a7..8364c22200 100644 --- a/dependencymanager/.gradle-wrapper/gradle-wrapper.properties +++ b/dependencymanager/.gradle-wrapper/gradle-wrapper.properties @@ -20,4 +20,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip diff --git a/dependencymanager/build.gradle b/dependencymanager/build.gradle index 71ae1fde12..8219eef85e 100644 --- a/dependencymanager/build.gradle +++ b/dependencymanager/build.gradle @@ -20,3 +20,11 @@ tasks.named('wrapper') { jarFile = rootProject.file('.gradle-wrapper/gradle-wrapper.jar') } + +// The bnd launcher based integration tests run in the testOSGi task, so the plain +// Gradle test task of those projects legitimately has no tests to discover. +subprojects { + tasks.withType(Test).configureEach { + failOnNoDiscoveredTests = false + } +} diff --git a/dependencymanager/cnf/build.bnd b/dependencymanager/cnf/build.bnd index b5144dc788..fc975a5a95 100644 --- a/dependencymanager/cnf/build.bnd +++ b/dependencymanager/cnf/build.bnd @@ -58,8 +58,8 @@ # # Java parameters # -javac.source: 1.8 -javac.target: 1.8 +javac.source: 11 +javac.target: 11 # # Removes some headers in order to reduce binary diff between same bundles that are not changed between subsequent releases. diff --git a/dependencymanager/cnf/ext/junit.bnd b/dependencymanager/cnf/ext/junit.bnd index 129c585689..99bc945e5f 100644 --- a/dependencymanager/cnf/ext/junit.bnd +++ b/dependencymanager/cnf/ext/junit.bnd @@ -15,5 +15,5 @@ # limitations under the License. # -junit: org.apache.servicemix.bundles.junit; version=4.12 +junit: org.apache.servicemix.bundles.junit; version=4.13.2 test-reports: test-results diff --git a/dependencymanager/cnf/ext/libraries.bnd b/dependencymanager/cnf/ext/libraries.bnd index 9148780069..2bcb86467a 100644 --- a/dependencymanager/cnf/ext/libraries.bnd +++ b/dependencymanager/cnf/ext/libraries.bnd @@ -17,25 +17,25 @@ ## # metatype service -metatype=org.apache.felix.metatype;version=1.0.4 +metatype=org.apache.felix.metatype;version=1.2.4 ## # log service -log=org.apache.felix.log;version=1.0.1 +log=org.apache.felix.log;version=1.3.2 ## # Gogo bundles gogo=\ - org.apache.felix.gogo.command;version=1.0.2,\ - org.apache.felix.gogo.runtime;version=1.0.10,\ - org.apache.felix.gogo.shell;version=1.0.0,\ - org.jline;version=3.0.4,\ + org.apache.felix.gogo.command;version=latest,\ + org.apache.felix.gogo.runtime;version=latest,\ + org.apache.felix.gogo.shell;version=latest,\ + org.jline;version=3.29.0,\ org.fusesource.jansi;version=1.16.0 ## # Configuration Admin -configadmin=org.apache.felix.configadmin;version=1.8.8 +configadmin=org.apache.felix.configadmin;version=latest ## # Event Admin @@ -53,25 +53,30 @@ webconsole=\ ## # bndlib -bndlib=biz.aQute.bndlib;version=5.2.0 +bndlib=biz.aQute.bndlib;version=7.4.0 ## # mockito -mockito=org.mockito.mockito-core;version=1.10.19 +mockito=\ + org.mockito.mockito-core;version=5.24.0,\ + net.bytebuddy.byte-buddy;version=1.17.7,\ + net.bytebuddy.byte-buddy-agent;version=1.17.7 ## # objenesis -objenesis=org.objenesis;version=2.2 +objenesis=org.objenesis;version=3.3 ## # runtime dependencies used by integration tests # itest.run=\ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.mockito.mockito-core;version='[1.10.19,1.10.20)',\ - org.objenesis;version='[2.2.0,2.2.1)' + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.mockito.mockito-core;version='[5.24.0,5.25)',\ + net.bytebuddy.byte-buddy;version='[1.17.7,1.18)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.7,1.18)',\ + org.objenesis;version='[3.3.0,3.3.1)' ## # Felix Framework # -felix.framework=org.apache.felix.framework;version='[5.6.10,5.6.10]' +felix.framework=org.apache.felix.framework;version='[8.0.0,9)' diff --git a/dependencymanager/cnf/repository.mvn b/dependencymanager/cnf/repository.mvn index 46d73cba8c..ebebab0bbf 100644 --- a/dependencymanager/cnf/repository.mvn +++ b/dependencymanager/cnf/repository.mvn @@ -16,19 +16,19 @@ # ant:ant:1.5 -biz.aQute.bnd:biz.aQute.bnd.gradle:5.2.0 -biz.aQute.bnd:biz.aQute.bndlib:5.2.0 -org.apache.felix:org.apache.felix.framework:5.6.10 +biz.aQute.bnd:biz.aQute.bnd.gradle:7.4.0 +biz.aQute.bnd:biz.aQute.bndlib:7.4.0 +org.apache.felix:org.apache.felix.framework:8.0.0-SNAPSHOT org.apache.felix:org.apache.felix.eventadmin:1.4.4 -org.apache.felix:org.apache.felix.gogo.command:1.0.2 -org.apache.felix:org.apache.felix.gogo.shell:1.0.0 -org.apache.felix:org.apache.felix.gogo.runtime:1.0.10 -org.jline:jline:3.0.4 +org.apache.felix:org.apache.felix.gogo.command:1.1.3-SNAPSHOT +org.apache.felix:org.apache.felix.gogo.shell:1.1.5-SNAPSHOT +org.apache.felix:org.apache.felix.gogo.runtime:1.2.0-SNAPSHOT +org.jline:jline:3.29.0 org.apache.felix:org.apache.felix.http.api:3.0.0 org.apache.felix:org.apache.felix.http.servlet-api:1.1.2 -org.apache.felix:org.apache.felix.configadmin:1.8.8 -org.apache.felix:org.apache.felix.log:1.0.1 -org.apache.felix:org.apache.felix.metatype:1.1.2 +org.apache.felix:org.apache.felix.configadmin:1.10.0-SNAPSHOT +org.apache.felix:org.apache.felix.log:1.3.2 +org.apache.felix:org.apache.felix.metatype:1.2.4 org.apache.felix:org.apache.felix.http.jetty:3.4.8 org.apache.felix:org.apache.felix.webconsole:4.3.4 org.apache.felix:org.apache.felix.dependencymanager:4.6.1 @@ -37,12 +37,14 @@ org.apache.felix:org.apache.felix.dependencymanager.lambda:1.2.2 org.apache.felix:org.apache.felix.dependencymanager.runtime:4.0.8 org.apache.felix:org.apache.felix.dependencymanager.shell:4.0.9 org.jline:jline-builtins:3.3.0 -org.apache.servicemix.bundles:org.apache.servicemix.bundles.junit:4.12_1 -org.mockito:mockito-core:1.10.19 -org.objenesis:objenesis:2.2 -org.osgi:osgi.annotation:6.0.1 -org.osgi:osgi.cmpn:6.0.0 -org.osgi:osgi.core:6.0.0 +org.apache.servicemix.bundles:org.apache.servicemix.bundles.junit:4.13.2_1 +org.mockito:mockito-core:5.24.0 +net.bytebuddy:byte-buddy:1.17.7 +net.bytebuddy:byte-buddy-agent:1.17.7 +org.objenesis:objenesis:3.3 +org.osgi:osgi.annotation:8.1.0 +org.osgi:osgi.cmpn:7.0.0 +org.osgi:osgi.core:8.0.0 biz.aQute.bnd:biz.aQute.bnd.annotation:3.5.0 org.slf4j:slf4j-simple:1.7.7 org.slf4j:slf4j-api:1.7.7 diff --git a/dependencymanager/gradle.properties b/dependencymanager/gradle.properties index 35354fb51e..a36e805284 100644 --- a/dependencymanager/gradle.properties +++ b/dependencymanager/gradle.properties @@ -17,9 +17,9 @@ * under the License. */ -bnd_version=5.2.0 +bnd_version=7.4.0 # bnd_plugin is the dependency declaration for the bnd gradle plugin -bnd_plugin=biz.aQute.bnd:biz.aQute.bnd.gradle:5.2.0 +bnd_plugin=biz.aQute.bnd:biz.aQute.bnd.gradle:7.4.0 org.gradle.jvmargs=-Xmx2g diff --git a/dependencymanager/org.apache.felix.dependencymanager.annotation/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.annotation/bnd.bnd index 9d04b269de..06ad54cc73 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.annotation/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.annotation/bnd.bnd @@ -14,11 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # -Bundle-Version: 5.0.3 +Bundle-Version: 6.0.0 -buildpath: \ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ - biz.aQute.bndlib;version=3.5 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ + biz.aQute.bndlib;version=7.4.0 Private-Package: org.apache.felix.dm.annotation.plugin.bnd Export-Package: org.apache.felix.dm.annotation.api Include-Resource: META-INF/=resources/,META-INF/changelog.txt=changelog.txt diff --git a/dependencymanager/org.apache.felix.dependencymanager.benchmark/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.benchmark/bnd.bnd index 57c6346496..4b0f4eb236 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.benchmark/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.benchmark/bnd.bnd @@ -14,13 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. # -javac.source: 1.8 -javac.target: 1.8 +javac.source: 11 +javac.target: 11 Bundle-Version: 1.0.0 -buildpath: \ org.apache.felix.dependencymanager;version=latest,\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0 -sub: \ *.bnd diff --git a/dependencymanager/org.apache.felix.dependencymanager.index.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.index.itest/bnd.bnd index 48b9256ed0..8efac4401d 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.index.itest/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.index.itest/bnd.bnd @@ -15,27 +15,27 @@ # limitations under the License. # -runbundles: \ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.apache.felix.metatype;version=1.1.2,\ - org.apache.felix.log;version=1.0.1,\ - org.apache.felix.configadmin;version=1.8.8,\ + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.apache.felix.metatype;version=1.2.4,\ + org.apache.felix.log;version=1.3.2,\ + org.apache.felix.configadmin;version=latest,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest,\ org.apache.felix.dependencymanager.index.itest.dynamic.customindex;version=latest,\ org.apache.felix.dependencymanager.index.itest.static.customindex;version=latest,\ org.apache.felix.dependencymanager.index.itest.tests;version=latest,\ - org.apache.felix.gogo.runtime;version=1.0.6 + org.apache.felix.gogo.runtime;version=latest --runee: JavaSE-1.8 +-runee: JavaSE-11 -runvm: -ea --runfw: org.apache.felix.framework;version='[5.6.10,5.6.10]' +-runfw: org.apache.felix.framework;version='[8.0.0,9)' -buildpath: \ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest,\ ${junit},\ - org.apache.felix.gogo.runtime;version=1.0 + org.apache.felix.gogo.runtime;version=latest -runsystempackages: \ sun.reflect Test-Cases: \ diff --git a/dependencymanager/org.apache.felix.dependencymanager.index.itest/src/org/apache/felix/dm/index/itest/tests/TestBase.java b/dependencymanager/org.apache.felix.dependencymanager.index.itest/src/org/apache/felix/dm/index/itest/tests/TestBase.java index 36a98fe7a8..fa17ba1272 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.index.itest/src/org/apache/felix/dm/index/itest/tests/TestBase.java +++ b/dependencymanager/org.apache.felix.dependencymanager.index.itest/src/org/apache/felix/dm/index/itest/tests/TestBase.java @@ -223,15 +223,40 @@ protected void sleep(int ms) { return (Dictionary) properties; } + @Override + public org.osgi.service.log.Logger getLogger(String name) { + return null; + } + + @Override + public org.osgi.service.log.Logger getLogger(Class clazz) { + return null; + } + + @Override + public L getLogger(Bundle bundle, String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(Class clazz, Class loggerType) { + return null; + } + public void log(int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { System.out.println(getLevel(level) + " - " + Thread.currentThread().getName() + " : " + message); } } public void log(int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -242,7 +267,7 @@ public void log(int level, String message, Throwable exception) { } public void log(ServiceReference sr, int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -252,7 +277,7 @@ public void log(ServiceReference sr, int level, String message) { } public void log(ServiceReference sr, int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -292,7 +317,16 @@ private String getLevel(int level) { } } - private void checkError(int level, Throwable exception) { + // Config Admin logs this at error level when a factory configuration has been created but not updated yet + // while the factory registers. It provides the configuration with the update, so it is not an error. + private static boolean isIgnoredMessage(String message) { + return message != null && message.startsWith("Ignoring new configuration pid="); + } + + private void checkError(int level, String message, Throwable exception) { + if (isIgnoredMessage(message) && exception == null) { + return; + } if (level <= LOG_ERROR) { m_errorsLogged = true; } diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd index 3005063c94..a3f4efab51 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/bnd.bnd @@ -15,27 +15,29 @@ # limitations under the License. # -runbundles: \ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.mockito.mockito-core;version='[1.10.19,1.10.20)',\ - org.objenesis;version='[2.2.0,2.2.1)',\ - org.apache.felix.metatype;version=1.1.2,\ - org.apache.felix.log;version=1.0.1,\ - org.apache.felix.configadmin;version=1.8.8,\ + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.mockito.mockito-core;version='[5.24.0,5.25)',\ + net.bytebuddy.byte-buddy;version='[1.17.7,1.18)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.7,1.18)',\ + org.objenesis;version='[3.3.0,3.3.1)',\ + org.apache.felix.metatype;version=1.2.4,\ + org.apache.felix.log;version=1.3.2,\ + org.apache.felix.configadmin;version=latest,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest,\ - org.apache.felix.gogo.runtime;version=1.0.6,\ + org.apache.felix.gogo.runtime;version=latest,\ org.apache.felix.gogo.shell,\ org.apache.felix.gogo.command --runee: JavaSE-1.8 +-runee: JavaSE-11 -runvm: -ea --runfw: org.apache.felix.framework;version='[5.6.10,5.6.10]' +-runfw: org.apache.felix.framework;version='[8.0.0,9)' -buildpath: \ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest,\ ${junit},\ - org.apache.felix.gogo.runtime;version=1.0 + org.apache.felix.gogo.runtime;version=latest -runsystempackages: \ sun.reflect -sub: \ diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/ConfigurationDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/ConfigurationDependencyTest.java index 23ab0d1924..e90581e0bb 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/ConfigurationDependencyTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/ConfigurationDependencyTest.java @@ -27,6 +27,7 @@ import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.itest.util.ConfigDeliveries; import org.apache.felix.dm.itest.util.Ensure; import org.apache.felix.dm.itest.util.TestBase; import org.osgi.service.cm.Configuration; @@ -40,7 +41,8 @@ */ @SuppressWarnings({"unchecked", "rawtypes"}) public class ConfigurationDependencyTest extends TestBase { - final static String PID = "ConfigurationDependencyTest.pid"; + // Unique per test, so that the asynchronous deletion of the configuration of a previous test cannot reach the next one. + final String PID = "ConfigurationDependencyTest.pid." + System.nanoTime(); /** * Tests that we can provision a type-safe configuration to a component. @@ -222,6 +224,7 @@ public void destroy() throws IOException { static class ConfigurationConsumer implements ManagedService, Runnable { protected final Ensure m_ensure; + protected final ConfigDeliveries m_deliveries = new ConfigDeliveries(); public ConfigurationConsumer(Ensure e) { m_ensure = e; @@ -229,6 +232,9 @@ public ConfigurationConsumer(Ensure e) { public void updated(Dictionary props) throws ConfigurationException { Assert.assertNotNull(props); + if (m_deliveries.isRepeat(props)) { + return; + } m_ensure.step(2); if (!"testvalue".equals(props.get("testkey"))) { Assert.fail("Could not find the configured property."); @@ -253,6 +259,9 @@ public ConfigurationConsumer3(Ensure e) { public void updated(Dictionary props) throws ConfigurationException { Assert.assertNotNull(props); + if (m_deliveries.isRepeat(props)) { + return; + } if (!"testvalue".equals(props.get("testkey"))) { Assert.fail("Could not find the configured property."); } @@ -276,6 +285,9 @@ public ConfigurationConsumer4(Ensure e) { } public void updated(Dictionary props) throws ConfigurationException { + if (m_deliveries.isRepeat(props)) { + return; + } if (! m_configured) { Assert.assertNotNull(props); if (!"testvalue".equals(props.get("testkey"))) { @@ -310,6 +322,7 @@ public void updatedWithComponentArg(Component component, Dictionary props) throw static class ConfigurationConsumerCallbackInstance { private final Ensure m_ensure; + private final ConfigDeliveries m_deliveries = new ConfigDeliveries(); public ConfigurationConsumerCallbackInstance(Ensure e) { m_ensure = e; @@ -317,6 +330,9 @@ public ConfigurationConsumerCallbackInstance(Ensure e) { public void updateConfiguration(Dictionary props) throws Exception { Assert.assertNotNull(props); + if (m_deliveries.isRepeat(props)) { + return; + } m_ensure.step(2); if (!"testvalue".equals(props.get("testkey"))) { Assert.fail("Could not find the configured property."); @@ -368,6 +384,7 @@ static interface MyConfig { static class ConfigurationConsumerWithTypeSafeConfiguration { private final Ensure m_ensure; + private final ConfigDeliveries m_deliveries = new ConfigDeliveries(); public ConfigurationConsumerWithTypeSafeConfiguration(Ensure e) { m_ensure = e; @@ -376,6 +393,9 @@ public ConfigurationConsumerWithTypeSafeConfiguration(Ensure e) { // configuration updates is always the first invoked callback (before init). public void updated(Component component, MyConfig cfg) throws ConfigurationException { if (cfg != null) { + if (m_deliveries.isRepeat((Object) cfg.getTestkey())) { + return; + } Assert.assertNotNull(component); Assert.assertNotNull(cfg); m_ensure.step(2); @@ -383,6 +403,7 @@ public void updated(Component component, MyConfig cfg) throws ConfigurationExcep Assert.fail("Could not find the configured property."); } } else { + m_deliveries.isRepeat((Dictionary) null); m_ensure.step(); } } diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5200_FactoryPidNotRestartedTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5200_FactoryPidNotRestartedTest.java index 1bab665482..9b484f09d9 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5200_FactoryPidNotRestartedTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5200_FactoryPidNotRestartedTest.java @@ -21,10 +21,10 @@ import java.io.IOException; import java.util.Dictionary; import java.util.Properties; +import java.util.function.BooleanSupplier; import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; -import org.apache.felix.dm.itest.util.Ensure; import org.apache.felix.dm.itest.util.TestBase; import org.junit.Assert; import org.osgi.service.cm.Configuration; @@ -35,24 +35,22 @@ * The factory configuration is created, the "Required" service is registered, so a factory configuration adapter INSTANCE1 is then created. * Now the "Required" service is unregistered: the factory config adapter INSTANCE1 is then stopped. * And when the "Required" service comes up again, then a new factory config adapter INSTANCE2 should be re-created, updated and started. + * When the factory configuration is removed, the factory config adapter instance is stopped. + *

+ * Config Admin may deliver the configuration to the factory more than once (for example when the factory is + * registered again), which makes the adapter instance be replaced by an other one. The test does not depend on + * how often that happens: it follows the instances instead of counting the calls. * * @author Felix Project Team */ public class FELIX5200_FactoryPidNotRestartedTest extends TestBase { - static FactoryPidComponent m_currentInstance; + private static final int TIMEOUT = 10000; - static Ensure m_ensure = new Ensure(); + // the instances of the adapter, in the order they have been started + static final java.util.List m_instances = new java.util.concurrent.CopyOnWriteArrayList<>(); - static Ensure.Steps m_steps = new Ensure.Steps( - 1, // updated is called the first time the adapter instance is created - 2, // component started - 3, // "Required" service is unregistered, and adapter instance is stopped - 4, // "Required" service is re-registered, a new adapter instance is created and called in updated - 5, // the new adapter instance is then started - 6 // the configuration is removed and the new adapter instance is stopped - ); - - public void testFactoryAdapterNotRestartedTest() { + public void testFactoryAdapterNotRestartedTest() throws InterruptedException { + m_instances.clear(); DependencyManager dm = getDM(); Component adapter = dm.createFactoryConfigurationAdapterService("factory.pid", "updated", false) @@ -71,35 +69,48 @@ public void testFactoryAdapterNotRestartedTest() { dm.add(adapter); dm.add(required); // adapter instance1 updated and started - m_ensure.waitForStep(2, 5000); - FactoryPidComponent currentInstance = m_currentInstance; + waitFor("the first adapter instance is started", () -> !m_instances.isEmpty()); + FactoryPidComponent instance1 = m_instances.get(0); + dm.remove(required); // adapter instance1 stopped - m_ensure.waitForStep(3, 5000); + waitFor("the first adapter instance is stopped", () -> instance1.m_stopped); + int started = m_instances.size(); + dm.add(required); - // adapter instance2 updated and started - m_ensure.waitForStep(5, 5000); - // a new adapter instance should have been created - Assert.assertNotEquals(currentInstance, m_currentInstance); + // a new adapter instance is created, updated and started + waitFor("a new adapter instance is started", () -> m_instances.size() > started); + FactoryPidComponent instance2 = m_instances.get(m_instances.size() - 1); + Assert.assertNotSame(instance1, instance2); + dm.remove(configurator); - // adapter instance2 stopped - m_ensure.waitForStep(6, 5000); + // the configuration is removed: the last adapter instance is stopped + waitFor("the adapter instance is stopped when the configuration is removed", () -> instance2.m_stopped); + } + + private void waitFor(String what, BooleanSupplier condition) throws InterruptedException { + long end = System.currentTimeMillis() + TIMEOUT; + while (!condition.getAsBoolean()) { + if (System.currentTimeMillis() > end) { + Assert.fail("Timed out waiting until " + what); + } + Thread.sleep(10); + } } public static class FactoryPidComponent { RequiredService m_required; + volatile boolean m_stopped; void updated(Dictionary properties) { - m_ensure.steps(m_steps); } void start() { - m_ensure.steps(m_steps); - m_currentInstance = this; + m_instances.add(this); } void stop() { - m_ensure.steps(m_steps); + m_stopped = true; } } diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5238_TypeSafeConfigWithDefaultMethodTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5238_TypeSafeConfigWithDefaultMethodTest.java index 3c8c92eb59..0096e073b9 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5238_TypeSafeConfigWithDefaultMethodTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5238_TypeSafeConfigWithDefaultMethodTest.java @@ -20,6 +20,7 @@ import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.itest.util.ConfigDeliveries; import org.apache.felix.dm.itest.util.Ensure; import org.apache.felix.dm.itest.util.TestBase; import org.junit.Assert; @@ -34,7 +35,8 @@ * @author Felix Project Team */ public class FELIX5238_TypeSafeConfigWithDefaultMethodTest extends TestBase { - final static String PID = "ConfigurationDependencyTest.pid"; + // Unique per test, so that the asynchronous deletion of the configuration of a previous test cannot reach the next one. + final String PID = "FELIX5238_TypeSafeConfigWithDefaultMethodTest.pid." + System.nanoTime(); /** * Tests that we can provision a type-safe config annotation to a component. @@ -92,6 +94,7 @@ public static interface MyConfigInterface { static class ConfigurationConsumerBase { protected final Ensure m_ensure; + protected final ConfigDeliveries m_deliveries = new ConfigDeliveries(); public ConfigurationConsumerBase(Ensure e) { m_ensure = e; @@ -115,6 +118,9 @@ public ConfigurationConsumer1(Ensure e) { // configuration updates is always the first invoked callback (before init). public void updated(Component component, MyConfigAnnot cfg) throws ConfigurationException { if (cfg != null) { + if (m_deliveries.isRepeat((Object) (cfg.getTestkey() + "/" + cfg.getTestkey2()))) { + return; + } Assert.assertNotNull(component); Assert.assertNotNull(cfg); if (!"testvalue".equals(cfg.getTestkey())) { @@ -125,6 +131,7 @@ public void updated(Component component, MyConfigAnnot cfg) throws Configuration } m_ensure.step(2); } else { + m_deliveries.isRepeat((java.util.Dictionary) null); m_ensure.step(); } } @@ -138,6 +145,9 @@ public ConfigurationConsumer2(Ensure e) { // configuration updates is always the first invoked callback (before init). public void updated(Component component, MyConfigInterface cfg) throws ConfigurationException { if (cfg != null) { + if (m_deliveries.isRepeat((Object) (cfg.getTestkey() + "/" + cfg.getTestkey2()))) { + return; + } Assert.assertNotNull(component); Assert.assertNotNull(cfg); if (!"testvalue".equals(cfg.getTestkey())) { @@ -148,6 +158,7 @@ public void updated(Component component, MyConfigInterface cfg) throws Configura } m_ensure.step(2); } else { + m_deliveries.isRepeat((java.util.Dictionary) null); m_ensure.step(); } } diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest.java index ed7762c4df..1d3a206c5d 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest.java @@ -45,7 +45,8 @@ * @author Felix Project Team */ public class FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest extends TestBase { - final static String PID = "ConfigurationDependencyTest.pid"; + // Unique per test, so that the asynchronous deletion of the configuration of a previous test cannot reach the next one. + final String PID = "FELIX5243_ConfigUpdateMissedIfComponentIsRestartingTest.pid." + System.nanoTime(); public void testOptionalConfigurationConsumer() throws InterruptedException { DependencyManager m = getDM(); diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/OptionalConfigurationDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/OptionalConfigurationDependencyTest.java index 9be16c0255..49c3dcec22 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/OptionalConfigurationDependencyTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/OptionalConfigurationDependencyTest.java @@ -20,6 +20,7 @@ import org.apache.felix.dm.Component; import org.apache.felix.dm.DependencyManager; +import org.apache.felix.dm.itest.util.ConfigDeliveries; import org.apache.felix.dm.itest.util.Ensure; import org.apache.felix.dm.itest.util.TestBase; import org.junit.Assert; @@ -40,7 +41,8 @@ * @author Felix Project Team */ public class OptionalConfigurationDependencyTest extends TestBase { - final static String PID = "ConfigurationDependencyTest.pid"; + // Unique per test, so that the asynchronous deletion of the configuration of a previous test cannot reach the next one. + final String PID = "OptionalConfigurationDependencyTest.pid." + System.nanoTime(); public void testOptionalConfigurationConsumer() { DependencyManager m = getDM(); @@ -69,6 +71,7 @@ public static interface MyConfig { static class OptionalConfigurationConsumer { protected final Ensure m_ensure; protected volatile int m_updateCount; + private final ConfigDeliveries m_deliveries = new ConfigDeliveries(); public OptionalConfigurationConsumer(Ensure e) { m_ensure = e; @@ -76,6 +79,9 @@ public OptionalConfigurationConsumer(Ensure e) { public void updated(MyConfig cnf) { // optional configuration, called after start(), like any other optional dependency callbacks. if (cnf != null) { + if (m_deliveries.isRepeat((Object) cnf.getTestkey())) { + return; // the same configuration delivered again + } m_updateCount ++; if (m_updateCount == 1) { if (!"default".equals(cnf.getTestkey())) { diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/ConfigDeliveries.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/ConfigDeliveries.java new file mode 100644 index 0000000000..8250ef8093 --- /dev/null +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/ConfigDeliveries.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.felix.dm.itest.util; + +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Detects that Config Admin delivers the same configuration again to a callback. + *

+ * Config Admin can provide a configuration to a service twice, for example once because the service registers + * while the configuration is updated (an update of the registration and an update of the configuration, close + * together). The tests count the configuration updates they expect, and ignore such a repeated delivery. + */ +public class ConfigDeliveries { + private Object m_last; + + /** + * @return true if the configuration is the one which has been delivered the last time. A lost configuration + * (null) is never a repeat. + */ + public synchronized boolean isRepeat(Dictionary properties) { + if (properties == null) { + m_last = null; + return false; + } + Map copy = new HashMap<>(); + for (Object key : Collections.list(properties.keys())) { + copy.put(key, properties.get(key)); + } + return isRepeat((Object) copy); + } + + /** + * @param identity describes the content of a typed configuration, for example the values of its properties. + */ + public synchronized boolean isRepeat(Object identity) { + boolean repeat = identity != null && Objects.equals(identity, m_last); + m_last = identity; + return repeat; + } +} diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/TestBase.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/TestBase.java index 78da1484a0..c1754cd58c 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/TestBase.java +++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/util/TestBase.java @@ -222,15 +222,40 @@ protected void sleep(int ms) { return (Dictionary) properties; } + @Override + public org.osgi.service.log.Logger getLogger(String name) { + return null; + } + + @Override + public org.osgi.service.log.Logger getLogger(Class clazz) { + return null; + } + + @Override + public L getLogger(Bundle bundle, String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(Class clazz, Class loggerType) { + return null; + } + public void log(int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { System.out.println(getLevel(level) + " - " + Thread.currentThread().getName() + " : " + message); } } public void log(int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -241,7 +266,7 @@ public void log(int level, String message, Throwable exception) { } public void log(ServiceReference sr, int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -251,7 +276,7 @@ public void log(ServiceReference sr, int level, String message) { } public void log(ServiceReference sr, int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -291,7 +316,16 @@ private String getLevel(int level) { } } - private void checkError(int level, Throwable exception) { + // Config Admin logs this at error level when a factory configuration has been created but not updated yet + // while the factory registers. It provides the configuration with the update, so it is not an error. + private static boolean isIgnoredMessage(String message) { + return message != null && message.startsWith("Ignoring new configuration pid="); + } + + private void checkError(int level, String message, Throwable exception) { + if (isIgnoredMessage(message) && exception == null) { + return; + } if (level <= LOG_ERROR) { m_errorsLogged = true; } diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd index 118cfb1551..c2b0020695 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/bnd.bnd @@ -19,27 +19,29 @@ org.apache.felix.dependencymanager.shell;version=latest,\ org.apache.felix.dependencymanager.lambda;version=latest,\ ${junit},\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0 -runbundles: \ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.mockito.mockito-core;version='[1.10.19,1.10.20)',\ - org.objenesis;version='[2.2.0,2.2.1)',\ - org.apache.felix.metatype;version=1.0.10,\ - org.apache.felix.log;version=1.0.1,\ + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.mockito.mockito-core;version='[5.24.0,5.25)',\ + net.bytebuddy.byte-buddy;version='[1.17.7,1.18)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.7,1.18)',\ + org.objenesis;version='[3.3.0,3.3.1)',\ + org.apache.felix.metatype;version=1.2.4,\ + org.apache.felix.log;version=1.3.2,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest,\ - org.apache.felix.configadmin;version=1.8.8,\ + org.apache.felix.configadmin;version=latest,\ org.apache.felix.dependencymanager.lambda;version=latest,\ - org.apache.felix.gogo.runtime;version=1.0.6 + org.apache.felix.gogo.runtime;version=latest --runee: JavaSE-1.8 --runfw: org.apache.felix.framework;version='[5.6.10,5.6.10]' +-runee: JavaSE-11 +-runfw: org.apache.felix.framework;version='[8.0.0,9)' -runvm: -ea Bundle-Version: 0.0.0.${tstamp} Test-Cases: ${classes;CONCRETE;EXTENDS;junit.framework.TestCase} -javac.source: 1.8 -javac.target: 1.8 +javac.source: 11 +javac.target: 11 # all tests are configured to assume that dependencies are required by default -runproperties: \ diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java index efc034e034..8df2dd0e13 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java +++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.itest/src/org/apache/felix/dm/lambda/itest/TestBase.java @@ -216,15 +216,40 @@ protected void sleep(int ms) { } } + @Override + public org.osgi.service.log.Logger getLogger(String name) { + return null; + } + + @Override + public org.osgi.service.log.Logger getLogger(Class clazz) { + return null; + } + + @Override + public L getLogger(Bundle bundle, String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(String name, Class loggerType) { + return null; + } + + @Override + public L getLogger(Class clazz, Class loggerType) { + return null; + } + public void log(int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { System.out.println(getLevel(level) + " - " + Thread.currentThread().getName() + " : " + message); } } public void log(int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -236,7 +261,7 @@ public void log(int level, String message, Throwable exception) { @SuppressWarnings("rawtypes") public void log(ServiceReference sr, int level, String message) { - checkError(level, null); + checkError(level, message, null); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -247,7 +272,7 @@ public void log(ServiceReference sr, int level, String message) { @SuppressWarnings("rawtypes") public void log(ServiceReference sr, int level, String message, Throwable exception) { - checkError(level, exception); + checkError(level, message, exception); if (LOG_LEVEL >= level) { StringBuilder sb = new StringBuilder(); sb.append(getLevel(level) + " - " + Thread.currentThread().getName() + " : "); @@ -287,7 +312,16 @@ private String getLevel(int level) { } } - private void checkError(int level, Throwable exception) { + // Config Admin logs this at error level when a factory configuration has been created but not updated yet + // while the factory registers. It provides the configuration with the update, so it is not an error. + private static boolean isIgnoredMessage(String message) { + return message != null && message.startsWith("Ignoring new configuration pid="); + } + + private void checkError(int level, String message, Throwable exception) { + if (isIgnoredMessage(message) && exception == null) { + return; + } if (level <= LOG_ERROR) { m_errorsLogged = true; } diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd index 5b5b5a1066..559acfb89e 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.lambda.samples/bnd.bnd @@ -2,8 +2,8 @@ org.apache.felix.dependencymanager.lambda;version=latest,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.gogo.runtime;version=latest,\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ biz.aQute.bnd.annotation Bundle-Version: 0.0.0.${tstamp} diff --git a/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd index 604546bb1b..c0fc44827e 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.lambda/bnd.bnd @@ -14,18 +14,18 @@ # See the License for the specific language governing permissions and # limitations under the License. # -javac.source: 1.8 -javac.target: 1.8 -Bundle-Version: 1.2.3 +javac.source: 11 +javac.target: 11 +Bundle-Version: 2.0.0 -buildpath: \ org.apache.felix.dependencymanager;version=latest,\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ - osgi.annotation;version=6.0.1 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ + osgi.annotation;version=8.1 Export-Package: \ org.apache.felix.dm.lambda,\ org.apache.felix.dm.lambda.callbacks --runfw: org.apache.felix.framework;version='[4.4.1,4.4.1]' --runee: JavaSE-1.8 +-runfw: org.apache.felix.framework;version='[8.0.0,9)' +-runee: JavaSE-11 Private-Package: org.apache.felix.dm.lambda.impl Include-Resource: META-INF/=resources/,META-INF/changelog.txt=changelog.txt diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd index 239126ee5b..cfc781e5f8 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd @@ -20,22 +20,24 @@ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.runtime;version=latest,\ org.apache.felix.dependencymanager.itest.api;version=latest,\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0 -runbundles: \ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.mockito.mockito-core;version='[1.10.19,1.10.20)',\ - org.objenesis;version='[2.2.0,2.2.1)',\ - org.apache.felix.metatype;version=1.1.2,\ - org.apache.servicemix.bundles.junit;version=4.12,\ - org.apache.felix.configadmin;version=1.8.8,\ - org.apache.felix.gogo.runtime;version=1.0.6,\ - org.apache.felix.log;version=1.0.1,\ + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.mockito.mockito-core;version='[5.24.0,5.25)',\ + net.bytebuddy.byte-buddy;version='[1.17.7,1.18)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.7,1.18)',\ + org.objenesis;version='[3.3.0,3.3.1)',\ + org.apache.felix.metatype;version=1.2.4,\ + org.apache.servicemix.bundles.junit;version=4.13.2,\ + org.apache.felix.configadmin;version=latest,\ + org.apache.felix.gogo.runtime;version=latest,\ + org.apache.felix.log;version=1.3.2,\ org.apache.felix.dependencymanager;version=latest,\ org.apache.felix.dependencymanager.runtime;version=latest,\ org.apache.felix.dependencymanager.shell;version=latest --runee: JavaSE-1.7 --runfw: org.apache.felix.framework;version='[5.6.10,5.6.10]' +-runee: JavaSE-11 +-runfw: org.apache.felix.framework;version='[8.0.0,9)' -runsystempackages: \ sun.reflect -runvm:-ea diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd index 7236438f9d..def3055b76 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/bnd.bnd @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -Bundle-Version: 4.0.9 +Bundle-Version: 5.0.0 -buildpath: \ osgi.core;version=4.2,\ osgi.cmpn;version=4.2,\ diff --git a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java index fb4456ba09..55581f8d06 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java +++ b/dependencymanager/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/InvocationUtil.java @@ -22,8 +22,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; -import java.security.AccessController; -import java.security.PrivilegedAction; /** * Java reflexion utility methods. @@ -90,14 +88,7 @@ public static Object invokeMethod(Object object, final Method m = clazz.getDeclaredMethod(name, signature); if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) { - AccessController.doPrivileged(new PrivilegedAction() - { - public Object run() - { - m.setAccessible(true); - return null; - } - }); + m.setAccessible(true); return m.invoke(object, parameters[i]); } } diff --git a/dependencymanager/org.apache.felix.dependencymanager.samples/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.samples/bnd.bnd index 0c8e16ebd8..1b2d1769f3 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.samples/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.samples/bnd.bnd @@ -21,8 +21,8 @@ Bundle-Version: 1.0.0.${tstamp} org.apache.felix.gogo.runtime;version=latest,\ org.apache.felix.dependencymanager.runtime;version=latest,\ org.apache.felix.dependencymanager.annotation;version=latest,\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0 -sub: \ *.bnd -metatype: * diff --git a/dependencymanager/org.apache.felix.dependencymanager.shell/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager.shell/bnd.bnd index 957d03bf5e..a266661fda 100644 --- a/dependencymanager/org.apache.felix.dependencymanager.shell/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager.shell/bnd.bnd @@ -18,13 +18,13 @@ ${mockito},\ org.apache.felix.dependencymanager;version=latest,\ ${junit},\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ - org.apache.felix.gogo.runtime;version=1.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ + org.apache.felix.gogo.runtime;version=latest Private-Package: \ org.apache.felix.dm.shell Bundle-Activator:org.apache.felix.dm.shell.Activator -Bundle-Version: 4.0.10 +Bundle-Version: 5.0.0 Include-Resource: META-INF/=resources/,META-INF/changelog.txt=changelog.txt Bundle-Name: Apache Felix Dependency Manager Shell Bundle-Description: Gogo Shell commands for Apache Felix Dependency Manager @@ -34,4 +34,4 @@ Bundle-Vendor: The Apache Software Foundation -testpath: \ ${junit},\ ${mockito},\ - org.objenesis;version=2.2 + org.objenesis;version=3.3 diff --git a/dependencymanager/org.apache.felix.dependencymanager/bnd.bnd b/dependencymanager/org.apache.felix.dependencymanager/bnd.bnd index 26ec2d9672..8be859759b 100644 --- a/dependencymanager/org.apache.felix.dependencymanager/bnd.bnd +++ b/dependencymanager/org.apache.felix.dependencymanager/bnd.bnd @@ -17,9 +17,9 @@ -buildpath: \ ${mockito},\ ${junit},\ - osgi.core;version=6.0,\ - osgi.cmpn;version=6.0,\ - osgi.annotation;version=6.0 + osgi.core;version=8.0,\ + osgi.cmpn;version=7.0,\ + osgi.annotation;version=8.1 Private-Package: \ org.apache.felix.dm.impl,\ org.apache.felix.dm.impl.index,\ @@ -34,7 +34,7 @@ Export-Package: \ Include-Resource: META-INF/=resources/,META-INF/changelog.txt=changelog.txt Import-Package: !org.junit,!org.mockito.*,org.osgi.framework;version="[1.8, 2)",* Bundle-Activator: org.apache.felix.dm.impl.Activator -Bundle-Version: 4.6.2 +Bundle-Version: 5.0.0 Bundle-Name: Apache Felix Dependency Manager Bundle-Description: Provides dynamic service and component dependency management Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt @@ -45,7 +45,7 @@ Bundle-Category: osgi -testpath: \ ${junit},\ ${mockito},\ - org.objenesis;version=2.2 + org.objenesis;version=3.3 diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/tracker/ServiceTracker.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/tracker/ServiceTracker.java index 9148a5d005..55df178e50 100644 --- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/tracker/ServiceTracker.java +++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/tracker/ServiceTracker.java @@ -15,8 +15,6 @@ * limitations under the License. */ -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -259,15 +257,9 @@ public ServiceTracker(final BundleContext context, final Filter filter, this.context = context; this.trackReference = null; this.trackClass = null; - final Version frameworkVersion = (Version) AccessController - .doPrivileged(new PrivilegedAction() { - public Version run() { - String version = context - .getProperty(Constants.FRAMEWORK_VERSION); - return (version == null) ? Version.emptyVersion - : new Version(version); - } - }); + final String version = context.getProperty(Constants.FRAMEWORK_VERSION); + final Version frameworkVersion = (version == null) ? Version.emptyVersion + : new Version(version); final boolean endMatchSupported = (frameworkVersion .compareTo(endMatchVersion) >= 0); this.listenerFilter = endMatchSupported ? filter.toString() : null; diff --git a/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/tracker/TrackedTest.java b/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/tracker/TrackedTest.java index 5b12dbce96..432e27045b 100644 --- a/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/tracker/TrackedTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/tracker/TrackedTest.java @@ -255,6 +255,18 @@ public Bundle getBundle() { return null; } + @Override + @SuppressWarnings("rawtypes") + public java.util.Dictionary getProperties() { + return null; + } + + @Override + @SuppressWarnings("rawtypes") + public Object adapt(Class type) { + return null; + } + @Override public Bundle[] getUsingBundles() { return null; diff --git a/dependencymanager/org.apache.felix.dependencymanager/test/test/MultiPropertyFilterIndexReferencedTest.java b/dependencymanager/org.apache.felix.dependencymanager/test/test/MultiPropertyFilterIndexReferencedTest.java index 1fd8fd044c..aff6950240 100644 --- a/dependencymanager/org.apache.felix.dependencymanager/test/test/MultiPropertyFilterIndexReferencedTest.java +++ b/dependencymanager/org.apache.felix.dependencymanager/test/test/MultiPropertyFilterIndexReferencedTest.java @@ -281,6 +281,18 @@ public Bundle getBundle() { return null; } + @Override + @SuppressWarnings("rawtypes") + public java.util.Dictionary getProperties() { + return null; + } + + @Override + @SuppressWarnings("rawtypes") + public Object adapt(Class type) { + return null; + } + @Override public Bundle[] getUsingBundles() { return null; diff --git a/dependencymanager/org.apache.felix.dependencymanager/test/test/TestReference.java b/dependencymanager/org.apache.felix.dependencymanager/test/test/TestReference.java index 73ebc6bea1..a90c702eb4 100644 --- a/dependencymanager/org.apache.felix.dependencymanager/test/test/TestReference.java +++ b/dependencymanager/org.apache.felix.dependencymanager/test/test/TestReference.java @@ -69,6 +69,18 @@ public Bundle getBundle() { return null; } + @Override + @SuppressWarnings("rawtypes") + public java.util.Dictionary getProperties() { + return null; + } + + @Override + @SuppressWarnings("rawtypes") + public Object adapt(Class type) { + return null; + } + @Override public Bundle[] getUsingBundles() { return null; diff --git a/dependencymanager/release/build.gradle b/dependencymanager/release/build.gradle index db781b0390..abf3c108f4 100644 --- a/dependencymanager/release/build.gradle +++ b/dependencymanager/release/build.gradle @@ -44,19 +44,14 @@ ext.svnReleasePath = "https://dist.apache.org/repos/dist/release/felix" apply plugin: 'java' apply from: file("rat.gradle") -// Add bnd as a build dependency -buildscript { - dependencies { - classpath files('cnf/gradle/biz.aQute.bnd.gradle.jar') - } -} - // Configure RAT plugin to ignore some files rat { excludes = [ 'rat-report.xml', '**/.git/**', '**/.gradle/**', + 'build/**', + '**/.keepme', '**/.project', '**/.settings/**', '**/*.iml', @@ -82,7 +77,7 @@ rat { // Setup the workspace Workspace workspace -workspace = Workspace.getWorkspace(".") +workspace = Workspace.getWorkspace(rootProject.projectDir) task makeStaging { doLast { diff --git a/dependencymanager/release/rat.gradle b/dependencymanager/release/rat.gradle index a15d798d87..0a572f2baf 100644 --- a/dependencymanager/release/rat.gradle +++ b/dependencymanager/release/rat.gradle @@ -20,7 +20,8 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task -import org.gradle.api.internal.project.IsolatedAntBuilder +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal apply plugin: RatPlugin @@ -28,20 +29,24 @@ class RatTask extends DefaultTask { @Input List excludes - def reportPath = '.' - def xmlReport = reportPath + '/rat-report.xml' + // Directory which is checked, and the file the xml report is written to. + @Internal + File baseDir - def generateXmlReport(File reportDir) { - def antBuilder = services.get(IsolatedAntBuilder) - def ratClasspath = project.configurations.rat - antBuilder.withClasspath(ratClasspath).execute { - ant.taskdef(resource: 'org/apache/rat/anttasks/antlib.xml') - ant.report(format: 'xml', reportFile: xmlReport) { - fileset(dir: ".") { - patternset { - excludes.each { - exclude(name: it) - } + @Internal + File xmlReport + + def generateXmlReport() { + xmlReport.parentFile.mkdirs() + def ratClasspath = project.configurations.rat.asPath + def ratExcludes = excludes + def checkedDir = baseDir + project.ant.taskdef(resource: 'org/apache/rat/anttasks/antlib.xml', classpath: ratClasspath) + project.ant.report(format: 'xml', reportFile: xmlReport.absolutePath) { + fileset(dir: checkedDir.absolutePath) { + patternset { + ratExcludes.each { + exclude(name: it) } } } @@ -49,7 +54,7 @@ class RatTask extends DefaultTask { } def printUnknownFiles() { - def ratXml = new XmlParser().parse(xmlReport) + def ratXml = new groovy.xml.XmlParser().parse(xmlReport) ratXml.resource.each { resource -> if (resource.'license-approval'.@name[0] == "false") { println('Unknown license: ' + resource.@name) @@ -59,11 +64,7 @@ class RatTask extends DefaultTask { @TaskAction def rat() { - File reportDir = new File(reportPath) - if (!reportDir.exists()) { - reportDir.mkdirs() - } - generateXmlReport(reportDir) + generateXmlReport() printUnknownFiles() } } @@ -75,7 +76,10 @@ class RatPlugin implements Plugin { Task ratTask = project.task("rat", type: RatTask, group: 'Build', - description: 'Runs Apache Rat checks.') + description: 'Runs Apache Rat checks.') { + baseDir = project.rootProject.projectDir + xmlReport = new File(project.rootProject.projectDir, 'build/rat-report.xml') + } project.tasks[JavaBasePlugin.CHECK_TASK_NAME].dependsOn ratTask } @@ -87,7 +91,7 @@ class RatPlugin implements Plugin { mavenCentral() } project.dependencies { - rat 'org.apache.rat:apache-rat-tasks:0.8' + rat 'org.apache.rat:apache-rat-tasks:0.16.1' } } }