/*
* $Id: XopusHandlerAction.java,v 1.30 2003/05/02 15:32:20 michi Exp $
* <License>
* The Apache Software License
*
* Copyright (c) 2002 lenya. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software must
* display the following acknowledgment: "This product includes software developed
* by lenya (http://www.lenya.org)"
*
* 4. The name "lenya" must not be used to endorse or promote products derived from
* this software without prior written permission. For written permission, please
* contact contact@lenya.org
*
* 5. Products derived from this software may not be called "lenya" nor may "lenya"
* appear in their names without prior written permission of lenya.
*
* 6. Redistributions of any form whatsoever must retain the following acknowledgment:
* "This product includes software developed by lenya (http://www.lenya.org)"
*
* THIS SOFTWARE IS PROVIDED BY lenya "AS IS" WITHOUT ANY WARRANTY EXPRESS OR IMPLIED,
* INCLUDING THE WARRANTY OF NON-INFRINGEMENT AND THE IMPLIED WARRANTIES OF MERCHANTI-
* BILITY AND FITNESS FOR A PARTICULAR PURPOSE. lenya WILL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY YOU AS A RESULT OF USING THIS SOFTWARE. IN NO EVENT WILL lenya BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR LOST PROFITS EVEN IF lenya HAS
* BEEN ADVISED OF THE POSSIBILITY OF THEIR OCCURRENCE. lenya WILL NOT BE LIABLE FOR ANY
* THIRD PARTY CLAIMS AGAINST YOU.
*
* Lenya includes software developed by the Apache Software Foundation, W3C,
* DOM4J Project, BitfluxEditor and Xopus.
* </License>
*/
package org.apache.lenya.cms.cocoon.acting;
import org.apache.avalon.excalibur.io.FileUtil;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.acting.ConfigurableComposerAction;
import org.apache.excalibur.xml.dom.DOMParser;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.environment.http.HttpRequest;
import org.apache.cocoon.serialization.Serializer;
import org.apache.cocoon.util.IOUtils;
import org.apache.cocoon.util.PostInputStream;
import org.apache.cocoon.xml.dom.DOMStreamer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.lenya.cms.ac.Identity;
import org.apache.lenya.cms.rc.RevisionController;
import org.apache.lenya.xml.DOMParserFactory;
import org.apache.lenya.xml.DOMWriter;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.String;
import java.util.HashMap;
import java.util.Map;
/**
* Interfaces with Xopus: handles the requests and replies to them
*
* @author Memo Birgi
* @author Michael Wechner
* @version 2003.1.4
*/
public class XopusHandlerAction extends ConfigurableComposerAction {
private String xmlRoot = null;
private String xslRoot = null;
private String xsdRoot = null;
private String tempRoot = null;
private Map relRootDirs = new HashMap();
private String rcmlDirectory = null;
private String backupDirectory = null;
/**
* Gets the configuration from the sitemap
*
* @param conf DOCUMENT ME!
*
* @throws ConfigurationException DOCUMENT ME!
*/
public void configure(Configuration conf) throws ConfigurationException {
super.configure(conf);
xmlRoot = conf.getChild("xml").getAttribute("href");
xslRoot = conf.getChild("xsl").getAttribute("href");
xsdRoot = conf.getChild("xsd").getAttribute("href");
tempRoot = conf.getChild("temp").getAttribute("href");
getLogger().debug(".configure(): \n" + "Relative XML Root Directory: " + xmlRoot + "\n" +
"Relative XSL Root Directory: " + xslRoot + "\n" + "Relative XSD Root Directory: " +
xsdRoot + "\n" + "Relative Temp Directory: " + tempRoot);
// Encode File types and their root directories, relative to the sitemap directory
relRootDirs.put("xml", xmlRoot);
relRootDirs.put("xsl", xslRoot);
relRootDirs.put("xsd", xsdRoot);
relRootDirs.put("temp", tempRoot);
// Revision Control Parameters
rcmlDirectory = conf.getChild("rcmlDirectory").getAttribute("href");
backupDirectory = conf.getChild("backupDirectory").getAttribute("href");
}
/**
* DOCUMENT ME!
*
* @param redirector DOCUMENT ME!
* @param resolver DOCUMENT ME!
* @param objectModel DOCUMENT ME!
* @param source DOCUMENT ME!
* @param params DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws IOException DOCUMENT ME!
* @throws ComponentException DOCUMENT ME!
* @throws SAXException DOCUMENT ME!
* @throws ProcessingException DOCUMENT ME!
*/
public java.util.Map act(Redirector redirector, SourceResolver resolver, Map objectModel,
String source, Parameters params)
throws IOException, ComponentException, SAXException, ProcessingException {
// Get absolute path of sitemap directory
org.apache.cocoon.environment.Source input_source = resolver.resolve("");
String sitemapPath = input_source.getSystemId();
sitemapPath = sitemapPath.substring(5); // Remove "file:" protocol
getLogger().debug(".act(): Absolute Sitemap Directory: " + sitemapPath);
getLogger().debug(".act(): Absolute XML Root Directory: " + sitemapPath + xmlRoot);
getLogger().debug(".act(): Absolute XSL Root Directory: " + sitemapPath + xslRoot);
getLogger().debug(".act(): Absolute XSD Root Directory: " + sitemapPath + xsdRoot);
getLogger().debug(".act(): Absolute Temp Root Directory: " + sitemapPath + tempRoot);
// Get request object
HttpRequest httpReq = (HttpRequest) objectModel.get(ObjectModelHelper.REQUEST_OBJECT);
if (httpReq == null) {
getLogger().error("Could not get HTTP_REQUEST_OBJECT from objectModel");
return null;
}
int length = httpReq.getContentLength();
PostInputStream reqContent = new PostInputStream(httpReq.getInputStream(), length);
// construct DOM document from the request contents
DOMParser parser = (DOMParser) this.manager.lookup(DOMParser.ROLE);
InputSource saxSource = new InputSource(reqContent);
Document requestDoc = parser.parseDocument(saxSource);
// get the root element (should be "request") and its attributes ---> FixMe: Add error handling
Element root = requestDoc.getDocumentElement();
getLogger().debug(".act(): Root element (should be 'request'): " + root.getTagName());
String reqId = root.getAttribute("id");
getLogger().debug(".act(): Request ID: " + reqId);
String reqType = root.getAttribute("type");
getLogger().debug(".act(): Request Type: " + reqType);
// get the first child element for root element (should be "data") and its attributes ---> FixMe: Add error handling
Element data = (Element) root.getFirstChild();
getLogger().debug(".act(): first child element (should be 'data'): " + data.getTagName());
String reqFile = data.getAttribute("id");
getLogger().debug(".act(): Requested File: " + reqFile);
String fileType = data.getAttribute("type");
getLogger().debug(".act(): Requested File's Type: " + fileType);
// close the input stream
reqContent.close();
// Define Files
File tempFileDir = new File(sitemapPath + relRootDirs.get("temp") + "/" + relRootDirs.get(fileType));
if (!(tempFileDir.exists())) {
tempFileDir.mkdir();
}
File tempFile = IOUtils.createFile(tempFileDir, reqFile);
File permFile = new File(sitemapPath + relRootDirs.get(fileType) + "/" + reqFile);
if(!permFile.exists()) {
getLogger().error(".act(): No such file: " + permFile.getAbsolutePath());
getLogger().error(".act(): No such file: " + sitemapPath + "::" + relRootDirs.get(fileType) + "::" + reqFile);
return null;
}
// make a temporary copy of the file to be edited
if ("xml".equals(fileType) && "open".equals(reqType)) {
FileUtil.copyFile(permFile, tempFile);
getLogger().debug(".act(): PERMANENT FILE: " + permFile.getAbsolutePath());
getLogger().debug(".act(): TEMPORARY FILE: " + tempFile.getAbsolutePath());
}
// set sitemap params for response routing
Map sitemapParams = new HashMap();
sitemapParams.put("reqId", reqId);
sitemapParams.put("reqType", reqType);
sitemapParams.put("reqFile", reqFile);
sitemapParams.put("fileType", fileType);
if ("xml".equals(fileType) && ("open".equals(reqType) || "save".equals(reqType))) {
sitemapParams.put("reqFilePath", (String) relRootDirs.get("temp") + "/" + (String) relRootDirs.get(fileType) + "/" + reqFile);
getLogger().debug(".act(): File to be edited (in temp dir): " + sitemapParams.get("reqFilePath"));
} else {
sitemapParams.put("reqFilePath", (String) relRootDirs.get(fileType) + "/" + reqFile);
}
// The xopus sitemap will return the XML
if ("open".equals(reqType)) {
return sitemapParams;
}
// save to temporary file, if needed
if ("save".equals(reqType) || "checkin".equals(reqType)) {
getLogger().debug(".act(): Write to temp file: " + tempFile);
try {
Element contentNode = (Element) data.getFirstChild();
DOMParserFactory dpf = new DOMParserFactory();
// Create a new document, where the actual content starts at the root element, which is the inner part of requestDoc
Document contentDocument = dpf.getDocument();
contentDocument.appendChild((Element) dpf.cloneNode(contentDocument, contentNode, true));
new DOMWriter(new FileOutputStream(tempFile)).printWithoutFormatting(contentDocument);
} catch (Exception e) {
getLogger().error(".act(): Exception during writing to temp file: " + e);
}
}
// save to permanent file, if needed
if ("checkin".equals(reqType)) {
getLogger().debug(".act(): Save to permanent file: " + permFile);
RevisionController rc = new RevisionController(sitemapPath + rcmlDirectory,
sitemapPath + backupDirectory, sitemapPath);
try {
Session session = httpReq.getSession(false);
if (session == null) {
throw new Exception("No session");
}
Identity identity = (Identity) session.getAttribute("org.apache.lenya.cms.ac.Identity");
getLogger().debug(".act(): Checkin: " + reqFile + "::" + identity.getUsername());
rc.reservedCheckIn(xmlRoot + reqFile, identity.getUsername(), true);
FileUtil.copyFile(tempFile, permFile);
} catch (Exception e) {
getLogger().error(".act(): Exception during checkin of " + xmlRoot + reqFile + " (" + e + ")");
return null;
}
}
return sitemapParams;
}
}