001/*
002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     <a href="mailto:grenard@nuxeo.com">Guillaume</a>
016 */
017package org.nuxeo.ecm.platform.sessioninspector.jsf;
018
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import javax.ws.rs.GET;
024import javax.ws.rs.Path;
025import javax.ws.rs.PathParam;
026import javax.ws.rs.Produces;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.ecm.platform.sessioninspector.jsf.model.MonitorNode;
031import org.nuxeo.ecm.platform.sessioninspector.jsf.model.UIAliasHolderWrapper;
032import org.nuxeo.ecm.platform.sessioninspector.jsf.model.UIComponentWrapper;
033import org.nuxeo.ecm.platform.sessioninspector.util.ObjectVisitor;
034import org.nuxeo.ecm.webengine.model.WebObject;
035import org.nuxeo.ecm.webengine.model.impl.DefaultObject;
036
037/**
038 * @since 5.9.2
039 */
040@WebObject(type = "jsfStateManagerHandler")
041public class StateManagerHandler extends DefaultObject {
042
043    private static final Log log = LogFactory.getLog(StateManagerHandler.class);
044
045    private final static String STATE_ORDER_CLASS = "org.nuxeo.ecm.platform.ui.web.application.NuxeoConversationStateHolder";
046
047    @GET
048    @Produces("text/html")
049    @Path(value = "viewState/{viewId}/{sequenceId}")
050    @SuppressWarnings("boxing")
051    public Object viewState(@PathParam("viewId") String viewId, @PathParam("sequenceId") String sequenceId,
052            @PathParam("computeSize") boolean computeSize) throws NoSuchFieldException, SecurityException,
053            IllegalArgumentException, IllegalAccessException {
054        MonitorNode rootNode = getMonitorNode(viewId, sequenceId);
055
056        long dSessionSize = -1;
057        long cumulatedSize = -1;
058
059        if (false) {
060            // disabled, too heavy to compute for now
061            // try {
062            // dSessionSize = AgentLoader.INSTANCE.getSizer().deepSizeOf(
063            // getStateHolder()) / 1024 / 8;
064            // } catch (Exception e) {
065            // log.error("Could not compute size", e);
066            // dSessionSize = -1;
067            // }
068        }
069
070        Map<String, Object> args = new HashMap<String, Object>();
071        args.put("viewId", viewId);
072        args.put("sequenceId", sequenceId);
073        args.put("dSessionSize", dSessionSize);
074        args.put("cumulatedSize", rootNode.getCumulatedSize());
075        args.put("cumulatedDepth", rootNode.getCumulatedDepth());
076        args.put("maxDepth", rootNode.getMaxDepth());
077
078        List<MonitorNode> nodeList = rootNode.toList();
079        args.put("nodeList", nodeList);
080        args.put("nbBranch", nodeList.size());
081        return getView("viewState").args(args);
082
083    }
084
085    @GET
086    @Produces("text/html")
087    @Path(value = "viewObjects/{viewId}/{sequenceId}")
088    @SuppressWarnings("boxing")
089    public Object viewStats(@PathParam("viewId") String viewId, @PathParam("sequenceId") String sequenceId,
090            @PathParam("computeSize") boolean computeSize) throws NoSuchFieldException, SecurityException,
091            IllegalArgumentException, IllegalAccessException {
092        ObjectVisitor v = new ObjectVisitor();
093        v.visit(getState(viewId, sequenceId));
094
095        Map<String, Object> args = new HashMap<String, Object>();
096        args.put("viewId", viewId);
097        args.put("sequenceId", sequenceId);
098        args.put("objectList", v.getObjectStatisticsList());
099        return getView("viewObjects").args(args);
100
101    }
102
103    @GET
104    @Produces("text/html")
105    @Path(value = "uiComponent/{viewId}/{sequenceId}/{path}")
106    public Object viewUIComponent(@PathParam("viewId") String viewId, @PathParam("sequenceId") String sequenceId,
107            @PathParam("path") String path) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
108            IllegalAccessException {
109        MonitorNode rootNode = getMonitorNode(viewId, sequenceId);
110        MonitorNode childNode = rootNode.getChild(path.split(":"));
111        UIComponentWrapper comp = new UIComponentWrapper(childNode.getId(), (Object[]) childNode.getStateReference());
112
113        Map<String, Object> args = getArguments(childNode, comp, path);
114        return getView("uiComponent").args(args);
115    }
116
117    @SuppressWarnings("boxing")
118    protected Map<String, Object> getArguments(MonitorNode node, UIComponentWrapper comp, String path) {
119        Map<String, Object> args = new HashMap<String, Object>();
120        args.put("id", comp.getId());
121        args.put("path", path);
122        args.put("type", node.getType());
123        args.put("children", comp.getFlatState());
124        args.put("depth", node.getDepth());
125        args.put("size", node.getSize());
126        return args;
127    }
128
129    @GET
130    @Produces("text/html")
131    @Path(value = "uiAliasHolder/{viewId}/{sequenceId}/{path}")
132    public Object viewUIAliasHolder(@PathParam("viewId") String viewId, @PathParam("sequenceId") String sequenceId,
133            @PathParam("path") String path) throws NoSuchFieldException, SecurityException, IllegalArgumentException,
134            IllegalAccessException {
135        MonitorNode rootNode = getMonitorNode(viewId, sequenceId);
136        MonitorNode childNode = rootNode.getChild(path.split(":"));
137        UIAliasHolderWrapper alias = new UIAliasHolderWrapper(childNode.getId(),
138                (Object[]) childNode.getStateReference());
139
140        Map<String, Object> args = getArguments(childNode, alias, path);
141        args.put("aliasId", alias.getAliasId());
142        args.put("mapperSize", alias.getAliasVariableMapperSize());
143        args.put("variables", alias.getVariables().entrySet());
144        return getView("uiAliasHolder").args(args);
145    }
146
147    private MonitorNode getMonitorNode(String viewId, String sequenceId) throws NoSuchFieldException,
148            SecurityException, IllegalArgumentException, IllegalAccessException {
149        Object[] o = getState(viewId, sequenceId);
150        return new MonitorNode(o[0], (Object[]) ((Object[]) o[1])[0]);
151    }
152
153    // FIXME: NuxeoConversationStateHolder has been disabled for JSF2 migration
154
155    private Object[] getState(String viewId, String sequenceId) {
156        return null;
157        // NuxeoConversationStateHolder h = getStateHolder();
158        // String computedViewId = "/" + viewId + ".xhtml";
159        // return h.getState(null, computedViewId, sequenceId);
160    }
161
162    // private NuxeoConversationStateHolder getStateHolder() {
163    // HttpSession s = ctx.getRequest().getSession();
164    // NuxeoConversationStateHolder h = (NuxeoConversationStateHolder)
165    // s.getAttribute(STATE_ORDER_CLASS);
166    // return h;
167    // }
168
169}