Conversation
FELIX-6812 replaced getConfiguration(pid, "?") with a listConfigurations call, and it builds the filter by concatenating the pid. A pid is not a filter-safe value, and the class already escapes one in findExistingConfiguration. A pid holding an asterisk builds a substring filter. listConfigurations then returns configurations the event was not about, and ConfigInstaller writes the first of them back to that other configuration's file. A pid holding a parenthesis throws InvalidSyntaxException instead, which the catch reports as a failure to save, so the configuration is never written back. escapeFilterValue left the backslash alone, although the OSGi filter grammar reserves it. A pid holding a backslash therefore stayed ambiguous after the escaping. The backslash is escaped first, or the escapes added after it would be escaped a second time. The method now matches literals rather than patterns. It compiled four patterns per call, and FELIX-6812 moved it from findExistingConfiguration, called once per file install, to doConfigurationEvent, called for every configuration event. Two tests raise CM_UPDATED for a pid holding an asterisk and for a pid holding a backslash, and each one fails when its escape is removed.
FELIX-6812 moved the CM_UPDATED path from getConfiguration to listConfigurations, and two tests kept the expectations of the older call. Neither test calls EasyMock.verify, so an expectation nothing consumes fails nothing. testUseExistingConfigAndObserveCMDeleted expects listConfigurations for any argument and answers null. The handler then returns before it reads anything, so the test asserts nothing at all while it passes. It now expects the filter the handler builds and answers with a configuration. testUseExistingConfigWithFileinstallFilenameAndObserveCMDeleted still expects getConfiguration and update. The CM_UPDATED path writes the file and calls no method on the configuration, and getConfiguration is reachable from setConfig only, which this test never calls. Both tests verify their mocks now, which is what makes an expectation load-bearing. The dead expectations go, and the Capture that fed update goes with them. Adding the verify call before removing the expectations fails on Configuration.update, which is the measurement behind this commit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A follow-up on FELIX-6812, and it is described in this comment.
fileinstall-3.7.5is not released yet, so the fix can still travel with the change it repairs. Tell me if you would rather see a new issue, and I will retitle this pull request.What happens
FELIX-6812 replaced
getConfiguration(pid, "?")with alistConfigurationscall, and it builds the filter by concatenating the pid. A pid is not a filter-safe value.findExistingConfigurationescapes its own filter value throughescapeFilterValue, nine lines below in the same class, and the new call site does not.Two failures follow, and neither one is visible to the user.
listConfigurationsthen returns configurations the event was not about, andConfigInstallerwrites the first of them back to that other configuration's file.InvalidSyntaxException. The catch reports it as "Unable to save configuration", so the configuration is never written back to its file.What changed
The pid is escaped through
escapeFilterValue, which is the method the other call site already uses.escapeFilterValueleft the backslash alone, although the OSGi filter grammar reserves that character. The escaping added for the pid is incomplete without the backslash case, so this pull request covers both. The backslash is escaped first, or the escapes added after it would be escaped a second time.The backslash defect predates FELIX-6812, and it affects
findExistingConfigurationas well. Say the word and I will move that half to an issue of its own.The method now matches literals rather than patterns.
String.replaceAllcompiles a pattern on each call, andescapeFilterValuecompiled four of them. FELIX-6812 moved this method fromfindExistingConfiguration, called once per file install, todoConfigurationEvent, called for every configuration event.The empty result of
listConfigurationsnow logs at debug level.listConfigurationsreturns only the configurations the caller may see, andgetConfiguration(pid, "?")did not filter that way. A configuration bound to another bundle's location therefore stops being written back to its file once a SecurityManager runs. See Configuration Admin 104.13.3. Neither early return left a trace before.The two tests FELIX-6812 left green and empty
FELIX-6812 moved the
CM_UPDATEDpath tolistConfigurations, and two tests kept the expectations of the older call. Neither test callsEasyMock.verify, so an expectation nothing consumes fails nothing.testUseExistingConfigAndObserveCMDeletedexpectslistConfigurationsfor any argument and answersnull. The handler returns before it reads anything, so the test asserts nothing at all while it passes green.testUseExistingConfigWithFileinstallFilenameAndObserveCMDeletedstill expectsgetConfigurationandupdate. TheCM_UPDATEDpath writes the file and calls no method on the configuration, andgetConfigurationis reachable fromsetConfigonly, which this test never calls.Both tests verify their mocks now, and the dead expectations go. Adding the verify call before removing the expectations fails on
Configuration.update, which is the measurement behind the commit.This half is test hygiene rather than a defect in the shipped code, and it is the fallout of the same change. Tell me if you would rather see it in an issue of its own, and I will move the commit.
Tests
testTheConfigurationEventFilterEscapesAnAsteriskInThePidandtestTheConfigurationEventFilterEscapesABackslashInThePidraiseCM_UPDATEDfor such a pid and assert the filter the handler builds. Each test fails when its escape is removed.mvn teston thefileinstallmodule passes on JDK 11, exceptDirectoryWatcherTest.testInvalidTempDir. That test also fails on an unmodifiedmasteron this machine, which is FELIX-6837.