Package org.apache.isis.viewer.html.servlet.internal

Source Code of org.apache.isis.viewer.html.servlet.internal.WebController

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you under the Apache License, Version 2.0 (the
*  "License"); you may not use this file except in compliance
*  with the License.  You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing,
*  software distributed under the License is distributed on an
*  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
*  KIND, either express or implied.  See the License for the
*  specific language governing permissions and limitations
*  under the License.
*/

package org.apache.isis.viewer.html.servlet.internal;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.debug.DebugString;
import org.apache.isis.core.commons.exceptions.IsisApplicationException;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.util.Dump;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.userprofile.UserProfile;
import org.apache.isis.core.runtime.userprofile.UserProfilesDebugUtil;
import org.apache.isis.viewer.html.PathBuilder;
import org.apache.isis.viewer.html.action.Action;
import org.apache.isis.viewer.html.action.ActionException;
import org.apache.isis.viewer.html.action.ChangeContext;
import org.apache.isis.viewer.html.action.LogOut;
import org.apache.isis.viewer.html.action.Welcome;
import org.apache.isis.viewer.html.action.edit.AddItemToCollection;
import org.apache.isis.viewer.html.action.edit.EditObject;
import org.apache.isis.viewer.html.action.edit.RemoveItemFromCollection;
import org.apache.isis.viewer.html.action.edit.Save;
import org.apache.isis.viewer.html.action.misc.About;
import org.apache.isis.viewer.html.action.misc.SetUser;
import org.apache.isis.viewer.html.action.misc.SwapUser;
import org.apache.isis.viewer.html.action.view.CollectionView;
import org.apache.isis.viewer.html.action.view.FieldCollectionView;
import org.apache.isis.viewer.html.action.view.ObjectView;
import org.apache.isis.viewer.html.action.view.ServiceView;
import org.apache.isis.viewer.html.component.Block;
import org.apache.isis.viewer.html.component.Component;
import org.apache.isis.viewer.html.component.ComponentFactory;
import org.apache.isis.viewer.html.component.DebugPane;
import org.apache.isis.viewer.html.component.Page;
import org.apache.isis.viewer.html.context.Context;
import org.apache.isis.viewer.html.context.ObjectLookupException;
import org.apache.isis.viewer.html.crumb.Crumb;
import org.apache.isis.viewer.html.image.ImageLookup;
import org.apache.isis.viewer.html.monitoring.servermonitor.Monitor;
import org.apache.isis.viewer.html.request.Request;
import org.apache.isis.viewer.html.task.InvokeMethod;
import org.apache.isis.viewer.html.task.TaskLookupException;
import org.apache.isis.viewer.html.task.TaskStep;

public class WebController {

    private static final Logger LOG = Logger.getLogger(WebController.class);
    private static final Logger ACCESS_LOG = Logger.getLogger("access_log");

    private static final String ERROR_REASON = "This error occurs when you go back to a page " + "using the browsers back button.  To avoid this error in the future please avoid using the back button";

    protected class DebugView implements Action {
        public DebugView() {
        }

        @Override
        public void execute(final Request request, final Context context, final Page page) {
            page.setTitle("Debug");

            final DebugPane debugPane = context.getComponentFactory().createDebugPane();
            page.setDebug(debugPane);

            final DebugString debug = new DebugString();

            final AuthenticationSession authenticationSession = IsisContext.getAuthenticationSession();
            debug.appendTitle("Session");
            if (authenticationSession != null) {
                debug.appendln("user", authenticationSession.getUserName());
                debug.appendln("roles", authenticationSession.getRoles());
            } else {
                debug.appendln("none");
            }

            final UserProfile userProfile = IsisContext.getUserProfile();
            debug.appendTitle("User profile");
            if (userProfile != null) {
                UserProfilesDebugUtil.asDebuggableWithTitle(userProfile).debugData(debug);
            } else {
                debug.appendln("none");
            }

            debug.appendTitle("Actions");
            final Iterator e = actions.entrySet().iterator();
            debug.indent();
            while (e.hasNext()) {
                final Map.Entry element = (Map.Entry) e.next();
                debug.appendln(element.getKey() + " -> " + element.getValue());
            }
            debug.unindent();

            context.debug(debug);

            ImageLookup.debug(debug);

            debugPane.appendln("<pre>" + debug.toString() + "</pre>");
        }

        @Override
        public String name() {
            return "debug";
        }
    }

    protected class DebugSpecification implements Action {
        public DebugSpecification() {
        }

        @Override
        public void execute(final Request request, final Context context, final Page page) {
            final DebugPane debugPane = context.getComponentFactory().createDebugPane();
            page.setDebug(debugPane);

            debugPane.addSection("Specification");
            final ObjectAdapter object = context.getMappedObject(request.getObjectId());
            debugPane.appendln(Dump.specification(object));
        }

        @Override
        public String name() {
            return "spec";
        }
    }

    protected class DebugObject implements Action {
        public DebugObject() {
        }

        @Override
        public void execute(final Request request, final Context context, final Page page) {
            final DebugPane debugPane = context.getComponentFactory().createDebugPane();
            page.setDebug(debugPane);

            debugPane.addSection("Adapter");
            final ObjectAdapter object = context.getMappedObject(request.getObjectId());
            debugPane.appendln(Dump.adapter(object));
            debugPane.addSection("Graph");
            debugPane.appendln(Dump.graph(object, IsisContext.getAuthenticationSession()));
        }

        @Override
        public String name() {
            return "dump";
        }
    }

    protected class DebugOn implements Action {
        private final WebController controller;

        public DebugOn(final WebController controller) {
            this.controller = controller;
        }

        @Override
        public void execute(final Request request, final Context context, final Page page) {
            controller.setDebug(true);
        }

        @Override
        public String name() {
            return "debugon";
        }
    }

    protected class DebugOff implements Action {
        private final WebController controller;

        public DebugOff(final WebController controller) {
            this.controller = controller;
        }

        @Override
        public void execute(final Request request, final Context context, final Page page) {
            controller.setDebug(false);
        }

        @Override
        public String name() {
            return "debugoff";
        }
    }

    private final Map actions = new HashMap();

    private boolean isDebug;
    private final PathBuilder pathBuilder;

    public WebController(final PathBuilder pathBuilder) {
        this.pathBuilder = pathBuilder;
    }

    public boolean actionExists(final Request req) {
        return actions.containsKey(req.getRequestType());
    }

    protected void addAction(final Action action) {
        actions.put(action.name(), action);
    }

    private void addCrumbs(final Context context, final Page page) {
        final Crumb[] crumbs = context.getCrumbs();
        final String[] names = new String[crumbs.length];
        final boolean[] isLinked = context.isLinked();

        for (int i = 0; i < crumbs.length; i++) {
            names[i] = crumbs[i].title();
        }

        final ComponentFactory factory = context.getComponentFactory();
        final Component breadCrumbs = factory.createBreadCrumbs(names, isLinked);

        page.setCrumbs(breadCrumbs);
    }

    public void addDebug(final Page page, final Request req) {
        page.addDebug("<a href=\"" + pathTo("debug") + "\">Debug</a>");
        final String id = req.getObjectId();
        if (id != null) {
            page.addDebug("<a href=\"" + pathTo("dump") + "?id=" + id + "\">Object</a>");
            page.addDebug("<a href=\"" + pathTo("spec") + "?id=" + id + "\">Spec</a>");
        }
        page.addDebug("<a href=\"" + pathTo("about") + "\">About</a>");
        page.addDebug("<a href=\"" + pathTo("debugoff") + "\">Debug off</a>");
    }

    public Page generatePage(final Context context, final Request request) {
        context.restoreAllObjectsToLoader();
        final Page page = context.getComponentFactory().createPage();
        pageHeader(context, page);
        final Block navigation = page.getNavigation();

        final Block optionBar = context.getComponentFactory().createBlock("options", null);
        optionBar.add(context.getComponentFactory().createHeading("Options"));

        Block block = context.getComponentFactory().createBlock("item", null);
        Component option = context.getComponentFactory().createLink("logout", "Log Out", "End the current session");
        block.add(option);
        optionBar.add(block);

        block = context.getComponentFactory().createBlock("item", null);
        option = context.getComponentFactory().createLink("about", "About", "Details about this application");
        block.add(option);
        optionBar.add(block);

        // boolean isExploring = SessionAccess.inExplorationMode();
        final boolean isExploring = IsisContext.getDeploymentType().isExploring();
        if (isExploring) {
            block = context.getComponentFactory().createBlock("item", null);
            option = context.getComponentFactory().createLink("swapuser", "Swap User", "Swap the exploration user");
            block.add(option);
            optionBar.add(block);
        }

        navigation.add(optionBar);

        listServices(context, navigation);
        listHistory(context, navigation);
        Monitor.addEvent("Web", "Request " + request);
        runAction(context, request, page);
        addCrumbs(context, page);

        // The web viewer has no views of other objects, so changes can be
        // ignored
        if (IsisContext.inSession() && IsisContext.inTransaction()) {
            IsisContext.getUpdateNotifier().clear();
        }
        // TODO deal with disposed objects

        return page;
    }

    public void init() {
        addAction(new About());
        addAction(new SwapUser());
        addAction(new SetUser());
        addAction(new DebugView());
        addAction(new DebugSpecification());
        addAction(new DebugObject());
        addAction(new Welcome());
        addAction(new ObjectView());
        addAction(new CollectionView());
        addAction(new FieldCollectionView());
        addAction(new InvokeMethod());
        addAction(new TaskStep());
        addAction(new EditObject());
        addAction(new Save());
        addAction(new ServiceView());
        addAction(new LogOut());
        addAction(new RemoveItemFromCollection());
        addAction(new AddItemToCollection());
        addAction(new ChangeContext());

        // TODO allow these to be exclude by configuration so they cannot be run
        // in a real system
        addAction(new DebugOn(this));
        addAction(new DebugOff(this));

        Logger.getLogger(this.getClass()).info("init");
    }

    public boolean isDebug() {
        return isDebug;
    }

    private void listHistory(final Context context, final Block navigation) {
        context.listHistory(context, navigation);
    }

    private void listServices(final Context context, final Block navigationBar) {
        final Block taskBar = context.getComponentFactory().createBlock("services", null);
        taskBar.add(context.getComponentFactory().createHeading("Services"));
        final AdapterManager adapterManager = IsisContext.getPersistenceSession().getAdapterManager();
        final List<Object> services = getUserProfile().getPerspective().getServices();
        for (final Object service : services) {
            final ObjectAdapter serviceAdapter = adapterManager.adapterFor(service);
            if (serviceAdapter == null) {
                LOG.warn("unable to find service Id: " + service + "; skipping");
                continue;
            }
            if (isHidden(serviceAdapter)) {
                continue;
            }
            final String serviceMapId = context.mapObject(serviceAdapter);
            taskBar.add(createServiceComponent(context, serviceMapId, serviceAdapter));
        }
        navigationBar.add(taskBar);
    }

    private Component createServiceComponent(final Context context, final String serviceMapId, final ObjectAdapter serviceNO) {
        final String serviceName = serviceNO.titleString();
        final String serviceIcon = serviceNO.getIconName();
        return context.getComponentFactory().createService(serviceMapId, serviceName, serviceIcon);
    }

    private boolean isHidden(final ObjectAdapter serviceNO) {
        final ObjectSpecification serviceNoSpec = serviceNO.getSpecification();
        final boolean isHidden = serviceNoSpec.isHidden();
        return isHidden;
    }

    private void pageHeader(final Context context, final Page page) {
        page.getPageHeader().add(context.getComponentFactory().createInlineBlock("none", "", null));
    }

    private void runAction(final Context context, final Request request, final Page page) {
        try {
            ACCESS_LOG.info("request " + request.toString());
            Request r = request;
            final DebugString debug = new DebugString();
            debug.startSection("Request");
            debug.appendln("http", request.toString());
            debug.endSection();
            do {
                final Action action = (Action) actions.get(r.getRequestType());
                try {
                    action.execute(r, context, page);
                } catch (final ObjectLookupException e) {
                    final String error = "The object/service you selected has timed out.  Please navigate to the object via the history bar.";
                    displayError(context, page, error);
                } catch (final TaskLookupException e) {
                    final String error = "The task you went back to has already been completed or cancelled.  Please start the task again.";
                    displayError(context, page, error);
                }
                r = r.getForward();
                if (r != null) {
                    LOG.debug("forward to " + r);
                }
            } while (r != null);
            if (LOG.isDebugEnabled()) {
                context.debug(debug);
                debug.appendln();
                if (IsisContext.inSession()) {
                    IsisContext.getSession(getExecutionContextId()).debugAll(debug);
                } else {
                    debug.appendln("No session");
                }
                LOG.debug(debug.toString());
            }
        } catch (final ActionException e) {
            page.setTitle("Error");
            page.getViewPane().setTitle("Error", "Action Exception");
            LOG.error("ActionException, executing action " + request.getRequestType(), e);
            page.getViewPane().add(context.getComponentFactory().createErrorMessage(e, isDebug));
        } catch (final IsisApplicationException e) {
            page.setTitle("Error");
            page.getViewPane().setTitle("Error", "Application Exception");
            LOG.error("ApplicationException, executing action " + request.getRequestType(), e);
            page.getViewPane().add(context.getComponentFactory().createErrorMessage(e, isDebug));
        } catch (final IsisException e) {
            page.setTitle("Error");
            page.getViewPane().setTitle("Error", "System Exception");
            LOG.error("ObjectAdapterRuntimeException, executing action " + request.getRequestType(), e);
            page.getViewPane().add(context.getComponentFactory().createErrorMessage(e, true));
        } catch (final RuntimeException e) {
            page.setTitle("Error");
            page.getViewPane().setTitle("Error", "System Exception");
            LOG.error("RuntimeException, executing action " + request.getRequestType(), e);
            page.getViewPane().add(context.getComponentFactory().createErrorMessage(e, true));
        }
    }

    private void displayError(final Context context, final Page page, final String errorMessage) {
        page.setTitle("Error");
        page.getViewPane().setTitle("Error", "");

        final Block block1 = context.getComponentFactory().createBlock("error", "");
        block1.add(context.getComponentFactory().createInlineBlock("", errorMessage, ""));
        page.getViewPane().add(block1);

        final Block block2 = context.getComponentFactory().createBlock("text", "");
        block2.add(context.getComponentFactory().createInlineBlock("", ERROR_REASON, ""));
        page.getViewPane().add(block2);
    }

    public void setDebug(final boolean on) {
        this.isDebug = on;
    }

    protected String pathTo(final String prefix) {
        return pathBuilder.pathTo(prefix);
    }

    // ///////////////////////////////////////////////////////
    // Dependencies (from singleton)
    // ///////////////////////////////////////////////////////

    private UserProfile getUserProfile() {
        return IsisContext.getUserProfile();
    }

    private String getExecutionContextId() {
        return IsisContext.getSessionId();
    }
}
TOP

Related Classes of org.apache.isis.viewer.html.servlet.internal.WebController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.