Issue Details (XML | Word | Printable)

Key: SIPSERVLET_SPEC-24
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Major Major
Assignee: jonbo372
Reporter: jonbo372
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
sipservlet-spec

Improve header support by introducing a Header interface.

Created: 02/Nov/12 07:03 PM   Updated: 15/Jan/14 06:21 AM   Resolved: 15/Jan/14 06:21 AM
Component/s: None
Affects Version/s: None
Fix Version/s: None

Time Tracking:
Not Specified

Tags:
Participants: binod and jonbo372


 Description  « Hide

In 289, if you want to extract out all the headers out of a sip message you will end up writing a double for-loop to get all the headers and their values out. Also, you have to come up with your own structure for storing that information in a meaningful way. Consider the following example that extracts out all X-headers out of a message and returns them in a list:

Example of extracting out X-headers in 289
private List<Header> extractXHeaders(final SipServletMessage msg) {
        final Iterator<String> it = msg.getHeaderNames();
        if (it == null) {
            return Collections.emptyList();
        }

        final List<Header> xHeaders = new ArrayList<Header>();

        while (it.hasNext()) {
            final String header = it.next();
            if (header.toLowerCase().startsWith("x-")) {
                final ListIterator<String> valueIt = msg.getHeaders(header);
                while (valueIt.hasNext()) {
                    final String value = valueIt.next();
                    xHeaders.add(new Header(header, value));
                }
            }
        }

        return xHeaders;
    }

Not shown in the above snippet is the Header class that holds the name and the value of the header.

Suggested solution:

Introduce a Header interface that all headers will inherit from (in the current specification that would be Parameterable only) and expose new convenience methods in SipServletMessage for extracting out all headers.

Note: full interface declaration at the end

Summary of new interfaces
Interface Header {
   String getName();
   String getValue();
}

SipServletMessage {
   ...
   Iterator<Header> getHeaders();
   ...
}

With the new interface additions the same code for extracting out the x-headers:

Example of extracting out X-headers in 359 (with proposed changes)
private List<Header> extractHeaders2(final SipServletMessage msg) {
        final Iterator<Header> headers = msg.getHeaders();
        final List<Header> xHeaders = new ArrayList<Header>();

        while (headers.hasNext()) {
            final Header header = headers.next();
            if (header.getName().toLowerCase().equals("x-")) {
                xHeaders.add(header);
            }
        }

        return xHeaders;
    }

This will also allow people to create their own Header library which would have a cleaner integration with the container because of the re-usable Header-interface.

Suggested Interface

Suggested additions to the SipServletMessage
public static interface SipServletMessage {

        /**
         * Obtain a list of all the headers in the {@link SipServletMessage}.
         * The order of the headers in the list follows that of the
         * {@link SipServletMessage}.
         * 
         * Note, modifying the iterator will not change the headers in the
         * {@link SipServletMessage}.
         * 
         * @return an iterator of all the headers in the message or an empty
         *         iterator if there are none.
         */
        Iterator<Header> getHeaders();

        /**
         * Returns the header with specified name. If the message did not
         * include a header of the specified name, this method returns null. If
         * multiple headers exist, the first one is returned. The header name is
         * case insensitive.
         * 
         * TODO: better name
         */
        Header getHeader2(String name);

        /**
         * Get all the headers with the specified name. If there are no headers
         * with that name an empty iterator will be returned. The name is case
         * insensitive.
         * 
         * @param name
         *            the name of the header to extract out of this
         *            {@link SipServletMessage}
         * @return an iterator of headers or an empty iterator if no headers
         *         with that name exists.
         */
        Iterator<Header> getHeaders2(String name);

        /**
         * Add a header to this message.
         * 
         * @param header
         *            the header to add to this message.
         * 
         * @throws IllegalArgumentException
         *             if the specified header field is a system header or if it
         *             cannot legally appear in this message
         */
        void addHeader(Header header) throws IllegalArgumentException;

        /**
         * Sets a header. If the header already has been set, the new header
         * will overwrite the previous one. If there are multiple headers with
         * the * same name, they all are replaced by this header name
         * 
         * @param header
         * @throws IllegalArgumentException
         * @throws NullPointerException
         */
        void setHeader(Header header) throws IllegalArgumentException, NullPointerException;
    }


binod added a comment - 29/Aug/13 11:52 AM

Can we avoid "2" that is appearing in the method names? Since getHeader and getHeaders methods are already taken, one way to avoid the "2" might be by using "HeaderEntry" as the interface name instead of "Header".

Another question is, since SIP Servlet 1.1 has already defined Parameterable interface, how would Parameterable (and Address) values be handled? One way might be to define new interface as HeaderEntry<String, V> and then have the methods return HeaderEntry<String, String> or HeaderEntry<String, Parameterable>, when app invokes getHeaderEntry and getParameterableHeaderEntry respectively.

Opinion? comments?


jonbo372 added a comment - 25/Sep/13 05:16 PM

Agreed. As the javadoc says for the getHeader2, a better name is certainly needed. I don't really like getHeaderEntry (if I understood you correctly) because I don't like to change the name of the Header since it is a Header and not a HeaderEntry.

Parameterable and Address would simply inherit from the Header interface. Compare to JSR32. Hence, just cast it if you know it is of a certain type.


binod added a comment - 15/Jan/14 06:21 AM

Given the way headers are specified as header values in the 1.1 API, it does not make much sense to introduce a headerfield that will disrupt the design in a non-intuitive way. So, EG decided not to pursue this API further. Please see the email thread below for details.

https://java.net/projects/sipservlet-spec/lists/users/archive/2013-10/message/29