/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.tuscany.sca.binding.atom.provider;

import static org.apache.tuscany.sca.binding.atom.provider.AtomBindingUtil.entry;
import static org.apache.tuscany.sca.binding.atom.provider.AtomBindingUtil.feedEntry;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.abdera.Abdera;
import org.apache.abdera.factory.Factory;
import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.model.Category;
import org.apache.abdera.model.Collection;
import org.apache.abdera.model.Document;
import org.apache.abdera.model.Feed;
import org.apache.abdera.model.Link;
import org.apache.abdera.model.Service;
import org.apache.abdera.model.Workspace;
import org.apache.abdera.parser.ParseException;
import org.apache.abdera.parser.Parser;
import org.apache.abdera.writer.WriterFactory;
import org.apache.commons.codec.binary.Base64;
import org.apache.tuscany.sca.binding.http.HTTPCacheContext;
import org.apache.tuscany.sca.data.collection.Entry;
import org.apache.tuscany.sca.databinding.Mediator;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.apache.tuscany.sca.invocation.InvocationChain;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.invocation.MessageFactory;
import org.apache.tuscany.sca.runtime.RuntimeWire;

/**
 * A resource collection binding listener, implemented as a Servlet and
 * registered in a Servlet host provided by the SCA hosting runtime.
 *
 * @version $Rev$ $Date$
 */
class AtomBindingListenerServlet extends HttpServlet {
    private static final Logger logger = Logger.getLogger(AtomBindingListenerServlet.class.getName());
    private static final long serialVersionUID = 1L;

    private static final Factory abderaFactory = Abdera.getNewFactory();
    private static final Parser abderaParser = Abdera.getNewParser();
    private static final String ETAG = "ETag";
    private static final String LASTMODIFIED = "Last-Modified";    
    private static final String LOCATION = "Location";    
    private static final String CONTENTLOCATION = "Content-Location";    
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat( "EEE, dd MMM yyyy HH:mm:ss Z" ); // RFC 822 date time

    private RuntimeWire wire;
    private Invoker getFeedInvoker;
    private Invoker getAllInvoker;
    private Invoker queryInvoker;
    private Invoker getInvoker;
    private Invoker postInvoker;
    private Invoker postMediaInvoker;
    private Invoker putInvoker;
    private Invoker putMediaInvoker;
    private Invoker deleteInvoker;
    private MessageFactory messageFactory;
    private String title;
    private String description;
    private Mediator mediator;
    private DataType<?> itemClassType;
    private DataType<?> itemXMLType;
    private boolean supportsFeedEntries;

    /**
     * Constructs a new binding listener.
     * 
     * @param wire
     * @param messageFactory
     * @param feedType
     */
    AtomBindingListenerServlet(RuntimeWire wire, MessageFactory messageFactory, Mediator mediator, String title, String description) {
        this.wire = wire;
        this.messageFactory = messageFactory;
        this.mediator = mediator;
        this.title = title;
        this.description = description;

        // Get the invokers for the supported operations
        Operation getOperation = null;
        for (InvocationChain invocationChain : this.wire.getInvocationChains()) {
            invocationChain.setAllowsPassByReference(true);
            Operation operation = invocationChain.getTargetOperation();
            String operationName = operation.getName();
            if (operationName.equals("getFeed")) {
                getFeedInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("getAll")) {
                getAllInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("query")) {
                queryInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("get")) {
                getInvoker = invocationChain.getHeadInvoker();
                getOperation = operation;
            } else if (operationName.equals("put")) {
                putInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("putMedia")) {
                putMediaInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("post")) {
                postInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("postMedia")) {
                postMediaInvoker = invocationChain.getHeadInvoker();
            } else if (operationName.equals("delete")) {
                deleteInvoker = invocationChain.getHeadInvoker();
            }
        }

        // Determine the collection item type
        if (getOperation != null) {
            itemXMLType = new DataTypeImpl<Class<?>>(String.class.getName(), String.class, String.class);
            Class<?> itemClass = getOperation.getOutputType().getPhysical();
            if (itemClass == org.apache.abdera.model.Entry.class) {
                supportsFeedEntries = true;
            }
            //We assume that the item type is the same for both input and 
            //ouput for all operations on the interface
            itemClassType = getOperation.getOutputType();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // No authentication required for a get request

        // Test for any cache info in the request
        HTTPCacheContext cacheContext = null;    	
        try { 
            cacheContext = HTTPCacheContext.getCacheContextFromRequest( request );
        } catch ( java.text.ParseException e ) {    
        }
        // System.out.println( "AtomBindingListener.doGet cache context=" + cacheContext );

        // Get the request path
        //int servletPathLength = request.getContextPath().length() + request.getServletPath().length();
        //String path = URLDecoder.decode(request.getRequestURI().substring(servletPathLength), "UTF-8");

        String path = URLDecoder.decode(getRequestPath(request), "UTF-8");
        
        logger.fine("get " + request.getRequestURI());

        // Handle an Atom request
        if (path != null && path.equals("/atomsvc")) {
            /*
             <?xml version='1.0' encoding='UTF-8'?>
             <service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
                <workspace>
                   <atom:title type="text">resource</atom:title>
                   <collection href="http://luck.ibm.com:8084/customer">
                      <atom:title type="text">entries</atom:title>
                      <accept>application/atom+xml;type=entry</accept>
                      <categories />
                   </collection>
                </workspace>
             </service>
             */

            // Return the Atom service document
            response.setContentType("application/atomsvc+xml; charset=utf-8");

            String href = request.getRequestURL().toString();
            href = href.substring(0, href.length() - "/atomsvc".length());

            String workspaceURL = new String( href );
            int pathIndex = workspaceURL.indexOf( request.getServletPath() );
            if ( -1 != pathIndex ) {
                workspaceURL = workspaceURL.substring( 0, pathIndex ) + "/";
            }

            Service service = abderaFactory.newService();
            //service.setText("service");

            Workspace workspace = abderaFactory.newWorkspace();
            if ( title != null ) {
                workspace.setTitle(title);
            } else {
                workspace.setTitle("workspace");
            }
            workspace.setBaseUri( new IRI( workspaceURL ));

            Collection collection = workspace.addCollection("collection", href );
            Feed feed = getFeed( request );
            if ( feed != null ) {
                String title = feed.getTitle();
                if ( title != null ) {
                    collection.setTitle(title);
                } else {
                    collection.setTitle("entries");
                }
                collection.addAccepts("application/atom+xml;type=feed");
                collection.addAccepts("application/json;type=feed");
                collection.addAccepts("application/atom+xml;type=entry");
                collection.addAccepts("application/json;type=entry");
                List<Category> categories = feed.getCategories();
                if ( categories != null ) {
                    collection.addCategories(categories, false, null); 
                } else {
                    collection.addCategories().setFixed(false);
                }

            } else {
                collection.setTitle("entries");
                // collection.addAccepts("application/atom+xml;type=feed");
                collection.addAccepts("application/atom+xml; type=entry");
                collection.addAccepts("application/json;type=entry");
                collection.addCategories().setFixed(false);            
            }
            workspace.addCollection(collection);
            service.addWorkspace(workspace);

            //FIXME add prettyPrint support
            try {
                service.getDocument().writeTo(response.getOutputStream());
            } catch (IOException ioe) {
                throw new ServletException(ioe);
            }

        } else if (path == null || path.length() == 0 || path.equals("/")) {

            // Return a feed containing the entries in the collection
            Feed feed = getFeed( request );
            if (feed != null) {
                String feedETag = null;
                if (feed.getId() != null)
                    feedETag = "\"" + feed.getId().toString() + "\"";
                Date feedUpdated = feed.getUpdated();
                // Test request for predicates.
                String predicate = request.getHeader( "If-Match" );
                if (( predicate != null ) && ( !predicate.equals(feedETag) )) {
                    // No match, should short circuit
                    response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
                    return;
                }
                predicate = request.getHeader( "If-None-Match" );
                if (( predicate != null ) && ( predicate.equals(feedETag) )) {
                    // Match, should short circuit
                    response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                    return;
                }
                if ( feedUpdated != null ) {
                    predicate = request.getHeader( "If-Unmodified-Since" );                
                    if ( predicate != null ) {
                        try {
                            Date predicateDate = dateFormat.parse( predicate ); 
                            if ( predicateDate.compareTo( exactSeconds(feedUpdated) ) < 0 ) {
                                // Match, should short circuit
                                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                                return;
                            }             		
                        } catch ( java.text.ParseException e ) {
                            // Ignore and move on
                        }
                    }
                    predicate = request.getHeader( "If-Modified-Since" );                
                    if ( predicate != null ) {
                        try {
                            Date predicateDate = dateFormat.parse( predicate ); 
                            if ( predicateDate.compareTo( exactSeconds(feedUpdated) ) >= 0 ) {
                                // Match, should short circuit
                                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                                return;
                            }             		
                        } catch ( java.text.ParseException e ) {
                            // Ignore and move on
                        }
                    }
                }
                // Provide Etag based on Id and time if given.
                // Ignore if not given. (Browser may cache if trivial ETag is given.)
                if ( feedETag != null ) {
                    response.addHeader(ETAG, feedETag);
                }
                if ( feedUpdated != null ) {
                    response.addHeader(LASTMODIFIED, dateFormat.format( feedUpdated ));
                }

                // Content negotiation
                String acceptType = request.getHeader( "Accept" );
                String preferredType = getContentPreference( acceptType ); 
                if (( preferredType != null ) && ((preferredType.indexOf( "json") > -1) || (preferredType.indexOf( "JSON") > -1 ))) {
                    // JSON response body
                    response.setContentType("application/json;type=feed");

                    try {
                        Abdera abdera = new Abdera();
                        WriterFactory wf = abdera.getWriterFactory();
                        org.apache.abdera.writer.Writer json = wf.getWriter("json");
                        feed.writeTo(json, response.getWriter());
                    } catch (Exception e) {
                        throw new ServletException(e);
                    }           		

                } else {
                    // Write the Atom feed
                    response.setContentType("application/atom+xml;type=feed");
                    try {
                        feed.getDocument().writeTo(response.getOutputStream());
                    } catch (IOException ioe) {
                        throw new ServletException(ioe);
                    }
                }
            } else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
            }

        } else if (path.startsWith("/")) {
            // Return a specific entry in the collection
            org.apache.abdera.model.Entry feedEntry;

            // Invoke the get operation on the service implementation
            Message requestMessage = messageFactory.createMessage();
            String id = path.substring(1);
            requestMessage.setBody(new Object[] {id});
            Message responseMessage = getInvoker.invoke(requestMessage);
            if (responseMessage.isFault()) {
                Object body = responseMessage.getBody();
                if (body.getClass().getName().endsWith(".NotFoundException")) {
                    response.sendError(HttpServletResponse.SC_NOT_FOUND);
                    return;
                } else {
                    throw new ServletException((Throwable)responseMessage.getBody());
                }

            }
            if (supportsFeedEntries) {
                // The service implementation returns a feed entry 
                feedEntry = responseMessage.getBody();
            } else {
                // The service implementation only returns a data item, create an entry
                // from it
                Entry<Object, Object> entry = new Entry<Object, Object>(id, responseMessage.getBody()); 
                feedEntry = feedEntry(entry, itemClassType, itemXMLType, mediator, abderaFactory);
            }
            // Write the Atom entry
            if (feedEntry != null) {
                String entryETag = null;
                if (feedEntry.getId() != null)
                    entryETag = feedEntry.getId().toString();
                Date entryUpdated = feedEntry.getUpdated();
                if ( entryUpdated != null )
                    response.addHeader(LASTMODIFIED, dateFormat.format( entryUpdated ));
                // TODO Check If-Modified-Since If-Unmodified-Since predicates against LASTMODIFIED. 
                // If true return 304 and null body.

                Link link = feedEntry.getSelfLink();
                if (link != null) {
                    response.addHeader(LOCATION, link.getHref().toString());
                } else {
                    link = feedEntry.getLink( "Edit" );
                    if (link != null) {
                        response.addHeader(LOCATION, link.getHref().toString());
                    }
                }

                // Test request for predicates.
                String predicate = request.getHeader( "If-Match" );
                if (( predicate != null ) && ( !predicate.equals(entryETag) )) {
                    // No match, should short circuit
                    response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED);
                    return;
                }
                predicate = request.getHeader( "If-None-Match" );
                if (( predicate != null ) && ( predicate.equals(entryETag) )) {
                    // Match, should short circuit
                    response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                    return;
                }
                if ( entryUpdated != null ) {
                    predicate = request.getHeader( "If-Unmodified-Since" );                
                    if ( predicate != null ) {
                        try {
                            Date predicateDate = dateFormat.parse( predicate ); 
                            if ( predicateDate.compareTo( entryUpdated ) < 0 ) {
                                // Match, should short circuit
                                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                                return;
                            }             		
                        } catch ( java.text.ParseException e ) {
                            // Ignore and move on
                        }
                    }
                    predicate = request.getHeader( "If-Modified-Since" );                
                    if ( predicate != null ) {
                        try {
                            Date predicateDate = dateFormat.parse( predicate ); 
                            if ( predicateDate.compareTo( entryUpdated ) > 0 ) {
                                // Match, should short circuit
                                response.sendError(HttpServletResponse.SC_NOT_MODIFIED);
                                return;
                            }             		
                        } catch ( java.text.ParseException e ) {
                            // Ignore and move on
                        }
                    }
                }
                // Provide Etag based on Id and time if given.
                // Ignore if not given. (Browser may cache if trivial ETag is given.)
                if (entryETag != null) {
                    response.addHeader(ETAG, entryETag );
                }
                if ( entryUpdated != null ) {
                    response.addHeader(LASTMODIFIED, dateFormat.format( entryUpdated ));
                }

                // Content negotiation
                String acceptType = request.getHeader( "Accept" );
                String preferredType = getContentPreference( acceptType ); 
                if (( preferredType != null ) && ((preferredType.indexOf( "json") > -1) || (preferredType.indexOf( "JSON") > -1 ))) {
                    // JSON response body
                    response.setContentType("application/json;type=entry");
                    try {
                        Abdera abdera = new Abdera();
                        WriterFactory wf = abdera.getWriterFactory();
                        org.apache.abdera.writer.Writer json = wf.getWriter("json");
                        feedEntry.writeTo(json, response.getWriter());
                    } catch (Exception e) {
                        throw new ServletException(e);
                    }           		
                } else {
                    // XML response body 
                    response.setContentType("application/atom+xml;type=entry");
                    try {
                        feedEntry.writeTo(getWriter(response));
                    } catch (IOException ioe) {
                        throw new ServletException(ioe);
                    }
                }
            } else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
            }
        } else {
            // Path doesn't match any known pattern
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }

    }

    protected Feed getFeed( HttpServletRequest request ) throws ServletException {
        if (supportsFeedEntries) {
            // The service implementation supports feed entries, invoke its getFeed operation
            Message requestMessage = messageFactory.createMessage();
            Message responseMessage;
            if (request.getQueryString() != null) {
                requestMessage.setBody(new Object[] {request.getQueryString()});
                responseMessage = queryInvoker.invoke(requestMessage);
            } else {
                responseMessage = getFeedInvoker.invoke(requestMessage);
            }
            if (responseMessage.isFault()) {
                throw new ServletException((Throwable)responseMessage.getBody());
            }
            return (Feed)responseMessage.getBody();		    
        } else {

            // The service implementation does not support feed entries,
            // invoke its getAll operation to get the data item collection, then create
            // feed entries from the items
            Message requestMessage = messageFactory.createMessage();
            Message responseMessage;
            if (request.getQueryString() != null) {
                requestMessage.setBody(new Object[] {request.getQueryString()});
                responseMessage = queryInvoker.invoke(requestMessage);
            } else {
                responseMessage = getAllInvoker.invoke(requestMessage);
            }
            if (responseMessage.isFault()) {
                throw new ServletException((Throwable)responseMessage.getBody());
            }
            Entry<Object, Object>[] collection = (Entry<Object, Object>[])responseMessage.getBody();
            if (collection != null) {

                // Create the feed
                Feed feed = abderaFactory.newFeed();

                // Set the feed title
                if (title != null) {
                    feed.setTitle(title);
                } else {
                    feed.setTitle("Feed");
                }
                if (description != null) {
                    feed.setSubtitle(description);
                }
                // All feeds must provide Id and updated elements.
                // However, some do not, so provide some program protection.
                feed.setId( "Feed" + feed.hashCode());
                Date responseLastModified = new Date( 0 );

                // Add entries to the feed
                for (Entry<Object, Object> entry: collection) {
                    org.apache.abdera.model.Entry feedEntry = feedEntry(entry, itemClassType, itemXMLType, mediator, abderaFactory);
                    // Use the most recent entry update as the feed update
                    Date entryUpdated = feedEntry.getUpdated();
                    if (( entryUpdated != null ) && (entryUpdated.compareTo( responseLastModified  ) > 0 )) {
                        responseLastModified = entryUpdated;
                    }
                    feed.addEntry(feedEntry);
                }
                // If no entries were newly updated,
                if ( responseLastModified.compareTo( new Date( 0 ) ) == 0 ) {
                    responseLastModified = new Date();
                }
                return feed;
            }
        }
        return null;
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
    IOException {
        // Authenticate the user
        String user = processAuthorizationHeader(request);
        if (user == null) {
            unauthorized(response);
            return;
        }

        // Get the request path
        String path = URLDecoder.decode(getRequestPath(request), "UTF-8");

        if (path == null || path.length() == 0 || path.equals("/")) {
            org.apache.abdera.model.Entry createdFeedEntry = null;

            // Create a new Atom entry
            String contentType = request.getContentType();
            if (contentType != null && contentType.startsWith("application/atom+xml")) {

                // Read the entry from the request
                org.apache.abdera.model.Entry feedEntry;
                try {
                    Document<org.apache.abdera.model.Entry> doc = abderaParser.parse(request.getReader());
                    feedEntry = doc.getRoot();
                } catch (ParseException pe) {
                    throw new ServletException(pe);
                }

                // Let the component implementation create it
                if (supportsFeedEntries) {

                    // The service implementation supports feed entries, pass the entry to it
                    Message requestMessage = messageFactory.createMessage();
                    requestMessage.setBody(new Object[] {feedEntry});
                    Message responseMessage = postInvoker.invoke(requestMessage);
                    if (responseMessage.isFault()) {
                        throw new ServletException((Throwable)responseMessage.getBody());
                    }
                    createdFeedEntry = responseMessage.getBody();
                } else {

                    // The service implementation does not support feed entries, pass the data item to it
                    Message requestMessage = messageFactory.createMessage();
                    Entry<Object, Object> entry = entry(feedEntry, itemClassType, itemXMLType, mediator);
                    requestMessage.setBody(new Object[] {entry.getKey(), entry.getData()});
                    Message responseMessage = postInvoker.invoke(requestMessage);
                    if (responseMessage.isFault()) {
                        throw new ServletException((Throwable)responseMessage.getBody());
                    }
                    entry.setKey(responseMessage.getBody());
                    createdFeedEntry = feedEntry(entry, itemClassType, itemXMLType, mediator, abderaFactory);
                }

            } else if (contentType != null) {
                // Create a new media entry

                // Get incoming headers
                String title = request.getHeader("Title");
                String slug = request.getHeader("Slug");

                // Let the component implementation create the media entry
                Message requestMessage = messageFactory.createMessage();
                requestMessage.setBody(new Object[] {title, slug, contentType, request.getInputStream()});
                Message responseMessage = postMediaInvoker.invoke(requestMessage);
                if (responseMessage.isFault()) {
                    throw new ServletException((Throwable)responseMessage.getBody());
                }
                createdFeedEntry = responseMessage.getBody();

                // Transfer media info to response header.
                // Summary is a comma separated list of header properties.
                String summary = createdFeedEntry.getSummary();
                addPropertiesToHeader( response, summary );

            } else {
                response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
            }

            // A new entry for non-media was created successfully.
            if (createdFeedEntry != null) {
                // Set location of the created entry in the Location header
                IRI feedId = createdFeedEntry.getId();
                if ( feedId != null ) {
                    response.addHeader(ETAG, "\"" + feedId.toString() + "\"" );
                }
                Date entryUpdated = createdFeedEntry.getUpdated();
                if ( entryUpdated != null ) {
                    response.addHeader(LASTMODIFIED, dateFormat.format( entryUpdated ));
                }
                Link link = createdFeedEntry.getSelfLink();
                if (link != null) {
                    response.addHeader(LOCATION, link.getHref().toString());
                } 
                Link editLink = createdFeedEntry.getEditLink();
                if (editLink != null) {
                    response.addHeader(LOCATION, editLink.getHref().toString());
                }
                Link editMediaLink = createdFeedEntry.getEditMediaLink();
                if (editMediaLink != null) {
                    response.addHeader(CONTENTLOCATION, editMediaLink.getHref().toString());
                }

                // Write the created Atom entry
                response.setStatus(HttpServletResponse.SC_CREATED);
                response.setContentType("application/atom+xml;type=entry");
                try {
                    createdFeedEntry.writeTo(getWriter(response));
                } catch (ParseException pe) {
                    throw new ServletException(pe);
                }

            } else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
            }

        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    private Writer getWriter(HttpServletResponse response) throws UnsupportedEncodingException, IOException {
        Writer writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
        return writer;
    }

    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // Authenticate the user
        String user = processAuthorizationHeader(request);
        if (user == null) {
            unauthorized(response);
            return;
        }

        // Get the request path
        String path = URLDecoder.decode(getRequestPath(request), "UTF-8");

        if (path != null && path.startsWith("/")) {
            String id = path.substring(1);

            // Update an Atom entry
            String contentType = request.getContentType();
            if (contentType != null && contentType.startsWith("application/atom+xml")) {

                // Read the entry from the request
                org.apache.abdera.model.Entry feedEntry;
                try {
                    Document<org.apache.abdera.model.Entry> doc = abderaParser.parse(request.getReader());
                    feedEntry = doc.getRoot();
                } catch (ParseException pe) {
                    throw new ServletException(pe);
                }

                // Let the component implementation create it
                if (supportsFeedEntries) {
                    // The service implementation supports feed entries, pass the entry to it
                    Message requestMessage = messageFactory.createMessage();
                    requestMessage.setBody(new Object[] {id, feedEntry});
                    Message responseMessage = putInvoker.invoke(requestMessage);
                    if (responseMessage.isFault()) {
                        Object body = responseMessage.getBody();
                        if (body.getClass().getName().endsWith(".NotFoundException")) {
                            response.sendError(HttpServletResponse.SC_NOT_FOUND);
                        } else {
                            throw new ServletException((Throwable)responseMessage.getBody());
                        }
                    }
                } else {
                    // The service implementation does not support feed entries, pass the data item to it
                    Message requestMessage = messageFactory.createMessage();
                    Entry<Object, Object> entry = entry(feedEntry, itemClassType, itemXMLType, mediator);
                    requestMessage.setBody(new Object[] {entry.getKey(), entry.getData()});
                    Message responseMessage = putInvoker.invoke(requestMessage);
                    if (responseMessage.isFault()) {
                        Object body = responseMessage.getBody();
                        if (body.getClass().getName().endsWith(".NotFoundException")) {
                            response.sendError(HttpServletResponse.SC_NOT_FOUND);
                        } else {
                            throw new ServletException((Throwable)responseMessage.getBody());
                        }
                    }
                }

            } else if (contentType != null) {

                // Update a media entry

                // Let the component implementation create the media entry
                Message requestMessage = messageFactory.createMessage();
                requestMessage.setBody(new Object[] {id, contentType, request.getInputStream()});
                Message responseMessage = putMediaInvoker.invoke(requestMessage);

                Object body = responseMessage.getBody();
                if (responseMessage.isFault()) {
                    if (body.getClass().getName().endsWith(".NotFoundException")) {
                        response.sendError(HttpServletResponse.SC_NOT_FOUND);
                    } else {
                        throw new ServletException((Throwable)responseMessage.getBody());
                    }
                }

                // Transfer content to response header.

            } else {
                response.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
        }
    }

    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException,  IOException {

        // Authenticate the user
        String user = processAuthorizationHeader(request);
        if (user == null) {
            unauthorized(response);
            return;
        }

        // Get the request path
        String path = URLDecoder.decode(getRequestPath(request), "UTF-8");

        String id;
        if (path != null && path.startsWith("/")) {
            id = path.substring(1);
        } else {
            id = "";
        }

        // Delete a specific entry from the collection
        Message requestMessage = messageFactory.createMessage();
        requestMessage.setBody(new Object[] {id});
        Message responseMessage = deleteInvoker.invoke(requestMessage);
        if (responseMessage.isFault()) {
            Object body = responseMessage.getBody();
            if (body.getClass().getName().endsWith(".NotFoundException")) {
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
            } else {
                throw new ServletException((Throwable)responseMessage.getBody());
            }
        }
    }

    
    /**
     * 
     * @param request
     * @return
     */
    private static String getRequestPath(HttpServletRequest request) {
        // Get the request path
        String contextPath = request.getContextPath();
        String servletPath = request.getServletPath();
        String requestURI = request.getRequestURI();
        
        int contextPathLength = request.getContextPath().length();
        int servletPathLenght = servletPath.contains(contextPath) ? servletPath.length() - contextPath.length() : servletPath.length();
        
        String requestPath = requestURI.substring(contextPathLength + servletPathLenght);
        
        return requestPath;
    }
    
    /**
     * Process the authorization header
     * 
     * @param request
     * @return
     * @throws ServletException
     */
    private String processAuthorizationHeader(HttpServletRequest request) throws ServletException {

        // FIXME temporarily disabling this as it doesn't work with all browsers 
        if (true)
            return "admin";

        try {
            String authorization = request.getHeader("Authorization");
            if (authorization != null) {
                StringTokenizer tokens = new StringTokenizer(authorization);
                if (tokens.hasMoreTokens()) {
                    String basic = tokens.nextToken();
                    if (basic.equalsIgnoreCase("Basic")) {
                        String credentials = tokens.nextToken();
                        String userAndPassword = new String(Base64.decodeBase64(credentials.getBytes()));
                        int colon = userAndPassword.indexOf(":");
                        if (colon != -1) {
                            String user = userAndPassword.substring(0, colon);
                            String password = userAndPassword.substring(colon + 1);

                            // Authenticate the User.
                            if (authenticate(user, password)) {
                                return user;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new ServletException(e);
        }
        return null;
    }

    /**
     * Authenticate a user.
     * 
     * @param user
     * @param password
     * @return
     */
    private boolean authenticate(String user, String password) {
        // TODO Handle this using SCA security policies
        return ("admin".equals(user) && "admin".equals(password));
    }

    /**
     * Reject an unauthorized request.
     * 
     * @param response
     */
    private void unauthorized(HttpServletResponse response) throws IOException {
        response.setHeader("WWW-Authenticate", "BASIC realm=\"Tuscany\"");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    /**
     * Get content-type preference using application/atom-xml as default
     * @param acceptType content-type preference using application/atom-xml as default
     * @return
     */
    private static String getContentPreference( String acceptType ) {
        if (( acceptType == null ) || ( acceptType.length() < 1 )) {
            return "application/atom+xml";    		
        }
        StringTokenizer st = new StringTokenizer( acceptType, "," );
        if ( st.hasMoreTokens() ) {
            return st.nextToken(); 
        }
        return "application/atom+xml";
    }

    /** Take a list of key values and add them to the header.
     * For instance "Content-Type=image/gif,Content-Length=14201"
     * @param response
     * @param properties
     */
    private static void addPropertiesToHeader( HttpServletResponse response, String properties  ) {
        if ( properties == null ) return; 
        StringTokenizer props = new StringTokenizer( properties, ",");
        while( props.hasMoreTokens()) {
            String prop = props.nextToken();
            StringTokenizer keyVal = new StringTokenizer( prop, "=");
            String key = null;
            String val = null;
            if ( keyVal.hasMoreTokens() )
                key = keyVal.nextToken();
            if ( keyVal.hasMoreTokens() )
                val = keyVal.nextToken();
            if (( key != null ) && ( val != null )) {
                response.addHeader(key, val);                			
            }
        }
    }

    /**
     * Round a date down to an exact number of seconds
     * @param date with millisecond precision
     * @return date rounded down to nearest second
     */
    private Date exactSeconds(Date date) {
        return new Date(date.getTime() / 1000 * 1000);
    }

}
