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