I'll try to have a look at those today or tomorrow.

2013/12/2 Bengt Rodehav <[email protected]>

> I've replaced FELIX-4332 with FELIX-4338 and FELIX-4339.
>
> I have attached a patch for FELIX-4338 and hope that someone can have a
> look at it and possibly commit it.
>
> FELIX-4339 is trickier but I would appreciate a discussion about how this
> should be handled.
>
> /Bengt
>
>
> 2013/11/29 Bengt Rodehav <[email protected]>
>
> > I've tested more with the proposed change in order to stop FileInstall to
> > incorrectly change the contents of the configuration file (problem b)
> from
> > my previous post). It seems to work fine. I would really like that to be
> > fixed. Would you like me to create a patch atttached to the JIRA?
> >
> > Problem a) is probably not trivial to fix. I've experimented a lot and
> > it's very hard for me to foresee how many escape characters I need in
> > different circumstances. One real life example for me is how I configure
> an
> > integration service that uses a Camel route underneath. If I put the
> > followiing contents in a test.cfg file:
> >
> > *mydir=C:/temp*
> >
> >
> *timestampedfile=$\\\\{file:onlyname\\\\}-$\\\\{date:now:yyyyMMddHHmmssSSS\\\\}.$\\\\{file:ext\\\\}*
> > *move=${mydir}/archive/$\\{date:now:yyyyMMdd\\}/${timestampedfile}*
> > *moveFailed=${mydir}/failed/${timestampedfile}*
> > *fromUri=file:${mydir}?move=${move}&moveFailed=${moveFailed}*
> >
> > And execute the following command:
> >
> >
> > *config:list "(service.pid=test)"*
> >
> > I get the following output:
> >
> > *----------------------------------------------------------------*
> > *Pid:            test*
> > *BundleLocation: null*
> > *Properties:*
> > *   moveFailed =
> >
> C:/temp/failed/${file:onlyname}-${date:now:yyyyMMddHHmmssSSS}.${file:ext}*
> > *   mydir = C:/temp*
> > *   timestampedfile =
> > $\{file:onlyname\}-$\{date:now:yyyyMMddHHmmssSSS\}.$\{file:ext\}*
> > *   service.pid = test*
> > *   fromUri =
> > file:C:/temp?move=C:/temp/archive//-.&moveFailed=C:/temp/failed/-.*
> > *   move =
> >
> C:/temp/archive/${date:now:yyyyMMdd}/${file:onlyname}-${date:now:yyyyMMddHHmmssSSS}.${file:ext}*
> > *   felix.fileinstall.filename =
> > file:/C:/dev/karaf/connect/common/etc/test.cfg*
> >
> > Thus, the variables "move" and "moveFailed" looks the way I want but the
> > final variable "fromUri" is messed up because of an extra variable
> > substitution.
> >
> > I haven't managed to come up with any number of backslashes that will
> > produce the correct result for me.
> >
> > The only workaround I have right now is to not use variables at all. It
> > does, however, make the configuration files extremely verbose and it's
> easy
> > to introduce errors that way.
> >
> > Presently, variable substitution is very unpredictable since it's being
> > done in a recursive way. I would prefer doing it in an iterative manner
> to
> > make it predictable. E g "${a}" should always evaluate to the same value
> no
> > matter where in the configuration file it is referenced.
> >
> > /Bengt
> >
> >
> >
> >
> >
> >
> >
> >
> > 2013/11/28 Bengt Rodehav <[email protected]>
> >
> >> I've investigated this a bit more. There are actually two different
> >> problems:
> >>
> >> a) The number of escape characters I need depends on from where I
> >> reference the variable. For every indirection I need to double the
> number
> >> of backslashes. This also means that all uses of a variable containing
> >> escape characters must be used from the same level of indirection. A bit
> >> complicated but it's due to the fact that all variables are evaluated
> >> dynamically. This means that unescaping can occur several times.
> >>
> >> b) FileInstall incorrectly thinks that a configuration property is
> >> changed and therefore overwrites the property with the evaluated value.
> >>
> >> I think I've found the reason (and possibly a solution) to b).
> >>
> >> In the ConfigInstaller.setConfig() method the properties are read from a
> >> configuration file and propagated as a configuration. Here is an excerpt
> >> from that method:
> >>
> >> *                final Properties p = new Properties();*
> >> *                in.mark(1);*
> >> *                boolean isXml = in.read() == '<';*
> >> *                in.reset();*
> >> *                if (isXml) {*
> >> *                    p.loadFromXML(in);*
> >> *                } else {*
> >> *                    p.load(in);*
> >> *                }*
> >> *                InterpolationHelper.performSubstitution((Map) p,
> >> context);*
> >> *                ht.putAll(p);*
> >>
> >> Note that the file is read using Java's standard Properties class. The
> >> unescaping is also done by that class. Then, at the end, the variable
> >> substitution is done as a separate call.
> >>
> >> Then look at the ConfigInstaller.configurationEvent() method:
> >>
> >> *        if (configurationEvent.getType() ==
> >> ConfigurationEvent.CM_UPDATED)*
> >> *        {*
> >> *            try*
> >> *            {*
> >> *                Configuration config =
> >> getConfigurationAdmin().getConfiguration(*
> >> *
>  configurationEvent.getPid(),*
> >> *
> >> configurationEvent.getFactoryPid());*
> >> *                Dictionary dict = config.getProperties();*
> >> *                String fileName = (String) dict.get(
> >> DirectoryWatcher.FILENAME );*
> >> *                File file = fileName != null ? fromConfigKey(fileName)
> :
> >> null;*
> >> *                if( file != null && file.isFile()   ) {*
> >> *                    if( fileName.endsWith( ".cfg" ) )*
> >> *                    {*
> >> *                        org.apache.felix.utils.properties.Properties
> >> props = new org.apache.felix.utils.properties.Properties( file, context
> );*
> >>
> >> Note that now the configuration file is read using
> >> org.apache.felix.utils.properties.Properties class. It turns out that
> they
> >> don't produce identical results. I haven't investigated exactly how they
> >> differ but they do.
> >>
> >> A simple test:
> >>
> >> 1. Create a configuration file with the following content:
> >>
> >> a=$\\\\{var}
> >> ab=${a}b
> >> abc=${ab}c
> >>
> >> 2. Add the following line at the end:
> >>
> >> d=foo
> >>
> >> 3. FileInstall will now incorrectly change the contents of the
> >> configuration file to:
> >>
> >>  a=$\\\\{var}
> >> ab=${a}b
> >> abc = ${var}bc
> >> d=foo
> >>
> >> Now if I change the ConfigInstaller.setConfig() method to the following:
> >>
> >> *org.apache.felix.utils.properties.Properties p = new
> >> org.apache.felix.utils.properties.Properties( f, context );*
> >> *InterpolationHelper.performSubstitution((Map) p, context);*
> >>
> >> Then FileInstall will not incorrectly change the contents of the
> >> configuration file.
> >>
> >> I propose to do this change in order to solve problem b) above. I
> >> appreciate if you have any thoughts on this.
> >>
> >> I realize that problem a) is trickier due to the dynamic nature of
> >> variable substitution. I haven't yet determined how I think the escape
> >> characters should be handled but the current situation is not ideal.
> >>
> >> /Bengt
> >>
> >>
> >>
> >>
> >> 2013/11/28 Bengt Rodehav <[email protected]>
> >>
> >>> JIRA created:
> >>>
> >>> https://issues.apache.org/jira/browse/FELIX-4332
> >>>
> >>> /Bengt
> >>>
> >>>
> >>> 2013/11/28 Bengt Rodehav <[email protected]>
> >>>
> >>>> I've come up with easily reproducable errors using Karaf 2.3.3:
> >>>>
> >>>> - Install a fresh Karaf 2.3.3
> >>>> - Add the following line to etc/custom.properties:
> >>>>   felix.fileinstall.enableConfigSave = true
> >>>>
> >>>> Create a file etc/test.cfg with the following contents:
> >>>>
> >>>> a=$\\{var}
> >>>> ab=${a}b
> >>>> abc=${ab}c
> >>>>
> >>>> I expect this to be evaluated to:
> >>>> a=$\{var}
> >>>> ab=$\{var}b
> >>>> abc=$\{var}bc
> >>>>
> >>>> But if I execute the Karaf command:
> >>>>
> >>>>   config:list "(service.pid=test)"
> >>>>
> >>>> I get:
> >>>>
> >>>> ----------------------------------------------------------------
> >>>> Pid:            test
> >>>> BundleLocation: null
> >>>> Properties:
> >>>>    service.pid = test
> >>>>    a = ${var}
> >>>>    abc = bc
> >>>>    felix.fileinstall.filename =
> >>>> file:/C:/dev/Karaf/apache-karaf-2.3.3/etc/test.cfg
> >>>>    ab = b
> >>>>
> >>>> My interpretation of this is that the variable "a" has been correctly
> >>>> evaluated. But, when evalutating the variable "ab" it seems that the
> >>>> variable "a" is evaluated again despite the fact that it has already
> been
> >>>> evaluated. FileInstall now looks for the value of a variable called
> "var"
> >>>> which evalutes to an empty string because there is no such variable.
> >>>>
> >>>> The variable "abc" consequently evaluates to "bc" since the variable
> >>>> "ab" has been evaluated to "b".
> >>>>
> >>>> To make it even worse, now change the first row in test.cfg to:
> >>>>
> >>>> a=$\\\\{var}
> >>>>
> >>>> We now get:
> >>>>
> >>>> ----------------------------------------------------------------
> >>>> Pid:            test
> >>>> BundleLocation: null
> >>>> Properties:
> >>>>    service.pid = test
> >>>>    a = $\{var}
> >>>>    abc = ${var}bc
> >>>>    felix.fileinstall.filename =
> >>>> file:/C:/dev/Karaf/apache-karaf-2.3.3/etc/test.cfg
> >>>>    ab = ${var}b
> >>>>
> >>>> Thus we get the same phenomenom. The variable "a" is evaluated
> >>>> differently if it is evaluated on its own or as part of another
> expression.
> >>>> But, due to having configured FileInstall to write back changes, the
> >>>> contents of the test.cfg is now changed by FileInstall despite the
> fact
> >>>> that the configuration has not changed at all. The contents of
> test.cfg is
> >>>> now:
> >>>>
> >>>> a=$\\\\{var}
> >>>> ab=${a}b
> >>>> abc = ${var}bc
> >>>>
> >>>> The "abc" variable has been altered. FileInstall has incorrectly
> >>>> determined that its value has changed.
> >>>>
> >>>> This is clearly a bug. I will create a JIRA.
> >>>>
> >>>> /Bengt
> >>>>
> >>>>
> >>>>
> >>>> 2013/11/26 Bengt Rodehav <[email protected]>
> >>>>
> >>>>> I'm using Apache Karaf 2.3.3 which comes with FileInstall 3.2.6. I
> >>>>> have set the felix.fileinstall.enableConfigSave property to true in
> order
> >>>>> to have FileInstall write back configuration changes to the file.
> Normally
> >>>>> all configuration changes are done by editing the configuration file
> but
> >>>>> there is one property that I change programmatically using
> ConfigAdmin (an
> >>>>> "enable" property to start/stop my service). I am dependent on that
> >>>>> property being persisted in the configuration file which is why I
> set the
> >>>>> enableConfigSave property to true.
> >>>>>
> >>>>> When configuring FileInstall to write back configuration changes to
> >>>>> the configuration file, it is important that variables are not
> substituted
> >>>>> for the evaluated value. This normally works since FileInstall
> evalutates
> >>>>> the property in the configuration file and compares it with the
> >>>>> configuration admin's value. If they are the same, the value in the
> >>>>> configuration file is kept unchanged.
> >>>>>
> >>>>> However, when using the escape character this is broken. In my case
> >>>>> I'm using Apache Camel underneath. When configuring routes via the
> config
> >>>>> admin, I sometimes need to set a value to
> >>>>> "${expression-to-be-evaluated-by-camel}". I therefore escape the "{"
> and
> >>>>> "}" to stop FileInstall from trying to evaluate the expression. Like
> this:
> >>>>>
> >>>>> $\\{expression-to-be-evaluated-by-camel\\}
> >>>>>
> >>>>> This also normally works but not when I have an indirection. E g when
> >>>>> specifying the following:
> >>>>>
> >>>>> a=$\\{var}
> >>>>> ab=${a}b
> >>>>>
> >>>>> FileInstall will change the configuration file to:
> >>>>>
> >>>>> a=$\\{var}
> >>>>> ab = ${var}b
> >>>>>
> >>>>> Note that the variable "ab" has now been expanded and written back to
> >>>>> the configuration file even if neither of the variables "a" and "ab"
> have
> >>>>> been changed.
> >>>>>
> >>>>> I think this is because FileInstall does the following:
> >>>>>
> >>>>> 1. Calculates the value of "a" to "$\{var}
> >>>>> 2. Calculates the value of "b" to "${var}b
> >>>>>
> >>>>> Note that every evaluation will perform "unescaping". This means that
> >>>>> an extra "unescaping" will be done for every indirection which fools
> >>>>> FileInstall into thinking that the property has been changed.
> >>>>>
> >>>>> I'm not exactly sure how this should be fixed in FileInstall. One
> idea
> >>>>> is to never "unescape" already evaluated variables. Actually I think
> this
> >>>>> is probably what would fix this...
> >>>>>
> >>>>> Does anybody have any ideas about this? Should I create a JIRA?
> >>>>>
> >>>>> /Bengt
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>
> >>>
> >>
> >
>



-- 
-----------------------
Guillaume Nodet
------------------------
Red Hat, Open Source Integration

Email: [email protected]
Web: http://fusesource.com
Blog: http://gnodet.blogspot.com/

Reply via email to