Java tutorial
/* ========================================================================== * * 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); } } }