FWIW I'm liking the fact that lookups become case insensitive; as its what folks expect in HTTP/Mail type scenarios. Using a custom Map also makes it possible for a component/endpoint to disable this feature if it wishes (or use a different Map implementation if it can think of a good reason to do so).
2009/8/10 Claus Ibsen <claus.ib...@gmail.com>: > 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 > -- James ------- http://macstrac.blogspot.com/ Open Source Integration http://fusesource.com/