org.infoglue.cms.applications.common.actions.SimpleXmlServiceAction.java Source code

Java tutorial

Introduction

Here is the source code for org.infoglue.cms.applications.common.actions.SimpleXmlServiceAction.java

Source

/* ===============================================================================
 *
 * Part of the InfoGlue Content Management Platform (www.infoglue.org)
 *
 * ===============================================================================
 *
 *  Copyright (C)
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2, as published by the
 * Free Software Foundation. See the file LICENSE.html for more information.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY, including the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc. / 59 Temple
 * Place, Suite 330 / Boston, MA 02111-1307 / USA.
 *
 * ===============================================================================
 */

/**
 * @author Stefan Sik
 * @since 1.4
 */

package org.infoglue.cms.applications.common.actions;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.infoglue.cms.applications.common.VisualFormatter;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentTypeDefinitionController;
import org.infoglue.cms.controllers.kernel.impl.simple.ContentVersionController;
import org.infoglue.cms.controllers.kernel.impl.simple.LanguageController;
import org.infoglue.cms.controllers.kernel.impl.simple.RepositoryController;
import org.infoglue.cms.controllers.kernel.impl.simple.TransactionHistoryController;
import org.infoglue.cms.entities.content.ContentVersionVO;
import org.infoglue.cms.entities.kernel.BaseEntityVO;
import org.infoglue.cms.entities.management.ContentTypeDefinitionVO;
import org.infoglue.cms.entities.management.RepositoryVO;
import org.infoglue.cms.entities.management.TransactionHistoryVO;
import org.infoglue.cms.entities.management.impl.simple.ContentTypeDefinitionImpl;
import org.infoglue.cms.exception.ConstraintException;
import org.infoglue.cms.exception.SystemException;
import org.infoglue.cms.security.InfoGluePrincipal;
import org.infoglue.cms.util.ChangeNotificationController;
import org.infoglue.cms.util.CmsPropertyHandler;
import org.infoglue.cms.util.XMLNotificationWriter;
import org.infoglue.deliver.util.Timer;

import com.frovi.ss.Tree.BaseNode;
import com.frovi.ss.Tree.INodeSupplier;

public abstract class SimpleXmlServiceAction extends InfoGlueAbstractAction {
    private final static Logger logger = Logger.getLogger(SimpleXmlServiceAction.class.getName());

    private static final String protectedPropertyFragments = "password,administrator,authorizer,authenticator,masterserver,slaveserver,log";

    protected static final String SERVICEREVISION = "$Revision: 1.24.2.1.2.4 $";
    protected static String ENCODING = "UTF-8";
    protected static String TYPE_FOLDER = "Folder";
    protected static String TYPE_ITEM = "Item";
    protected static String TYPE_REPOSITORY = "Repository";
    protected String showLeafs = "yes";
    protected Integer parent = null;
    protected Integer repositoryId = null;
    protected String urlArgSeparator = "&";
    protected String action = "";
    protected boolean createAction = false;
    protected boolean useTemplate = false;
    protected VisualFormatter formatter = new VisualFormatter();
    protected String[] allowedContentTypeIds = null;

    /*
     * 
     * Experimental
     *
     */
    protected static Map changeNotificationBuffer = new HashMap();

    public abstract INodeSupplier getNodeSupplier() throws SystemException, Exception;

    protected abstract BaseEntityVO getRootEntityVO(Integer repositoryId, InfoGluePrincipal principal)
            throws ConstraintException, SystemException;

    public List getContentTypeDefinitions() throws Exception {
        return ContentTypeDefinitionController.getController().getContentTypeDefinitionVOList();
    }

    public String encode(String text) {
        return text;
    }

    protected String makeAction(BaseNode node) throws UnsupportedEncodingException {
        String action = "javascript:onTreeItemClick(this,";
        //action+="'" + node.getId() + "','" + repositoryId + "','" + URLEncoder.encode(node.getTitle(),ENCODING) + "');";
        //action+="'" + node.getId() + "','" + repositoryId + "','" + new VisualFormatter().escapeForAdvancedJavascripts(node.getTitle()) + "');";
        action += "'" + node.getId() + "','" + repositoryId + "','"
                + new VisualFormatter().escapeForAdvancedJavascripts(node.getTitle()) + "');";
        return action;
    }

    protected String getFormattedDocument(Document doc) {
        return getFormattedDocument(doc, true, false);
    }

    protected String getFormattedDocument(Document doc, boolean compact, boolean supressDecl) {
        OutputFormat format = compact ? OutputFormat.createCompactFormat() : OutputFormat.createPrettyPrint();
        format.setSuppressDeclaration(supressDecl);
        format.setEncoding(ENCODING);
        format.setExpandEmptyElements(false);
        StringWriter stringWriter = new StringWriter();
        XMLWriter writer = new XMLWriter(stringWriter, format);
        try {
            writer.write(doc);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringWriter.toString();
    }

    protected String out(String string) throws IOException {
        getResponse().setContentType("text/xml; charset=" + ENCODING);
        getResponse().setHeader("Cache-Control", "no-cache");
        getResponse().setHeader("Pragma", "no-cache");
        getResponse().setDateHeader("Expires", 0);

        PrintWriter out = getResponse().getWriter();
        out.println(string);
        return NONE;
    }

    /*
     * Returns all Languages for a given repository (repositoryId)
     */
    public String doLanguage() throws Exception {
        return null;
    }

    public String doApplicationSettings() throws Exception {
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("applicationSettings");
        Properties props = CmsPropertyHandler.getProperties();
        for (Iterator i = props.keySet().iterator(); i.hasNext();) {
            String key = (String) i.next();
            String elmKey = key;
            if (key.matches("^\\d.*"))
                elmKey = "_" + key;
            String value = (String) props.get(key);
            if (!isProtectedProperty(key))
                root.addElement(elmKey).setText(value);
        }

        root.addElement("serviceRevision").setText(SERVICEREVISION);
        return out(getFormattedDocument(doc));
    }

    private boolean isProtectedProperty(String key) {
        String[] fragments = protectedPropertyFragments.split(",");
        for (int i = 0; i < fragments.length; i++)
            if (key.toLowerCase().indexOf(fragments[i].toLowerCase()) > -1)
                return true;
        return false;
    }

    /*
     * Returns all contentTypeDefinitions
     */
    public String doContentTypeDefinitions() throws Exception {
        List contentTypeDefinitions = getContentTypeDefinitions();
        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("definitions");
        TransactionHistoryController transactionHistoryController = TransactionHistoryController.getController();

        for (Iterator i = contentTypeDefinitions.iterator(); i.hasNext();) {
            ContentTypeDefinitionVO vo = (ContentTypeDefinitionVO) i.next();
            if (vo.getType().compareTo(ContentTypeDefinitionVO.CONTENT) == 0) {
                TransactionHistoryVO transactionHistoryVO = transactionHistoryController
                        .getLatestTransactionHistoryVOForEntity(ContentTypeDefinitionImpl.class,
                                vo.getContentTypeDefinitionId());

                Element definition = DocumentHelper.createElement("definition");
                definition.addAttribute("id", "" + vo.getContentTypeDefinitionId())
                        .addAttribute("type", "" + vo.getType()).addAttribute("name", vo.getName());

                if (transactionHistoryVO != null)
                    definition.addAttribute("mod", formatDate(transactionHistoryVO.getTransactionDateTime()));

                Element schemaValue = definition.addElement("schemaValue");
                schemaValue.addCDATA(vo.getSchemaValue());
                root.add(definition);
            }
        }

        return out(getFormattedDocument(doc));
    }

    public String doGetChangeNotifications() throws IOException {
        String id = getRequest().getSession().getId();
        StringWriter buffer = (StringWriter) changeNotificationBuffer.get(id);
        if (buffer == null) {
            buffer = new StringWriter();
            buffer.write("<changeNotifications>");
            changeNotificationBuffer.put(id, buffer);
            XMLNotificationWriter streamWriter = new XMLNotificationWriter(buffer, ENCODING, "", null, true, true);
            ChangeNotificationController.getInstance().registerListener(streamWriter);
        }

        buffer.write("</changeNotifications>");
        try {
            out(getFormattedDocument(DocumentHelper.parseText(buffer.toString())));
        } catch (Exception e) {
            out("<exception/>");
        }
        buffer.getBuffer().delete(0, buffer.getBuffer().length());
        buffer.write("<changeNotifications>");
        return null;
    }

    public String doGetChangeNotificationsStream() throws IOException {
        boolean open = true;
        String remoteId = getRequest().getRemoteAddr() + " / " + getInfoGluePrincipal().getName();

        String boundary = getRequest().getParameter("boundary");
        if (boundary == null)
            boundary = "-----------------infoglue-multipart-1d4faa3ac353573";
        getResponse().setHeader("boundary", boundary);
        getResponse().setBufferSize(0);
        getResponse().setContentType("text/plain; charset=" + ENCODING);
        getResponse().flushBuffer();
        Thread thread = Thread.currentThread();
        OutputStream out = getResponse().getOutputStream();
        InputStream in = getRequest().getInputStream();

        XMLNotificationWriter streamWriter = new XMLNotificationWriter(new OutputStreamWriter(out), ENCODING,
                boundary, thread, true, false);

        logger.info("Notification stream listen started from:" + remoteId);
        ChangeNotificationController.getInstance().registerListener(streamWriter);

        Thread streamWriterThread = new Thread(streamWriter);
        streamWriterThread.start();

        while (open) {
            try {
                Thread.sleep(Long.MAX_VALUE);
                out.flush();
            } catch (Exception e) {
                open = false;
            }
        }
        ChangeNotificationController.getInstance().unregisterListener(streamWriter);
        logger.info("Notification stream listen ended from:" + remoteId);
        return null;
    }

    protected String formatDate(Date date) {
        return "" + date;
    }

    /*
     * Main action, returns the content tree
     */
    public String doExecute() throws Exception {
        if (useTemplate)
            return "success";

        Timer t = new Timer();
        if (!logger.isInfoEnabled())
            t.setActive(false);

        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement("tree");

        INodeSupplier sup;

        if (repositoryId == null) {
            List repositories = RepositoryController.getController()
                    .getAuthorizedRepositoryVOList(this.getInfoGluePrincipal(), false);
            for (Iterator i = repositories.iterator(); i.hasNext();) {
                RepositoryVO r = (RepositoryVO) i.next();
                BaseEntityVO entityVO = getRootEntityVO(r.getId(), this.getInfoGluePrincipal());

                String src = action + "?repositoryId=" + r.getId() + urlArgSeparator + "parent=" + entityVO.getId();
                if (createAction && src.length() > 0)
                    src += urlArgSeparator + "createAction=true";
                if (action.length() > 0 && src.length() > 0)
                    src += urlArgSeparator + "action=" + action;
                String allowedContentTypeIdsUrlEncodedString = getAllowedContentTypeIdsAsUrlEncodedString();
                logger.info("allowedContentTypeIdsUrlEncodedString1:" + allowedContentTypeIdsUrlEncodedString);
                if (allowedContentTypeIdsUrlEncodedString.length() > 0 && src.length() > 0)
                    src += urlArgSeparator + allowedContentTypeIdsUrlEncodedString;

                logger.info("src:" + src);

                String text = r.getName();
                Element element = root.addElement("tree");
                element.addAttribute("id", "" + r.getId()).addAttribute("repositoryId", "" + r.getId())
                        .addAttribute("text", encode(text)).addAttribute("src", src)
                        .addAttribute("hasChildren", "true").addAttribute("type", TYPE_REPOSITORY);
            }
            out(getFormattedDocument(doc));
            t.printElapsedTime("End 3");
            return null;
        }

        sup = getNodeSupplier();

        if (parent == null) {
            BaseNode node = sup.getRootNode();
            String text = node.getTitle();
            String type = TYPE_FOLDER;
            String src = action + "?repositoryId=" + repositoryId + urlArgSeparator + "parent=" + node.getId();
            if (createAction && src.length() > 0)
                src += urlArgSeparator + "createAction=true";
            if (action.length() > 0 && src.length() > 0)
                src += urlArgSeparator + "action=" + action;
            String allowedContentTypeIdsUrlEncodedString = getAllowedContentTypeIdsAsUrlEncodedString();
            logger.info("allowedContentTypeIdsUrlEncodedString2:" + allowedContentTypeIdsUrlEncodedString);
            if (allowedContentTypeIdsUrlEncodedString.length() > 0 && src.length() > 0)
                src += urlArgSeparator + allowedContentTypeIdsUrlEncodedString;

            //logger.info("src2:" + src);

            Element elm = root.addElement("tree");
            elm.addAttribute("id", "" + node.getId()).addAttribute("repositoryId", "" + repositoryId)
                    .addAttribute("text", encode(text)).addAttribute("src", src)
                    .addAttribute("isHidden", (String) node.getParameters().get("isHidden"))
                    .addAttribute("hasChildren", "true").addAttribute("type", type);

            if (node.getParameters().containsKey("contentTypeDefinitionId"))
                elm.addAttribute("contentTypeDefinitionId",
                        (String) node.getParameters().get("contentTypeDefinitionId"));

            if (node.getParameters().containsKey("isProtected"))
                elm.addAttribute("isProtected", (String) node.getParameters().get("isProtected"));

            if (node.getParameters().containsKey("stateId"))
                elm.addAttribute("stateId", (String) node.getParameters().get("stateId"));

            out(getFormattedDocument(doc));
            t.printElapsedTime("End 2");
            return null;
        }

        if (parent.intValue() > -1) {
            Collection containerNodes = sup.getChildContainerNodes(parent);
            Collection childNodes = sup.getChildLeafNodes(parent);
            t.printElapsedTime("1.1");

            ContentController contentController = ContentController.getContentController();
            ContentVersionController contentVersionController = ContentVersionController
                    .getContentVersionController();

            Iterator it = containerNodes.iterator();
            while (it.hasNext()) {
                t.printElapsedTime("1.2");
                BaseNode theNode = (BaseNode) it.next();
                if (theNode.isContainer() && sup.hasChildren()) {
                    theNode.setChildren(sup.hasChildren(theNode.getId()));
                }
                t.printElapsedTime("1.3");

                // String src = theNode.hasChildren() ? action + "?repositoryId=" + repositoryId + urlArgSeparator + "parent=" + theNode.getId(): "";
                String src = action + "?repositoryId=" + repositoryId + urlArgSeparator + "parent="
                        + theNode.getId();
                if (createAction && src.length() > 0)
                    src += urlArgSeparator + "createAction=true";
                if (createAction && src.length() > 0)
                    src += urlArgSeparator + "showLeafs=" + showLeafs;
                if (action.length() > 0 && src.length() > 0)
                    src += urlArgSeparator + "action=" + action;
                String allowedContentTypeIdsUrlEncodedString = getAllowedContentTypeIdsAsUrlEncodedString();
                if (allowedContentTypeIdsUrlEncodedString.length() > 0 && src.length() > 0)
                    src += urlArgSeparator + allowedContentTypeIdsUrlEncodedString;

                Element elm = root.addElement("tree");
                elm.addAttribute("id", "" + theNode.getId()).addAttribute("parent", "" + parent)
                        .addAttribute("repositoryId", "" + repositoryId)
                        .addAttribute("text", encode(theNode.getTitle())).addAttribute("src", src)
                        .addAttribute("isHidden", (String) theNode.getParameters().get("isHidden"))
                        .addAttribute("type", TYPE_FOLDER).addAttribute("hasChildren", "" + theNode.hasChildren());

                if (theNode.getParameters().containsKey("contentTypeDefinitionId"))
                    elm.addAttribute("contentTypeDefinitionId",
                            "" + theNode.getParameters().get("contentTypeDefinitionId"));

                if (theNode.getParameters().containsKey("isProtected"))
                    elm.addAttribute("isProtected", (String) theNode.getParameters().get("isProtected"));

                if (theNode.getParameters().containsKey("stateId"))
                    elm.addAttribute("stateId", (String) theNode.getParameters().get("stateId"));

                if (createAction)
                    elm.addAttribute("action", makeAction(theNode));
            }

            it = childNodes.iterator();
            while (it.hasNext()) {
                BaseNode theNode = (BaseNode) it.next();

                String text = theNode.getTitle();
                String action = makeAction(theNode);
                String type = TYPE_ITEM;
                Element elm = root.addElement("tree");
                elm.addAttribute("id", "" + theNode.getId()).addAttribute("parent", "" + parent)
                        .addAttribute("repositoryId", "" + repositoryId).addAttribute("text", encode(text))
                        .addAttribute("type", type);

                if (theNode.getParameters().containsKey("contentTypeDefinitionId"))
                    elm.addAttribute("contentTypeDefinitionId",
                            "" + theNode.getParameters().get("contentTypeDefinitionId"));

                if (theNode.getParameters().containsKey("isProtected"))
                    elm.addAttribute("isProtected", (String) theNode.getParameters().get("isProtected"));

                if (theNode.getParameters().containsKey("stateId"))
                    elm.addAttribute("stateId", (String) theNode.getParameters().get("stateId"));

                if (createAction)
                    elm.addAttribute("action", action);
                else {
                    ContentVersionVO activeVersion = contentVersionController.getLatestActiveContentVersionVO(
                            theNode.getId(),
                            LanguageController.getController().getMasterLanguage(repositoryId).getLanguageId());
                    if (activeVersion != null && !useTemplate) {
                        elm.addAttribute("activeVersion", "" + activeVersion.getContentVersionId());
                        elm.addAttribute("activeVersionStateId", "" + activeVersion.getStateId());
                        elm.addAttribute("activeVersionModifier", "" + activeVersion.getVersionModifier());
                    }
                }
                t.printElapsedTime("1.4");

                //TODO - this was a quickfix only
                if (!useTemplate && sup.getClass().getName().indexOf("Content") > -1) {
                    if (theNode.getParameters().containsKey("contentTypeDefinitionId"))
                        elm.addAttribute("contentTypeId",
                                "" + theNode.getParameters().get("contentTypeDefinitionId"));
                    else {
                        try {
                            ContentTypeDefinitionVO contentTypeDefinitionVO = contentController
                                    .getContentTypeDefinition(theNode.getId());
                            if (contentTypeDefinitionVO != null)
                                elm.addAttribute("contentTypeId",
                                        "" + contentTypeDefinitionVO.getContentTypeDefinitionId());
                        } catch (Exception e) {
                            logger.error("The content " + theNode.getTitle() + " (" + theNode.getId()
                                    + " ) points to a removed content type perhaps: " + e.getMessage());
                        }
                    }
                    t.printElapsedTime("1.5");
                }
            }

            t.printElapsedTime("1.6");

            out(getFormattedDocument(doc));
            t.printElapsedTime("End 1");
            return null;
        }

        return null;
    }

    public Integer getParent() {
        return parent;
    }

    public void setParent(Integer integer) {
        parent = integer;
    }

    public Integer getRepositoryId() {
        return repositoryId;
    }

    public void setRepositoryId(Integer integer) {
        repositoryId = integer;
    }

    public boolean isCreateAction() {
        return createAction;
    }

    public void setCreateAction(boolean createAction) {
        this.createAction = createAction;
    }

    public boolean isUseTemplate() {
        return useTemplate;
    }

    public void setUseTemplate(boolean useTemplate) {
        this.useTemplate = useTemplate;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

    public String getShowLeafs() {
        return showLeafs;
    }

    public void setShowLeafs(String showLeafs) {
        this.showLeafs = showLeafs;
    }

    public String[] getAllowedContentTypeIds() {
        return allowedContentTypeIds;
    }

    public void setAllowedContentTypeIds(String[] allowedContentTypeIds) {
        this.allowedContentTypeIds = allowedContentTypeIds;
    }

    public String getAllowedContentTypeIdsAsUrlEncodedString() throws Exception {
        if (allowedContentTypeIds == null)
            return "";

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < allowedContentTypeIds.length; i++) {
            if (i > 0)
                sb.append("&");

            sb.append("allowedContentTypeIds=" + URLEncoder.encode(allowedContentTypeIds[i], "UTF-8"));
        }

        return sb.toString();
    }
}