0001: /*
0002: * Copyright 2001-2006 C:1 Financial Services GmbH
0003: *
0004: * This software is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License Version 2.1, as published by the Free Software Foundation.
0007: *
0008: * This software is distributed in the hope that it will be useful,
0009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0011: * Lesser General Public License for more details.
0012: *
0013: * You should have received a copy of the GNU Lesser General Public
0014: * License along with this library; if not, write to the Free Software
0015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
0016: */
0017:
0018: package de.finix.contelligent.webdav;
0019:
0020: import java.io.BufferedReader;
0021: import java.io.IOException;
0022: import java.io.InputStreamReader;
0023: import java.text.SimpleDateFormat;
0024: import java.util.ArrayList;
0025: import java.util.Date;
0026: import java.util.Enumeration;
0027: import java.util.HashMap;
0028: import java.util.Iterator;
0029: import java.util.Locale;
0030: import java.util.Map;
0031:
0032: import javax.servlet.ServletContext;
0033: import javax.servlet.ServletException;
0034: import javax.servlet.ServletInputStream;
0035: import javax.servlet.ServletOutputStream;
0036: import javax.servlet.http.Cookie;
0037: import javax.servlet.http.HttpServletRequest;
0038: import javax.servlet.http.HttpServletResponse;
0039: import javax.servlet.http.HttpSession;
0040:
0041: import de.finix.contelligent.CallData;
0042: import de.finix.contelligent.Component;
0043: import de.finix.contelligent.ComponentContext;
0044: import de.finix.contelligent.ComponentManager;
0045: import de.finix.contelligent.ComponentNotFoundException;
0046: import de.finix.contelligent.ComponentPath;
0047: import de.finix.contelligent.Container;
0048: import de.finix.contelligent.Contelligent;
0049: import de.finix.contelligent.Session;
0050: import de.finix.contelligent.SessionCreationException;
0051: import de.finix.contelligent.category.CategoryException;
0052: import de.finix.contelligent.components.CBinary;
0053: import de.finix.contelligent.components.CFragment;
0054: import de.finix.contelligent.components.CNumber;
0055: import de.finix.contelligent.components.CString;
0056: import de.finix.contelligent.components.CText;
0057: import de.finix.contelligent.components.Folder;
0058: import de.finix.contelligent.content.ContelligentBinaryContent;
0059: import de.finix.contelligent.content.ContelligentStringContent;
0060: import de.finix.contelligent.content.ContelligentTextContent;
0061: import de.finix.contelligent.content.Content;
0062: import de.finix.contelligent.content.ContentProvider;
0063: import de.finix.contelligent.core.ContelligentImpl;
0064: import de.finix.contelligent.core.ContelligentSession;
0065: import de.finix.contelligent.core.HTTPCallDataImpl;
0066: import de.finix.contelligent.core.TimeService;
0067: import de.finix.contelligent.core.security.ComponentPermission;
0068: import de.finix.contelligent.core.security.ContelligentSecurityManager;
0069: import de.finix.contelligent.core.security.User;
0070: import de.finix.contelligent.exception.ContelligentException;
0071: import de.finix.contelligent.exception.ContelligentExceptionID;
0072: import de.finix.contelligent.exception.ContelligentRuntimeException;
0073: import de.finix.contelligent.exception.NoReadPermissionException;
0074: import de.finix.contelligent.logging.LoggingService;
0075: import de.finix.contelligent.resource.BinaryResource;
0076: import de.finix.contelligent.resource.TextResource;
0077: import de.finix.contelligent.util.ThreadedMem;
0078:
0079: public class WebdavHandler {
0080: final static org.apache.log4j.Logger log = LoggingService
0081: .getLogger(WebdavHandler.class);
0082:
0083: private static final String CONTELLIGENT_SESSION_KEY = "contelligent/session";
0084:
0085: public static final String CONTELLIGENT_USER_AGENT = "Contelligent Client";
0086:
0087: public static final String DEFAULT_TYPE = "contelligent.content.Binary";
0088:
0089: private final static String[] searchEngineBots = new String[] {
0090: "googlebot", "scooter", "slurp", "ia_archiver",
0091: "architextspider", "sidewinder", "spider" };
0092:
0093: protected ContelligentImpl contelligent;
0094:
0095: private static WebdavHandler _instance = null;
0096:
0097: private HashMap extensionMapping = null;
0098:
0099: private final static SimpleDateFormat rfc1123 = new SimpleDateFormat(
0100: "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
0101:
0102: public WebdavHandler() {
0103: extensionMapping = new HashMap();
0104: extensionMapping.put("jpeg", new String[] { "image/jpeg",
0105: "contelligent.content.Image" });
0106: extensionMapping.put("jpg", new String[] { "image/jpeg",
0107: "contelligent.content.Image" });
0108: extensionMapping.put("gif", new String[] { "image/gif",
0109: "contelligent.content.Image" });
0110: extensionMapping.put("tiff", new String[] { "image/tiff",
0111: "contelligent.content.Image" });
0112: extensionMapping.put("tif", new String[] { "image/tiff",
0113: "contelligent.content.Image" });
0114: extensionMapping.put("png", new String[] { "image/png",
0115: "contelligent.content.Image" });
0116: extensionMapping.put("bmp", new String[] { "image/bmp",
0117: "contelligent.content.Image" });
0118: extensionMapping.put("pdf", new String[] { "application/pdf",
0119: "contelligent.content.Binary" });
0120: extensionMapping.put("doc", new String[] {
0121: "application/msword", "contelligent.content.Binary" });
0122: extensionMapping.put("zip", new String[] { "application/zip",
0123: "contelligent.content.Binary" });
0124: extensionMapping.put("xls", new String[] {
0125: "application/vnd.ms-excel",
0126: "contelligent.content.Binary" });
0127: extensionMapping.put("ppt", new String[] {
0128: "application/vnd.ms-powerpoint",
0129: "contelligent.content.Binary" });
0130: extensionMapping.put("swf", new String[] {
0131: "application/x-shockwave-flash",
0132: "contelligent.content.Binary" });
0133: extensionMapping.put("mid", new String[] { "audio/midi",
0134: "contelligent.content.Binary" });
0135: extensionMapping.put("mp3", new String[] { "audio/mpeg",
0136: "contelligent.content.Binary" });
0137: extensionMapping
0138: .put("ram", new String[] { "audio/x-pn-realaudio",
0139: "contelligent.content.Binary" });
0140: extensionMapping
0141: .put("rm", new String[] { "audio/x-pn-realaudio",
0142: "contelligent.content.Binary" });
0143: extensionMapping.put("ra", new String[] { "audio/x-realaudio",
0144: "contelligent.content.Binary" });
0145: extensionMapping.put("wav", new String[] { "audio/x-wav",
0146: "contelligent.content.Binary" });
0147: extensionMapping.put("txt", new String[] { "text/plain",
0148: "contelligent.content.Text" });
0149: extensionMapping.put("rtf", new String[] { "text/rtf",
0150: "contelligent.content.Text" });
0151: extensionMapping.put("htm", new String[] { "text/html",
0152: "contelligent.content.Text" });
0153: extensionMapping.put("html", new String[] { "text/html",
0154: "contelligent.content.Text" });
0155: extensionMapping.put("mht", new String[] { "message/rfc822",
0156: "contelligent.content.Text" });
0157: extensionMapping.put("mpeg", new String[] { "video/mpeg",
0158: "contelligent.content.Binary" });
0159: extensionMapping.put("mpe", new String[] { "video/mpeg",
0160: "contelligent.content.Binary" });
0161: extensionMapping.put("mpg", new String[] { "video/mpeg",
0162: "contelligent.content.Binary" });
0163: extensionMapping.put("qt", new String[] { "video/quicktime",
0164: "contelligent.content.Binary" });
0165: extensionMapping.put("mov", new String[] { "video/quicktime",
0166: "contelligent.content.Binary" });
0167: extensionMapping.put("avi", new String[] { "video/x-msvideo",
0168: "contelligent.content.Binary" });
0169: }
0170:
0171: public static WebdavHandler getInstance() {
0172:
0173: if (_instance == null)
0174: _instance = new WebdavHandler();
0175:
0176: return _instance;
0177:
0178: }
0179:
0180: public void propfind(HttpServletRequest request,
0181: HttpServletResponse response, ServletContext context,
0182: String servletBase) throws ServletException, IOException {
0183:
0184: log.debug("PROPFIND PARAMS: "
0185: + request.getParameterNames().toString());
0186: InputStreamReader isr = new InputStreamReader(request
0187: .getInputStream());
0188: BufferedReader br = new BufferedReader(isr);
0189: String line = br.readLine();
0190:
0191: while (line != null) {
0192: log.debug("R: " + line);
0193: line = br.readLine();
0194: }
0195: ServletOutputStream sos = response.getOutputStream();
0196: sos.print(getPropfindAnswer(request, response, context,
0197: servletBase));
0198:
0199: }
0200:
0201: public void put(HttpServletRequest request,
0202: HttpServletResponse response, ServletContext context)
0203: throws ServletException, IOException {
0204:
0205: log.debug("PUT PARAMS: "
0206: + request.getParameterNames().toString());
0207:
0208: String cname = request.getPathInfo();
0209: log.debug("CNAME : " + cname);
0210:
0211: try {
0212: contelligent = ContelligentImpl.getInstance();
0213:
0214: HTTPCallDataImpl callData = null;
0215: ContelligentSession session = null;
0216: ComponentPath compPath = null;
0217:
0218: String servletPath = request.getPathInfo();
0219: int sep = servletPath.lastIndexOf('.');
0220: compPath = (sep == -1) ? new ComponentPath(servletPath)
0221: : new ComponentPath(servletPath.substring(0, sep));
0222: String compExt = (sep == -1) ? "" : servletPath
0223: .substring(sep);
0224: if (compExt.length() <= 1)
0225: compExt = ""; // nur ein Punkt am Ende
0226: else
0227: compExt = compExt.substring(1); // Punkt vorne wegschneiden.
0228:
0229: callData = setupEnvironment(request, response, context,
0230: null, null);
0231: // session = (ContelligentSession)callData.getContelligentSession();
0232:
0233: ComponentManager manager = callData.getActualManager();
0234: log
0235: .debug("service() - trying to get component '"
0236: + compPath + "' from manager '" + manager
0237: + "' ...");
0238:
0239: Component comp = null;
0240:
0241: try {
0242: comp = manager.getComponent(compPath, callData);
0243: log.debug("Component found.");
0244: } catch (ComponentNotFoundException e) {
0245: log.debug("Component not found. Creating new one.");
0246: comp = createNewComponent(compPath, compExt, callData);
0247: log.debug("Component created.");
0248: }
0249:
0250: if (comp != null)
0251: if (comp instanceof ContentProvider) {
0252: Content content = ((ContentProvider) comp)
0253: .getContent();
0254: long currentTime = TimeService.getInstance()
0255: .currentTimeMillis();
0256: ComponentContext ctx = comp.getComponentContext();
0257:
0258: if (content instanceof ContelligentTextContent) {
0259: log.debug("Component has text content");
0260:
0261: BufferedReader br = request.getReader();
0262: String line = null;
0263:
0264: line = br.readLine();
0265: StringBuffer dataBuffer = new StringBuffer();
0266: while (line != null) {
0267: dataBuffer.append(line).append("\n");
0268: line = br.readLine();
0269: }
0270: log.debug("Store data:\n"
0271: + dataBuffer.toString());
0272:
0273: TextResource resource = new TextResource(
0274: dataBuffer.toString(), currentTime);
0275:
0276: Iterator ids = ctx
0277: .getContentResourceIdentifiers()
0278: .iterator();
0279: if (ids.hasNext()) {
0280: String resId = (String) ids.next();
0281: ctx.setContentResource(resId, resource);
0282: log
0283: .debug("Pass stream to Resource using id: '"
0284: + resId + "'");
0285: } else {
0286: ctx.setContentResource("", resource);
0287: log.debug("Pass stream to new Resource.");
0288: }
0289:
0290: // ((ContelligentTextContent)content).setText(dataBuffer.toString(),
0291: // callData);
0292: manager.updateComponent(comp, callData);
0293:
0294: } else if (content instanceof ContelligentBinaryContent) {
0295: log.debug("Component has binary content");
0296: String contentType = "application/octet-stream"; // Default
0297: if (extensionMapping.containsKey(compExt
0298: .toLowerCase())) {
0299: contentType = ((String[]) extensionMapping
0300: .get(compExt.toLowerCase()))[0];
0301: }
0302: String extension = compExt;
0303: int length = request.getContentLength();
0304: ServletInputStream sis = request
0305: .getInputStream();
0306: BinaryResource resource = new BinaryResource(
0307: sis, contentType, extension,
0308: currentTime, (int) length);
0309:
0310: Iterator ids = ctx
0311: .getContentResourceIdentifiers()
0312: .iterator();
0313: if (ids.hasNext()) {
0314: String resId = (String) ids.next();
0315: ctx.setContentResource(resId, resource);
0316: log
0317: .debug("Pass stream to Resource using id: "
0318: + resId);
0319: } else {
0320: ctx.setContentResource("", resource);
0321: log.debug("Pass stream to new Resource.");
0322: }
0323: manager.updateComponent(comp, callData);
0324: }
0325: } else {
0326: log.error("Component has no content.");
0327: }
0328:
0329: } catch (Exception e) {
0330: log.error("Failed to put data.", e);
0331: }
0332: }
0333:
0334: public void mkcol(HttpServletRequest request,
0335: HttpServletResponse response, ServletContext context)
0336: throws ServletException, IOException {
0337:
0338: log.debug("MKCOL PARAMS: "
0339: + request.getParameterNames().toString());
0340:
0341: String cname = request.getPathInfo();
0342: log.debug("CNAME : " + cname);
0343:
0344: try {
0345: contelligent = ContelligentImpl.getInstance();
0346:
0347: HTTPCallDataImpl callData = null;
0348: ContelligentSession session = null;
0349: ComponentPath compPath = null;
0350:
0351: String servletPath = request.getPathInfo();
0352: int sep = servletPath.lastIndexOf('.');
0353: compPath = (sep == -1) ? new ComponentPath(servletPath)
0354: : new ComponentPath(servletPath.substring(0, sep));
0355: String compExt = (sep == -1) ? "" : servletPath
0356: .substring(sep);
0357: if (compExt.length() <= 1)
0358: compExt = ""; // nur ein Punkt am Ende
0359: else
0360: compExt = compExt.substring(1); // Punkt vorne wegschneiden.
0361:
0362: callData = setupEnvironment(request, response, context,
0363: null, null);
0364:
0365: ComponentManager manager = callData.getActualManager();
0366: log
0367: .debug("service() - trying to get component '"
0368: + compPath + "' from manager '" + manager
0369: + "' ...");
0370:
0371: try {
0372: Component comp = manager.getComponent(compPath,
0373: callData);
0374: log.debug("Collection component already exists.");
0375: } catch (ComponentNotFoundException e) {
0376: log
0377: .debug("Collection component not found. Creating new one.");
0378: ComponentManager cm = callData.getActualManager();
0379: ComponentPath parentPath = new ComponentPath(compPath
0380: .getDir());
0381: Component parent = cm
0382: .getComponent(parentPath, callData);
0383: String type = "contelligent.core.Folder";
0384: Component comp = cm.createComponent((Container) parent,
0385: compPath.getName(), type, null, null, callData);
0386: log.debug("Component created.");
0387: }
0388: } catch (Exception e) {
0389: log.error("Failed to make collection.", e);
0390: }
0391: }
0392:
0393: public void lock(HttpServletRequest request,
0394: HttpServletResponse response, ServletContext context)
0395: throws ServletException, IOException {
0396: log.debug("LOCK PARAMS: "
0397: + request.getParameterNames().toString());
0398:
0399: // Not implemented yet; just an experimental fake for Office
0400:
0401: BufferedReader br = request.getReader();
0402: String line = null;
0403: String owner = null;
0404: line = br.readLine();
0405: // StringBuffer dataBuffer = new StringBuffer();
0406: while (line != null) {
0407: // dataBuffer.append( line ).append("\n");
0408: if (line.startsWith("<owner>")) {
0409: int start = line.indexOf('>') + 1;
0410: int end = line.indexOf('<', start);
0411: owner = line.substring(start, end);
0412: }
0413: line = br.readLine();
0414: }
0415: log.debug("Lock owner:\n" + owner);
0416:
0417: String servletPath = request.getPathInfo();
0418: StringBuffer answer = new StringBuffer();
0419: answer.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
0420: answer.append("<D:prop xmlns:D=\"DAV:\">\n");
0421: answer.append("<D:lockdiscovery>");
0422: answer.append("<D:activelock>");
0423: answer.append("<D:locktype><D:write/></D:locktype>");
0424: answer.append("<D:lockscope><D:exclusive/></D:lockscope>");
0425: answer.append("<D:depth>infinity</D:depth>");
0426: // answer.append("<D:owner><D:href>http://www.contelligent.de</D:href></D:owner>");
0427: answer.append("<D:owner>");
0428: answer.append(owner);
0429: answer.append("</D:owner>");
0430: answer.append("<D:timeout>Second-604800</D:timeout>");
0431: answer
0432: .append("<D:locktoken><D:href>opaquelocktoken:e71d4fae-5dec-22d6-fea5-00a0c91e6be4</D:href></D:locktoken>");
0433: answer.append("</D:activelock>");
0434: answer.append("</D:lockdiscovery>");
0435: answer.append("</D:prop>");
0436:
0437: response.getWriter().write(answer.toString());
0438:
0439: }
0440:
0441: public void unlock(HttpServletRequest request,
0442: HttpServletResponse response, ServletContext context)
0443: throws ServletException, IOException {
0444: log.debug("UNLOCK PARAMS: "
0445: + request.getParameterNames().toString());
0446: // Not implemented yet
0447: response.setStatus(HttpServletResponse.SC_NO_CONTENT);
0448: }
0449:
0450: public void delete(HttpServletRequest request,
0451: HttpServletResponse response, ServletContext context)
0452: throws ServletException, IOException {
0453:
0454: log.debug("DELETE PARAMS: "
0455: + request.getParameterNames().toString());
0456:
0457: try {
0458: contelligent = ContelligentImpl.getInstance();
0459:
0460: HTTPCallDataImpl callData = null;
0461: ContelligentSession session = null;
0462: ComponentPath compPath = null;
0463:
0464: String servletPath = request.getPathInfo();
0465: int sep = servletPath.lastIndexOf('.');
0466: compPath = (sep == -1) ? new ComponentPath(servletPath)
0467: : new ComponentPath(servletPath.substring(0, sep));
0468:
0469: callData = setupEnvironment(request, response, context,
0470: null, null);
0471: ComponentManager manager = callData.getActualManager();
0472: log
0473: .debug("service() - trying to delete component '"
0474: + compPath + "' from manager '" + manager
0475: + "' ...");
0476:
0477: manager.deleteComponentTree(callData, compPath);
0478:
0479: } catch (ContelligentRuntimeException e) {
0480: log.error("Failed to delete: " + e.getMessage());
0481: response.sendError(response.SC_FORBIDDEN, e.getMessage());
0482: } catch (ContelligentException e) {
0483: log.error("Failed to delete: " + e.getMessage());
0484: response.sendError(response.SC_FORBIDDEN, e.getMessage());
0485: } catch (Exception e) {
0486: log.error("Failed to delete.", e);
0487: }
0488: }
0489:
0490: public void move(HttpServletRequest request,
0491: HttpServletResponse response, ServletContext context)
0492: throws ServletException, IOException {
0493:
0494: log.debug("MOVE PARAMS: "
0495: + request.getParameterNames().toString());
0496:
0497: try {
0498: contelligent = ContelligentImpl.getInstance();
0499:
0500: HTTPCallDataImpl callData = null;
0501: ContelligentSession session = null;
0502: ComponentPath compPath = null;
0503: ComponentPath newCompPath = null;
0504:
0505: String targetPath = request.getHeader("Destination");
0506: log.debug("Destination: " + targetPath);
0507:
0508: String servletPath = request.getPathInfo();
0509: int sep = servletPath.lastIndexOf('.');
0510: compPath = (sep == -1) ? new ComponentPath(servletPath)
0511: : new ComponentPath(servletPath.substring(0, sep));
0512:
0513: callData = setupEnvironment(request, response, context,
0514: null, null);
0515: log.debug("Base: " + callData.getCurrentBaseURL());
0516: String pathStart = request.getContextPath() + "/webdav/";
0517: log.debug("path must start with: " + pathStart);
0518: int pos = targetPath.indexOf(pathStart);
0519: if (pos >= 0) {
0520: targetPath = targetPath.substring(pos
0521: + pathStart.length() - 1);
0522: sep = targetPath.lastIndexOf('.');
0523: newCompPath = (sep == -1) ? new ComponentPath(
0524: targetPath) : new ComponentPath(targetPath
0525: .substring(0, sep));
0526: }
0527:
0528: ComponentManager manager = callData.getActualManager();
0529: log
0530: .debug("service() - trying to move component '"
0531: + compPath + "' from manager '" + manager
0532: + "' ...");
0533: log.debug("service() - to '" + newCompPath + "' ");
0534:
0535: manager.moveComponentTree(compPath, newCompPath, callData);
0536:
0537: } catch (ContelligentRuntimeException e) {
0538: log.error("Failed to move: " + e.getMessage());
0539: response.sendError(response.SC_FORBIDDEN, e.getMessage());
0540: } catch (ContelligentException e) {
0541: log.error("Failed to move: " + e.getMessage());
0542: response.sendError(response.SC_FORBIDDEN, e.getMessage());
0543: } catch (Exception e) {
0544: log.error("Failed to move.", e);
0545: }
0546: }
0547:
0548: public void get(HttpServletRequest request,
0549: HttpServletResponse response, ServletContext context) {
0550:
0551: log.debug("GET PARAMS: "
0552: + request.getParameterNames().toString());
0553:
0554: final boolean debugEnabled = log.isDebugEnabled();
0555:
0556: try {
0557: ServletOutputStream sos = response.getOutputStream();
0558:
0559: contelligent = ContelligentImpl.getInstance();
0560:
0561: HTTPCallDataImpl callData = null;
0562: ContelligentSession session = null;
0563: ComponentPath compPath = null;
0564:
0565: String cname = request.getPathInfo();
0566: log.debug("CNAME : " + cname);
0567:
0568: String servletPath = request.getPathInfo();
0569: int sep = servletPath.lastIndexOf('.');
0570: compPath = (sep == -1) ? new ComponentPath(servletPath)
0571: : new ComponentPath(servletPath.substring(0, sep));
0572: callData = setupEnvironment(request, response, context,
0573: null, null);
0574: // session = (ContelligentSession)callData.getContelligentSession();
0575:
0576: ComponentManager manager = callData.getActualManager();
0577: // ComponentManager manager = session.getComponentManager();
0578: if (debugEnabled) {
0579: log.debug("service() - trying to get component '"
0580: + compPath + "' from manager '" + manager
0581: + "' ...");
0582: }
0583:
0584: Component comp = manager.getComponent(compPath, callData);
0585: if (!manager.callerHasPermission(callData, comp,
0586: ComponentPermission.READ)) {
0587: response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
0588: throw new NoReadPermissionException(callData
0589: .getContelligentSession().getUser(), comp
0590: .getComponentContext().getPath());
0591: }
0592:
0593: if (comp instanceof ContentProvider) {
0594: Content content = ((ContentProvider) comp).getContent();
0595: if (content instanceof ContelligentTextContent) {
0596: sos.print(((ContelligentTextContent) content)
0597: .getText(callData));
0598: } else if (content instanceof ContelligentBinaryContent) {
0599: ((ContelligentBinaryContent) content).streamBinary(
0600: sos, callData);
0601: }
0602: } else {
0603: log.error("Component has no content.");
0604: }
0605:
0606: } catch (ComponentNotFoundException cne) {
0607: log.error("Component not found during GET.");
0608: response.setStatus(HttpServletResponse.SC_NOT_FOUND); // 404
0609: } catch (Exception e) {
0610: log.error("EXC: ", e);
0611: }
0612:
0613: }
0614:
0615: public void head(HttpServletRequest request,
0616: HttpServletResponse response, ServletContext context) {
0617: get(request, response, context);
0618: }
0619:
0620: /**
0621: * @return
0622: */
0623: private String getPropfindAnswer(HttpServletRequest request,
0624: HttpServletResponse response, ServletContext context,
0625: String servletBase) {
0626:
0627: final boolean debugEnabled = log.isDebugEnabled();
0628: String ret = "";
0629:
0630: try {
0631:
0632: contelligent = ContelligentImpl.getInstance();
0633:
0634: HTTPCallDataImpl callData = null;
0635: ContelligentSession session = null;
0636: ComponentPath compPath = null;
0637:
0638: String cname = request.getPathInfo();
0639: log.debug("CNAME : " + cname);
0640:
0641: String dString = request.getHeader("Depth");
0642: int depth = 0;
0643: if (dString != null) {
0644: if (dString.equals("1")) {
0645: depth = 1;
0646: } else if (dString.equals("infinity")) {
0647: depth = 2; // Not supported yet really.
0648: }
0649: }
0650: log.debug("Depth: " + String.valueOf(depth));
0651:
0652: String servletPath = request.getPathInfo();
0653: int sepPos = servletPath.lastIndexOf('.');
0654: int slashPos = servletPath.lastIndexOf('/');
0655: if ((sepPos != -1) && (slashPos < sepPos)) {
0656: compPath = new ComponentPath(servletPath.substring(0,
0657: sepPos));
0658: } else {
0659: compPath = new ComponentPath(servletPath);
0660: }
0661: compPath = (sepPos == -1) ? new ComponentPath(servletPath)
0662: : new ComponentPath(servletPath
0663: .substring(0, sepPos));
0664: callData = setupEnvironment(request, response, context,
0665: null, null);
0666: // session = (ContelligentSession)callData.getContelligentSession();
0667:
0668: ComponentManager manager = callData.getActualManager();
0669: // ComponentManager manager = session.getComponentManager();
0670: if (debugEnabled) {
0671: log.debug("service() - trying to get component '"
0672: + compPath + "' from manager '" + manager
0673: + "' ...");
0674: }
0675:
0676: Component comp = manager.getComponent(compPath, callData);
0677:
0678: log.debug("comp loaded: " + comp);
0679:
0680: StringBuffer answer = new StringBuffer();
0681:
0682: answer
0683: .append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
0684: answer
0685: .append("<a:multistatus xmlns:a=\"DAV:\" xmlns:b=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\" xmlns:c=\"xml:\">");
0686:
0687: if ((comp instanceof CText) || (comp instanceof CFragment)
0688: || (comp instanceof CString)
0689: || (comp instanceof CBinary)
0690: || (comp instanceof CNumber)) {
0691: log.debug("std type");
0692: } else {
0693: if (comp instanceof Folder) {
0694: log.debug("folder type");
0695: Folder folder = (Folder) comp;
0696: createFolderEntry(comp, answer, callData,
0697: servletBase);
0698: if (depth > 0) {
0699: Iterator subnames = folder
0700: .getSubcomponentNames();
0701: while (subnames.hasNext()) {
0702: String sname = (String) subnames.next();
0703: log.debug("get subcomponent: " + sname);
0704: Component subc = manager.getSubcomponent(
0705: folder, sname, callData);
0706:
0707: if ((subc instanceof CText)
0708: || (subc instanceof CFragment)
0709: || (subc instanceof CString)
0710: || (subc instanceof CBinary)
0711: || (subc instanceof CNumber)) {
0712: createFileEntry(subc, answer, callData,
0713: servletBase);
0714: } else {
0715: createFolderEntry(subc, answer,
0716: callData, servletBase);
0717: }
0718: }
0719: }
0720: } else {
0721: // just to make sure...
0722: createFileEntry(comp, answer, callData, servletBase);
0723: }
0724: }
0725:
0726: answer
0727: .append("<a:responsedescription>OK.</a:responsedescription>");
0728: answer.append("</a:multistatus>");
0729:
0730: ret = answer.toString();
0731: } catch (ComponentNotFoundException cne) {
0732: StringBuffer answer = new StringBuffer();
0733: answer
0734: .append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
0735: answer
0736: .append("<a:multistatus xmlns:a=\"DAV:\" xmlns:b=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\" xmlns:c=\"xml:\">");
0737: answer.append("<a:response>");
0738: answer.append("<a:href>");
0739: answer.append(servletBase);
0740: answer.append(request.getPathInfo());
0741: answer.append("</a:href>");
0742: answer
0743: .append("<a:status>HTTP/1.1 404 Not Found</a:status>");
0744: answer.append("</a:response>");
0745: answer
0746: .append("<a:responsedescription>Resource not found.</a:responsedescription>");
0747: answer.append("</a:multistatus>");
0748: ret = answer.toString();
0749: } catch (Exception e) {
0750: log.error("EXC: ", e);
0751: }
0752:
0753: response.setStatus(207); // HTTP/1.1 207 Multi-Status
0754: log.debug("RET: " + ret);
0755:
0756: return ret;
0757: }
0758:
0759: private void createFolderEntry(Component comp, StringBuffer answer,
0760: CallData callData, String servletBase) {
0761: ComponentContext ctx = comp.getComponentContext();
0762: ComponentPath cp = ctx.getPath();
0763:
0764: // log.debug("Create Folder Entry: " + cp.getName());
0765:
0766: answer.append("<a:response>");
0767: answer.append("<a:href>");
0768: answer.append(servletBase);
0769: answer.append(cp.toPath());
0770: answer.append("/");
0771: answer.append("</a:href>");
0772: answer.append("<a:propstat>");
0773: answer.append("<a:status>HTTP/1.1 200 OK</a:status>");
0774: answer.append("<a:prop>");
0775: answer
0776: .append("<a:getcontentlength b:dt=\"int\">0</a:getcontentlength>");
0777: answer
0778: .append("<a:creationdate b:dt=\"dateTime.tz\">1980-01-01T00:00:00.000Z</a:creationdate>");
0779: answer.append("<a:displayname>");
0780: answer.append(comp.getComponentContext().getPath().getName());
0781: answer.append("</a:displayname>");
0782: answer.append("<a:getlastmodified b:dt=\"dateTime.rfc1123\">");
0783: answer.append(rfc1123.format(new Date(comp
0784: .getComponentContext().getLastModified())));
0785: answer.append("</a:getlastmodified>");
0786: answer.append("<a:resourcetype>");
0787: answer.append("<a:collection />");
0788: answer.append("</a:resourcetype>");
0789: answer.append("<a:supportedlock />");
0790: answer.append("<a:ishidden b:dt=\"boolean\">0</a:ishidden>");
0791: answer
0792: .append("<a:iscollection b:dt=\"boolean\">1</a:iscollection>");
0793: answer.append("<a:getcontenttype />");
0794: answer.append("</a:prop>");
0795: answer.append("</a:propstat>");
0796: answer.append("</a:response>");
0797:
0798: }
0799:
0800: private void createFileEntry(Component comp, StringBuffer answer,
0801: CallData callData, String servletBase) {
0802: ComponentContext ctx = comp.getComponentContext();
0803: ComponentPath cp = ctx.getPath();
0804:
0805: // log.debug("Create File Entry: " + cp.getName());
0806:
0807: String extension = "";
0808: int contentLength = 0;
0809: if (comp instanceof ContentProvider) {
0810: try {
0811: Content content = ((ContentProvider) comp).getContent();
0812:
0813: if (content instanceof ContelligentBinaryContent) {
0814: ContelligentBinaryContent cbin = (ContelligentBinaryContent) content;
0815: extension = "." + cbin.getExtension(callData);
0816: contentLength = cbin.length(callData);
0817: }
0818:
0819: if (content instanceof ContelligentStringContent) {
0820: ContelligentStringContent cstring = (ContelligentStringContent) content;
0821: extension = ".txt";
0822: contentLength = cstring.getString(callData)
0823: .length();
0824: }
0825: } catch (Exception e) {
0826: log.error("Could not retrieve content.", e);
0827: }
0828: }
0829: answer.append("<a:response>");
0830: answer.append("<a:href>");
0831: answer.append(servletBase);
0832: answer.append(cp.toPath());
0833: answer.append(extension);
0834: answer.append("</a:href>");
0835: answer.append("<a:propstat>");
0836: answer.append("<a:status>HTTP/1.1 200 OK</a:status>");
0837: answer.append("<a:prop>");
0838: answer
0839: .append("<a:getcontentlanguage>en-us</a:getcontentlanguage>");
0840: answer.append("<a:getcontentlength b:dt=\"int\">");
0841:
0842: answer.append(String.valueOf(contentLength));
0843: answer.append("</a:getcontentlength>");
0844: answer
0845: .append("<a:creationdate b:dt=\"dateTime.tz\">1980-01-01T00:00:00.000Z</a:creationdate>");
0846: answer.append("<a:displayname>");
0847: answer.append(cp.getName());
0848: answer.append(extension);
0849: answer.append("</a:displayname>");
0850: answer.append("<a:getlastmodified b:dt=\"dateTime.rfc1123\">");
0851: answer.append(rfc1123.format(new Date(comp
0852: .getComponentContext().getLastModified())));
0853: answer.append("</a:getlastmodified>");
0854: answer.append("<a:resourcetype />");
0855: answer.append("<a:supportedlock>");
0856: answer.append("<a:lockentry>");
0857: answer.append("<a:write />");
0858: answer.append("<a:shared />");
0859: answer.append("</a:lockentry>");
0860: answer.append("<a:lockentry>");
0861: answer.append("<a:write />");
0862: answer.append("<a:exclusive />");
0863: answer.append("</a:lockentry>");
0864: answer.append("</a:supportedlock>");
0865: answer.append("<a:ishidden b:dt=\"boolean\">0</a:ishidden>");
0866: answer
0867: .append("<a:iscollection b:dt=\"boolean\">0</a:iscollection>");
0868: answer
0869: .append("<a:getcontenttype>text/plain</a:getcontenttype>");
0870: answer.append("</a:prop>");
0871: answer.append("</a:propstat>");
0872: answer.append("</a:response>");
0873: }
0874:
0875: Component createNewComponent(ComponentPath compPath,
0876: String extension, CallData callData) {
0877:
0878: log.debug("Create new Component: " + compPath
0879: + " - Extension: " + extension);
0880:
0881: Component newComponent = null;
0882: String type = "-";
0883: try {
0884: ComponentManager cm = callData.getActualManager();
0885: ComponentPath parentPath = new ComponentPath(compPath
0886: .getDir());
0887: Component parent = cm.getComponent(parentPath, callData);
0888: if (extensionMapping.containsKey(extension.toLowerCase())) {
0889: type = ((String[]) extensionMapping.get(extension
0890: .toLowerCase()))[1];
0891: }
0892: if (type == null)
0893: type = DEFAULT_TYPE;
0894:
0895: log.debug("Type: " + type);
0896:
0897: newComponent = cm.createComponent((Container) parent,
0898: compPath.getName(), type, null, null, callData);
0899:
0900: log.debug("Component created.");
0901:
0902: } catch (Exception e) {
0903: log.error("Failes to create Component " + compPath
0904: + " with type " + type);
0905: }
0906: return newComponent;
0907: }
0908:
0909: /**
0910: * Describe <code>setupEnvironment</code> method here.
0911: *
0912: * @param request
0913: * a <code>HttpServletRequest</code> value
0914: * @param response
0915: * a <code>HttpServletResponse</code> value
0916: * @return a <code>CallData</code> value
0917: * @exception SessionCreationException
0918: * if an error occurs
0919: * @exception CategoryException
0920: * if an error occurs
0921: */
0922: HTTPCallDataImpl setupEnvironment(HttpServletRequest request,
0923: HttpServletResponse response, ServletContext context,
0924: String requestBaseURL, String requestHttpAuthBaseURL)
0925: throws SessionCreationException, CategoryException {
0926: final boolean debugEnabled = log.isDebugEnabled();
0927: boolean newSession = false;
0928: boolean configurePreview = false;
0929: String requestType = request.getContentType();
0930: String userAgent = request.getHeader("User-Agent");
0931: if (userAgent == null) {
0932: userAgent = "unspecified";
0933: }
0934: if (debugEnabled) {
0935: log.debug("setupEnvironment() - remote user is: "
0936: + userAgent);
0937: }
0938: boolean flashRequest = false;
0939: boolean searchEngineSpider = isSearchEngineSpider(userAgent);
0940: if (userAgent != null
0941: && userAgent.startsWith("Shockwave Flash")) {
0942: flashRequest = true;
0943: }
0944: if (requestType != null && requestType.equals("text/xml")) {
0945: if (debugEnabled) {
0946: log.debug("setupEnvironment() - request type is: "
0947: + requestType);
0948: }
0949: flashRequest = true;
0950: }
0951:
0952: HttpSession httpSession = request
0953: .getSession(!searchEngineSpider);
0954: ContelligentSession contellSession = null;
0955:
0956: if (!searchEngineSpider) {
0957: contellSession = (ContelligentSession) httpSession
0958: .getAttribute(CONTELLIGENT_SESSION_KEY);
0959: }
0960: if (contellSession == null) {
0961: log
0962: .debug("setupEnvironment() - ... contelligent-session not set -> generating new one ...");
0963: // check for auto-login
0964: /*
0965: * int sCount = contelligent.getNumberOfSessions();
0966: *
0967: * if(sCount >= contelligent.getLicense().getMaxSessions() &&
0968: * contelligent.getLicense().getMaxSessions() > -1 ) { throw new
0969: * MaxSessionsExceededException("max number of sessions exceeded.
0970: * license restricts the number of sessions to:
0971: * "+contelligent.getLicense().getMaxSessions()); }
0972: */
0973:
0974: Cookie[] cookies = request.getCookies();
0975: if (cookies != null) {
0976: for (int i = 0; i < cookies.length; i++) {
0977: Cookie cookie = cookies[i];
0978: if (cookie
0979: .getName()
0980: .equals(
0981: de.finix.contelligent.core.security.AutologinCookie.NAME)) {
0982: log
0983: .debug("setupEnvironment() - ... found cookie for autologin, trying to generate session from it ...");
0984: contellSession = (ContelligentSession) contelligent
0985: .beginSession(cookie);
0986: }
0987: }
0988: }
0989: if (contellSession == null) {
0990: ComponentManager manager = contelligent
0991: .getRootComponentManager();
0992: User initialUser = ContelligentSecurityManager
0993: .getInstance().getGuest();
0994: contellSession = (ContelligentSession) contelligent
0995: .beginSession(initialUser, manager);
0996: newSession = true;
0997: }
0998:
0999: // store contelligent-session in http-session:
1000: if (!searchEngineSpider) {
1001: httpSession.setAttribute(CONTELLIGENT_SESSION_KEY,
1002: contellSession);
1003: }
1004: // to work around a strange bug in tomcat, remove the call data from
1005: // the request
1006: // the callData is not null only after invalidating the HTTP session
1007: // if (request.getAttribute(HTTPCallData.SESSION_KEY) != null) {
1008: // request.removeAttribute(HTTPCallData.SESSION_KEY);
1009: // }
1010: if (debugEnabled)
1011: log.debug("setupEnvironment() - ... created session: "
1012: + contellSession);
1013: }
1014:
1015: // honor contelligent user principal in request
1016: if (request.getUserPrincipal() != null
1017: && request.getUserPrincipal() instanceof User) {
1018: contellSession.setNamedUser((User) request
1019: .getUserPrincipal());
1020: }
1021:
1022: String cSessionId = null;
1023: int previewMode = ContelligentSession.PREVIEW;
1024: if (!flashRequest) {
1025: cSessionId = request
1026: .getParameter(Contelligent.CONTELLIGENT_SESSION_COOKIE);
1027: String mode = request
1028: .getParameter(Contelligent.PREVIEW_MODE);
1029: if (mode != null && mode.equals(Contelligent.EDIT)) {
1030: previewMode = ContelligentSession.EDIT;
1031: }
1032: }
1033:
1034: // cSessionId overloads the userPrincipal from
1035: // request.getUserPrincipal as set above
1036: if (cSessionId != null) {
1037: Session s = contelligent.getSession(cSessionId);
1038: if (s != null) {
1039: contellSession
1040: .addObserverSession((ContelligentSession) s);
1041: contellSession.setComponentManager(s
1042: .getComponentManager());
1043: contellSession.setPreviewMode(previewMode);
1044: contellSession.setNamedUser(s.getUser());
1045: configurePreview = true;
1046:
1047: log.debug("Added session " + cSessionId
1048: + " as observer to " + contellSession.getId());
1049: }
1050: }
1051:
1052: ThreadedMem.setActualManager(contellSession
1053: .getComponentManager());
1054: if (debugEnabled)
1055: log.debug("setupEnvironment() - set actual manager "
1056: + contellSession.getComponentManager());
1057:
1058: HTTPCallDataImpl callData = null;// (HTTPCallData)request.getAttribute(HTTPCallData.SESSION_KEY);
1059:
1060: boolean currentHttpAuth = false;
1061: boolean currentProtocolHttps = false;
1062:
1063: if (requestBaseURL == null) {
1064: requestBaseURL = request.getContextPath(); // = webApp
1065: requestHttpAuthBaseURL = request.getContextPath(); // = webApp
1066:
1067: String requestServletMapping = request.getServletPath();
1068:
1069: String tmp = contelligent.getServletMapping();
1070:
1071: if (!tmp.startsWith("/"))
1072: tmp = "/" + tmp;
1073: requestBaseURL = requestBaseURL + tmp;
1074:
1075: tmp = contelligent.getSSOServletMapping();
1076:
1077: if (!tmp.startsWith("/"))
1078: tmp = "/" + tmp;
1079:
1080: requestHttpAuthBaseURL = requestHttpAuthBaseURL + tmp;
1081:
1082: // if SSO context
1083: if (requestServletMapping.substring(0).equals(tmp)) {
1084: currentHttpAuth = true;
1085: } else {
1086: currentHttpAuth = false;
1087: }
1088:
1089: if (request.getProtocol().toUpperCase().equals("HTTPS")) {
1090: currentProtocolHttps = true;
1091: } else {
1092: currentProtocolHttps = false;
1093: }
1094:
1095: // }
1096: }
1097:
1098: if (debugEnabled) {
1099: log.debug("setupEnvironment() - ... content type is: "
1100: + requestType);
1101: log.debug("setupEnvironment() - ... remote user is: "
1102: + userAgent);
1103: }
1104: if (requestType != null && requestType.startsWith("multipart")) {
1105: callData = new HTTPCallDataImpl(contellSession,
1106: requestBaseURL, requestHttpAuthBaseURL,
1107: contelligent.getHTTPPort(), contelligent
1108: .getHTTPSPort(), currentProtocolHttps,
1109: currentHttpAuth, request, response, context, true);
1110: } else {
1111: callData = new HTTPCallDataImpl(contellSession,
1112: requestBaseURL, requestHttpAuthBaseURL,
1113: contelligent.getHTTPPort(), contelligent
1114: .getHTTPSPort(), currentProtocolHttps,
1115: currentHttpAuth, request, response, context, true);
1116: }
1117:
1118: log.debug("setupEnvironment() - created calldata " + callData);
1119:
1120: ArrayList locales = new ArrayList();
1121: Enumeration enumVar = request.getLocales();
1122:
1123: while (enumVar.hasMoreElements()) {
1124: Object locale = enumVar.nextElement();
1125:
1126: if (locale != null) { // this is for orion
1127: locales.add(locale);
1128: }
1129: }
1130: callData.setLocales(locales);
1131:
1132: if (newSession) {
1133: Map categoryMap = contelligent.getCategoryManager()
1134: .getCategoryMap(callData, true);
1135: contellSession.setCategoryMap(categoryMap);
1136: }
1137:
1138: Map categoryMap = new HashMap(contellSession.getCategoryMap());
1139: categoryMap.putAll(contelligent.getCategoryManager()
1140: .getCategoryMap(callData, false));
1141:
1142: if (userAgent != null
1143: && userAgent.startsWith(CONTELLIGENT_USER_AGENT)) {
1144: if (contelligent.isSecureClient() && (!request.isSecure())) {
1145: throw new ContelligentRuntimeException(
1146: ContelligentExceptionID.security_client_requireSecure);
1147: }
1148: categoryMap.putAll(contelligent.getCategoryManager()
1149: .getCategoryMap(callData.getParameters()));
1150: }
1151: callData.setCategoryMap(categoryMap);
1152: callData.setSearchEngineSpider(searchEngineSpider);
1153: ThreadedMem.setCallData(callData);
1154: if (debugEnabled)
1155: log.debug("setupEnvironment() - ... callData '" + callData
1156: + "' bound to threaded-mem.");
1157:
1158: if (configurePreview) {
1159: String config = request
1160: .getParameter(Contelligent.PREVIEW_CONFIG);
1161: String date = request
1162: .getParameter(Contelligent.PREVIEW_DATE);
1163:
1164: if (config != null) {
1165: try {
1166: contelligent.configurePreview(new ComponentPath(
1167: config), date, contellSession, callData);
1168: } catch (Exception e) {
1169: throw new SessionCreationException(e);
1170: }
1171: }
1172: }
1173: return callData;
1174: }
1175:
1176: private boolean isSearchEngineSpider(String userAgent) {
1177: userAgent = userAgent.toLowerCase();
1178:
1179: for (int i = 0; i < searchEngineBots.length; i++) {
1180: if (userAgent.indexOf(searchEngineBots[i]) != -1) {
1181: return true;
1182: }
1183: }
1184: return false;
1185: }
1186:
1187: }
|