Hi Had a chat James as well.
Went for the solution without a KeyValuePair object as it causes pain with dynamic languages and template engines. And the camel-jms component had some obscure errors with it also. Its very easy to revert to old behavior as its just to change to use a java.util.HashMap in DefaultMessage. On Sat, Aug 8, 2009 at 9:53 PM, Hadrian Zbarcea<hzbar...@gmail.com> wrote: > Hi Claus, > > I added a comment on the Jira as well. > > Why not use a Map<lowercase-header, Pair<header, Object>> ? I believe this > to be a simple solution. Lookups should always be on the lowercase version > of the header, on the wire the original version should go. > > What do you think? > Hadrian > > On Aug 8, 2009, at 9:42 AM, Claus Ibsen wrote: > >> Hi >> >> I have just attached a much better implementation of the map, this >> time all code is in a single class and it does not use holder objects >> such as a KeyValuePair when storing the value. >> >> It also works out of the box with scripting engines that can access >> and manipulate the headers such as Freemarker and Velocity. >> >> The changes needed in DefaultMessage is basically to use this map >> instead of a regular HashMap. >> And when its copied to another map the original keys is automatic >> retained. >> >> >> >> On Sat, Aug 8, 2009 at 12:42 PM, Claus Ibsen<claus.ib...@gmail.com> wrote: >>> >>> Hi >>> >>> For background see ticket CAMEL-1886 >>> https://issues.apache.org/activemq/browse/CAMEL-1886 >>> >>> The issue is that headers is stored using keys that are case >>> sensitive, and that leads to a few problems and differences in Camel: >>> >>> - lookup is cumbersome as you must match case 100% >>> - errors in camel components that is unable to realize a header >>> already exists however with a different (case) >>> - some protocols are agnostic to header cases, such as HTTP (and all >>> its different transports using HTTP), Mail, and whatnot? >>> - camel-mail stores notoriously headers in lower keys only >>> - etc. >>> >>> And most importantly >>> - no one wants to send different values using a key that have >>> different case, such as: >>> Foo=cheese >>> FOO=cake >>> foo=beer >>> >>> So James and I had a chat about it and to see if would could do >>> something about it. >>> >>> The real reason that I picked up this issue is the tuning experiment >>> with Camel 2.x >>> http://camel.apache.org/camel-2x-speed-optimizations.html >>> >>> Where we want to take a few short cuts and offer header lookup on the >>> source directly to avoid the "tiny" overhead of extracting headers >>> from the source >>> and populate the camel message. This is useful if you do message >>> routing that only uses headers. The camel-jms component did already >>> offer this but >>> it also had some inconsistency in this relation. >>> >>> >>> I have attempted a resolution in the tuning branch but discovered an >>> issue, that it does take some more grunt work to keep the lower case >>> index in sync etc. >>> So I wanted to try a different approach >>> >>> CaseInsenstiveMap >>> =============== >>> >>> I have implemented a small case insenstive map so we can store headers >>> in 1 map instead of keeping 2 maps in sync. >>> I am still amazed why such a Map does not exists directly in the JDK >>> itself. >>> >>> What does this offer then >>> - lookup is easy as you can lookup using any case >>> and in the future we could also offer lookup for special keys people >>> spell differently such as: ContentType, content-type, content-type, >>> content_type and whatnot. >>> - put will also ensure that it replaces existing values >>> - and most importantly that it offers this as well when end users work >>> directly on the map using: >>> exchange.getIn().getHeaders().put("foo", "beer") >>> That will be able to replace existing keys if they are stored using: >>> Foo, FOO or what not >>> This is not possible today and or with a 2nd map that tracks lower >>> case indexes >>> >>> So how to retain the original keys. >>> >>> Well I implemented that as well, so when you e.g. copy the map to >>> another or extract from it using keySet it exposes a Set that uses the >>> original key cases. >>> So if you have stored using >>> exchange.getIn().setHeader("Foo", "cheese") >>> >>> Then the key in the ketSet is the original key = Foo. >>> But you can do lookup using: foo, FOO, FoO, FOo, and whatnot :) >>> >>> Using this implementation I actually find a few bugs in existing unit >>> tests and camel components that double add headers using different >>> cases. >>> For example camel-cxf in the new RS support. >>> >>> >>> I will later attach the code to the CAMEL-1886 ticket for people of >>> the community to take a look and review. >>> >>> >>> Here is a snippet from one of the test methods to give an idea >>> >>> public void testLookupCaseAgnosticAddHeaderRemoveHeader() { >>> Map<String, Object> map = new CaseInsensitiveMap(); >>> assertNull(map.get("foo")); >>> >>> map.put("foo", "cheese"); >>> >>> assertEquals("cheese", map.get("foo")); >>> assertEquals("cheese", map.get("Foo")); >>> assertEquals("cheese", map.get("FOO")); >>> assertNull(map.get("unknown")); >>> >>> map.put("bar", "beer"); >>> >>> assertEquals("beer", map.get("bar")); >>> assertEquals("beer", map.get("Bar")); >>> assertEquals("beer", map.get("BAR")); >>> assertNull(map.get("unknown")); >>> >>> map.remove("bar"); >>> assertNull(map.get("bar")); >>> assertNull(map.get("unknown")); >>> } >>> >>> >>> And when using the Message API >>> >>> public void testRemoveWithDifferentCase() { >>> Message msg = new DefaultMessage(); >>> assertNull(msg.getHeader("foo")); >>> >>> msg.setHeader("foo", "cheese"); >>> msg.setHeader("Foo", "bar"); >>> >>> assertEquals("bar", msg.getHeader("FOO")); >>> assertEquals("bar", msg.getHeader("foo")); >>> assertEquals("bar", msg.getHeader("Foo")); >>> >>> msg.removeHeader("FOO"); >>> >>> assertEquals(null, msg.getHeader("foo")); >>> assertEquals(null, msg.getHeader("Foo")); >>> assertEquals(null, msg.getHeader("FOO")); >>> >>> assertTrue(msg.getHeaders().isEmpty()); >>> } >>> >>> >>> >>> >>> >>> -- >>> Claus Ibsen >>> Apache Camel Committer >>> >>> Open Source Integration: http://fusesource.com >>> Blog: http://davsclaus.blogspot.com/ >>> Twitter: http://twitter.com/davsclaus >>> >> >> >> >> -- >> Claus Ibsen >> Apache Camel Committer >> >> Open Source Integration: http://fusesource.com >> Blog: http://davsclaus.blogspot.com/ >> Twitter: http://twitter.com/davsclaus > > -- Claus Ibsen Apache Camel Committer Open Source Integration: http://fusesource.com Blog: http://davsclaus.blogspot.com/ Twitter: http://twitter.com/davsclaus