biz.taoconsulting.dominodav.methods.LOCK.java Source code

Java tutorial

Introduction

Here is the source code for biz.taoconsulting.dominodav.methods.LOCK.java

Source

/* ========================================================================== *
 * Copyright (C) 2006, 2007 TAO Consulting Pte <http://www.taoconsulting.sg/> *
 *           based on work of                                                 *
 *           C) 2004-2005 Pier Fumagalli <http://www.betaversion.org/~pier/>  *
 *                            All rights reserved.                            *
 * ========================================================================== *
 *                                                                            *
 * Licensed 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 biz.taoconsulting.dominodav.methods;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import biz.taoconsulting.dominodav.DAVProperties;
import biz.taoconsulting.dominodav.LockInfo;
import biz.taoconsulting.dominodav.LockManager;
import biz.taoconsulting.dominodav.exceptions.DAVNotFoundException;
import biz.taoconsulting.dominodav.interfaces.IDAVRepository;
import biz.taoconsulting.dominodav.interfaces.IDAVResource;

import com.ibm.xsp.webdav.DavXMLResponsefactory;
import com.ibm.xsp.webdav.interfaces.IDAVXMLResponse;

/**
 * @author Bastian Buch (TAO Consulting)
 * 
 */
public class LOCK extends AbstractDAVMethod {

    /**
     * The logger object for event logging
     */
    private static final Log LOGGER = LogFactory.getLog(LOCK.class);

    /**
     * (non-Javadoc)
     * 
     * @see biz.taoconsulting.dominodav.methods.AbstractDAVMethod#action()
     */
    protected void action() {
        // uri is the unique identifier on the host includes servlet and
        // repository but not server
        LockInfo li = null;
        int status = HttpServletResponse.SC_OK; // We presume success
        String curURI = (String) this.getHeaderValues().get("uri");
        LockManager lm = this.getLockManager();
        HttpServletRequest req = this.getReq();
        HttpServletResponse res = this.getResp();
        String lockrequestorName = this.getOwnerFromXMLLockRequest(req);

        IDAVResource resource = null;
        Long TimeOutValue = this.getTimeOutValue(req);
        String relockToken = this.getRelockToken(req);

        // Get the resource to lock
        // Populates the resource and set status
        resource = this.getResourceToLock(curURI);
        try {
            curURI = java.net.URLDecoder.decode(curURI, "UTF-8");
        } catch (Exception e) {
        }
        // One can't lock a readonly resource
        if (resource == null || resource.isReadOnly()) {
            status = HttpServletResponse.SC_FORBIDDEN; // Client can't lock this
        } else if (relockToken != null) {
            li = lm.relock(resource, relockToken, TimeOutValue);
            if (li == null) {
                String eString = "Relock failed for " + relockToken + " for " + lockrequestorName;
                LOGGER.debug(eString);
                this.setErrorMessage(eString, 412); // Precondition failed
                status = 412;
            } else {
                LOGGER.debug("successful relock for " + relockToken + ", new Token:" + li.getToken());
                status = HttpServletResponse.SC_OK;
            }
        } else {
            li = lm.lock(resource, lockrequestorName, TimeOutValue);
            if (li == null) {
                String eString = "Lock failed for " + lockrequestorName + " and " + curURI;
                LOGGER.debug(eString); // Locked by someone else
                this.setErrorMessage(eString, 423); // Locked by someone else
                status = 423;
            } else {
                LOGGER.debug("Lock successful:" + curURI + " for " + lockrequestorName);
                status = HttpServletResponse.SC_OK;
            }
        }

        // Status of the request
        this.setHTTPStatus(status);

        if (status < 400) { // 400 and 500 determine failure!
            res.addHeader("Lock-Token", "<" + li.getToken() + ">");
            // Render the XML response
            this.writeLockResponseXML(res, li);
        }
    }

    /**
     * Extracts the XML Document than contains the lock request
     * 
     * @param req
     */

    /**
     * Extracts the XML Document than contains the lock request
     * 
     * @param req
     */
    private String getOwnerFromXMLLockRequest(HttpServletRequest req) {
        // We don't treat XML as XML here, but we just need a string
        // Not terrible good code
        String result = null;
        /*
         * Looks like this <?xml version="1.0" encoding="UTF-8" ?> <lockinfo
         * xmlns="DAV:"> <locktype> <write/> </locktype> <lockscope>
         * <exclusive/> </lockscope> <owner>Administrator</owner> </lockinfo>
         */

        boolean found = false;
        String curLine = null;
        BufferedReader in = null;
        // byte[] data = new byte[req.getContentLength()];
        // int len = 0, totalLen = 0;

        try {
            // LOGGER.info("1.1");
            // in = req.getReader();
            InputStream ins = req.getInputStream();
            // InputStream in= new
            // FileInputStream("d:/forChml/PunchOutSetupRequest.xml");
            StringBuffer xmlStr = new StringBuffer();
            int d;
            while ((d = ins.read()) != -1) {
                xmlStr.append((char) d);
            }
            // LOGGER.info("1.2");
            // do {
            // curLine = in.readLine();
            curLine = xmlStr.toString();
            // LOGGER.info("1.3="+curLine);
            if (curLine != null && curLine.contains("<owner>")) {
                found = true;

            } else {
                // LOGGER.info("1.4");
                if (curLine != null && curLine.contains("<D:owner>")) {
                    found = true;
                }
            }
            // } while (!found && curLine != null);

            if (found) {
                // curLine=curLine.substring(startIndex);
                int start = curLine.indexOf(">");
                int stop = curLine.lastIndexOf("<");
                result = curLine.substring(start + 1, stop);
                // LOGGER.info("1.5="+result);
                start = result.indexOf(">");
                stop = result.lastIndexOf("<");

                if (start > 0) {
                    result = result.substring(start + 1, stop);
                    start = result.indexOf("href>");
                    stop = result.lastIndexOf("<");

                    if (start > 0) {
                        if (stop > 0) {
                            result = result.substring(start + 5, stop);
                        } else {
                            result = result.substring(start + 5);
                        }
                    }

                    // LOGGER.info("1.6="+result);
                }
            }

        } catch (Exception e) {
            LOGGER.error(e);
            result = null;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }

        return result;

    }

    /**
     * Gets the relock header if we have one and extracts the opaque token for
     * the lock activity
     * 
     * @param req
     * @return the relock token or null if it isn't in a suitable format
     */
    private String getRelockToken(HttpServletRequest req) {
        /*
         * The token looks like this: If:
         * (<opaquelocktoken:fecc6ff70de5a701f6a52bb53fec9083>)
         */
        String result = null;
        String relockToken = req.getHeader("If");

        if (relockToken != null) {

            int start = relockToken.indexOf("<");
            int end = relockToken.lastIndexOf(">");

            if (start > 0 && end > start + 1) {
                result = relockToken.substring(start + 1, end);
            }
        }
        return result;
    }

    /**
     * Get the resource to lock - migh be a new resource
     * 
     * @param resource
     *            the empty resource
     * @param curURI
     *            the URL
     * @return new resource if it worked
     */
    private IDAVResource getResourceToLock(String curURI) {
        IDAVRepository rep = this.getRepository();
        IDAVResource resource = null;
        try {
            curURI = java.net.URLDecoder.decode(curURI, "UTF-8");
        } catch (Exception e) {
        }
        try {
            resource = rep.getResource(curURI, true);
        } catch (DAVNotFoundException exc) {
            // This could be a preliminary lock before a write
            resource = rep.createNewResource(curURI);
        }

        return resource;
    }

    /**
     * Get the Lock duration in seconds, fall back to default if not found in
     * header or the value is not in the expected format
     * 
     * @param req
     * @return
     */
    private Long getTimeOutValue(HttpServletRequest req) {

        String TimeOutHeader = req.getHeader("Timeout");
        Long TimeOutValue = LockManager.MAX_LOCK_DURATION_SEC;

        if (TimeOutHeader != null) {
            int whereDoSecondsStart = TimeOutHeader.indexOf('-') + 1;
            if (whereDoSecondsStart > 0) {
                try {
                    String sub = TimeOutHeader.substring(whereDoSecondsStart);
                    TimeOutValue = new Long(sub).longValue();
                    if (TimeOutValue > LockManager.MAX_LOCK_DURATION_SEC) {
                        TimeOutValue = LockManager.MAX_LOCK_DURATION_SEC;
                    }
                } catch (Exception e) {
                    // The header could not get converted
                    TimeOutValue = LockManager.MAX_LOCK_DURATION_SEC;
                }
            }
        }
        return TimeOutValue;

    }

    /**
     * (non-Javadoc)
     * 
     * @see biz.taoconsulting.dominodav.methods.AbstractDAVMethod#writeInitialHeader()
     */
    protected void writeInitialHeader() {
        // No header to add

    }

    /**
     * Writes out the XML response to a lock request
     * 
     * @param res
     * @param li
     */
    private void writeLockResponseXML(HttpServletResponse resp, LockInfo li) {
        IDAVXMLResponse xr = DavXMLResponsefactory.getXMLResponse(null, false);

        /*
         * Response looks like this: <D:prop xmlns:D="DAV:"> <D:lockdiscovery>
         * <D:activelock> <D:locktype> <D:write/> </D:locktype> <D:lockscope>
         * <D:exclusive/> </D:lockscope> <D:depth>0</D:depth>
         * <D:owner>Administrator</D:owner> <D:timeout>Second-179</D:timeout>
         * <D:locktoken>
         * <D:href>opaquelocktoken:45b028e368da5f3e1d9652b2a8f1e1dc</D:href>
         * </D:locktoken> </D:activelock> </D:lockdiscovery></D:prop>
         */

        xr.openTag("prop");
        xr.auxTag("username", li.getUsername());
        xr.openTag("lockdiscovery");
        xr.openTag("activelock");

        xr.openTag("locktype");
        xr.emptyTag("write");
        xr.closeTag(1);

        xr.openTag("lockscope");
        xr.emptyTag("exclusive");
        xr.closeTag(1);

        xr.simpleTag("depth", "0");
        xr.simpleTag("owner", li.getLocalUsername());
        xr.simpleTag("timeout", "Second-" + li.getTimeout());
        xr.openTag("locktoken");
        xr.simpleTag("href", li.getToken());

        xr.closeDocument(); // Close all pending tags and the document

        resp.setContentType(DAVProperties.TYPE_XML);
        // resp.setHeader("content-encoding", "utf-8");
        // resp.setContentLength(xr.getXMLBytes().length);

        try {
            String result = xr.toString();
            resp.setContentLength(result.length());
            PrintWriter out = resp.getWriter();
            out.write(result);
            out.close();
            // ServletOutputStream out = this.getOutputStream();
            // out.write(xr.getXMLBytes());
            // out.close();
        } catch (IOException e) {
            LOGGER.error(e);
        }

    }
}