You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/06 11:10:37 UTC

[44/51] [partial] ISIS-188: moving modules into core

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileLoaderDefault.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileLoaderDefault.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileLoaderDefault.java
new file mode 100644
index 0000000..68945ad
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileLoaderDefault.java
@@ -0,0 +1,251 @@
+/*
+ *  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.runtimes.dflt.runtime.userprofile;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.userprofile.UserProfile;
+import org.apache.isis.core.runtime.userprofile.UserProfileLoader;
+import org.apache.isis.core.runtime.userprofile.UserProfileStore;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.session.IsisSession;
+
+/**
+ * Acts like a bridge, loading the profile from the underlying store.
+ */
+public class UserProfileLoaderDefault implements UserProfileLoader, DebuggableWithTitle {
+
+    private static final String DEFAULT_PERSPECTIVE_NAME = "Apache Isis";
+    private static final String EXPLORATION = " Exploration";
+
+    private final Logger LOG = Logger.getLogger(UserProfile.class);
+
+    public static enum Mode {
+        /**
+         * Must provide some services.
+         */
+        STRICT,
+        /**
+         * For testing only, no services is okay.
+         */
+        RELAXED
+    }
+
+    private final UserProfileStore store;
+    private final Mode mode;
+
+    private UserProfile userProfile;
+
+    private List<Object> serviceList;
+
+    // //////////////////////////////////////////////////////
+    // Constructor
+    // //////////////////////////////////////////////////////
+
+    public UserProfileLoaderDefault(final UserProfileStore store) {
+        this(store, Mode.STRICT);
+    }
+
+    /**
+     * for testing purposes, explicitly specify the Mode.
+     */
+    public UserProfileLoaderDefault(final UserProfileStore store, final Mode mode) {
+        this.store = store;
+        this.mode = mode;
+    }
+
+    // //////////////////////////////////////////////////////
+    // init, shutdown
+    // //////////////////////////////////////////////////////
+
+    /**
+     * Does nothing.
+     */
+    @Override
+    public void init() {
+    }
+
+    /**
+     * Does nothing.
+     */
+    @Override
+    public void shutdown() {
+    }
+
+    // //////////////////////////////////////////////////////
+    // Fixtures
+    // //////////////////////////////////////////////////////
+
+    /**
+     * @see PersistenceSession#isFixturesInstalled()
+     */
+    @Override
+    public boolean isFixturesInstalled() {
+        return store.isFixturesInstalled();
+    }
+
+    // //////////////////////////////////////////////////////
+    // saveAs...
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public void saveAsDefault(final UserProfile userProfile) {
+        store.save("_default", userProfile);
+    }
+
+    @Override
+    public void saveForUser(final String userName, final UserProfile userProfile) {
+        store.save(userName, userProfile);
+    }
+
+    // //////////////////////////////////////////////////////
+    // saveSession
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public void saveSession(final List<ObjectAdapter> objects) {
+        loadOrCreateProfile();
+        userProfile.saveObjects(objects);
+        save(userProfile);
+    }
+
+    private void save(final UserProfile userProfile) {
+        saveForUser(userName(), userProfile);
+    }
+
+    // //////////////////////////////////////////////////////
+    // getProfile
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public UserProfile getProfile(final AuthenticationSession session) {
+        final String userName = session.getUserName();
+        final UserProfile profile = store.getUserProfile(userName);
+        userProfile = profile != null ? profile : createUserProfile(userName);
+        return userProfile;
+    }
+
+    @Override
+    @Deprecated
+    public UserProfile getProfile() {
+        loadOrCreateProfile();
+        return userProfile;
+    }
+
+    // //////////////////////////////////////////////////////
+    // Helpers: (for getProfile)
+    // //////////////////////////////////////////////////////
+
+    private void loadOrCreateProfile() {
+        if (userProfile == null) {
+            final String userName = userName();
+            final UserProfile profile = store.getUserProfile(userName);
+            userProfile = profile != null ? profile : createUserProfile(userName);
+        }
+    }
+
+    private UserProfile createUserProfile(final String userName) {
+        final UserProfile template = store.getUserProfile("_default");
+        if (template == null) {
+            return createDefaultProfile(userName);
+        } else {
+            return createProfileFromTemplate(userName, template);
+        }
+    }
+
+    private UserProfile createDefaultProfile(final String userName) {
+        final UserProfile profile = new UserProfile();
+        profile.newPerspective(DEFAULT_PERSPECTIVE_NAME + (IsisContext.getDeploymentType().isExploring() ? EXPLORATION : ""));
+
+        final List<Object> services = getServices();
+        if (services.size() == 0 && mode == Mode.STRICT) {
+            throw new IsisException("No known services");
+        }
+        for (final Object service : services) {
+            profile.getPerspective().addToServices(service);
+        }
+        LOG.debug("creating exploration UserProfile for " + userName);
+        return profile;
+    }
+
+    private UserProfile createProfileFromTemplate(final String userName, final UserProfile template) {
+        final UserProfile userProfile = new UserProfile();
+        userProfile.copy(template);
+        LOG.info("creating UserProfile, from template, for " + userName);
+        return userProfile;
+    }
+
+    // //////////////////////////////////////////////////////
+    // Debugging
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln("Store", store.toString());
+        debug.appendln("Mode", mode);
+
+        debug.appendln("Store", store);
+        debug.appendln("User Profile", userProfile);
+    }
+
+    @Override
+    public String debugTitle() {
+        return "User Profile Service";
+    }
+
+    // //////////////////////////////////////////////////////
+    // Dependencies (injected via setters)
+    // //////////////////////////////////////////////////////
+
+    @Override
+    public List<Object> getServices() {
+        return serviceList;
+    }
+
+    @Override
+    public void setServices(final List<Object> serviceList) {
+        this.serviceList = serviceList;
+    }
+
+    // //////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // //////////////////////////////////////////////////////
+
+    private static AuthenticationSession getAuthenticationSession() {
+        return getSession().getAuthenticationSession();
+    }
+
+    private static String userName() {
+        return getAuthenticationSession().getUserName();
+    }
+
+    private static IsisSession getSession() {
+        return IsisContext.getSession();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileStoreInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileStoreInstaller.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileStoreInstaller.java
new file mode 100644
index 0000000..bfa8f69
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfileStoreInstaller.java
@@ -0,0 +1,32 @@
+/*
+ *  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.runtimes.dflt.runtime.userprofile;
+
+import org.apache.isis.core.commons.components.Installer;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.runtime.userprofile.UserProfileStore;
+
+public interface UserProfileStoreInstaller extends Installer {
+
+    public static String TYPE = "user-profile-store";
+
+    UserProfileStore createUserProfileStore(final IsisConfiguration objectConfiguration);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfilesDebugUtil.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfilesDebugUtil.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfilesDebugUtil.java
new file mode 100644
index 0000000..252c24c
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/userprofile/UserProfilesDebugUtil.java
@@ -0,0 +1,103 @@
+/*
+ *  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.runtimes.dflt.runtime.userprofile;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.services.ServiceUtil;
+import org.apache.isis.core.runtime.userprofile.PerspectiveEntry;
+import org.apache.isis.core.runtime.userprofile.UserProfile;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+
+/**
+ * Introduced in order to remove the dependency between {@link UserProfile} and
+ * {@link PerspectiveEntry} on <tt>runtimes:dflt</tt>.
+ */
+public final class UserProfilesDebugUtil {
+
+    public static DebuggableWithTitle asDebuggableWithTitle(final UserProfile userProfile) {
+        return new DebuggableWithTitle() {
+
+            @Override
+            public void debugData(final DebugBuilder debug) {
+                debug.appendTitle("Options");
+                debug.indent();
+                debug.append(userProfile.getOptions());
+                debug.unindent();
+
+                debug.appendTitle("Perspectives");
+                for (final PerspectiveEntry entry : userProfile.getEntries()) {
+                    asDebuggableWithTitle(entry).debugData(debug);
+                }
+            }
+
+            @Override
+            public String debugTitle() {
+                return toString();
+            }
+        };
+    }
+
+    public static DebuggableWithTitle asDebuggableWithTitle(final PerspectiveEntry perspectiveEntry) {
+        return new DebuggableWithTitle() {
+
+            @Override
+            public void debugData(final DebugBuilder debug) {
+                debug.appendln("Name", perspectiveEntry.getName());
+                debug.blankLine();
+                debug.appendTitle("Services (Ids)");
+                debug.indent();
+                for (final Object service : perspectiveEntry.getServices()) {
+                    debug.appendln(ServiceUtil.id(service));
+                }
+                debug.unindent();
+
+                debug.blankLine();
+                debug.appendTitle("Objects");
+                debug.indent();
+                final AdapterManager adapterManager = getAdapterManager();
+                for (final Object obj : perspectiveEntry.getObjects()) {
+                    debug.appendln(adapterManager.adapterFor(obj).toString());
+                }
+                debug.unindent();
+            }
+
+            @Override
+            public String debugTitle() {
+                return "Perspective";
+            }
+        };
+    }
+
+    // ///////////////////////////////////////////////////////
+    // Dependencies (from Context)
+    // ///////////////////////////////////////////////////////
+
+    protected static AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected static PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewer.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewer.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewer.java
new file mode 100644
index 0000000..bfa4587
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewer.java
@@ -0,0 +1,45 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer;
+
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderAware;
+import org.apache.isis.runtimes.dflt.runtime.systemdependencyinjector.SystemDependencyInjectorAware;
+import org.apache.isis.runtimes.dflt.runtime.viewer.web.WebAppSpecification;
+
+/**
+ * Defines an mechanism for manipulating the domain objects.
+ * 
+ * <p>
+ * The mechanism may be realized as a user interface (for example the DnD viewer
+ * or HTML viewer) but might also be an abstract 'remoting' viewer of sockets or
+ * HTTP servlet requests.
+ */
+public interface IsisViewer extends ApplicationScopedComponent, SystemDependencyInjectorAware, IsisConfigurationBuilderAware {
+
+    /**
+     * Provide requirement for running a viewer from within an embedded web
+     * container.
+     * 
+     * <p>
+     * Returns <tt>null</tt> if does not run within a web container.
+     */
+    WebAppSpecification getWebAppSpecification();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerAbstract.java
new file mode 100644
index 0000000..c6f60b6
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerAbstract.java
@@ -0,0 +1,163 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilder;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderAware;
+import org.apache.isis.core.commons.ensure.Ensure;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequest;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.IsisSystem;
+import org.apache.isis.runtimes.dflt.runtime.system.SystemConstants;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.systemdependencyinjector.SystemDependencyInjector;
+import org.apache.isis.runtimes.dflt.runtime.systemdependencyinjector.SystemDependencyInjectorAware;
+import org.apache.isis.runtimes.dflt.runtime.viewer.web.WebAppSpecification;
+
+public abstract class IsisViewerAbstract implements IsisViewer {
+
+    /**
+     * @see {@link #setDeploymentType(DeploymentType)}
+     */
+    private DeploymentType deploymentType;
+
+    private SystemDependencyInjector systemDependencyInjector;
+    private IsisConfigurationBuilder isisConfigurationBuilder;
+
+    /**
+     * Optionally set, see
+     * {@link #setAuthenticationRequestViaArgs(AuthenticationRequest)}
+     */
+    private AuthenticationRequest authenticationRequestViaArgs;
+
+    // ////////////////////////////////////////////////////////////////
+    // Settings
+    // ////////////////////////////////////////////////////////////////
+
+    @Override
+    public void init() {
+
+        ensureDependenciesInjected();
+
+        final IsisConfiguration configuration = isisConfigurationBuilder.getConfiguration();
+        deploymentType = DeploymentType.lookup(configuration.getString(SystemConstants.DEPLOYMENT_TYPE_KEY));
+
+        final String user = configuration.getString(SystemConstants.USER_KEY);
+        final String password = configuration.getString(SystemConstants.PASSWORD_KEY);
+
+        if (user != null) {
+            authenticationRequestViaArgs = new AuthenticationRequestPassword(user, password);
+        }
+    }
+
+    @Override
+    public void shutdown() {
+        // does nothing
+    }
+
+    // ////////////////////////////////////////////////////////////////
+    // Settings
+    // ////////////////////////////////////////////////////////////////
+
+    public final DeploymentType getDeploymentType() {
+        return deploymentType;
+    }
+
+    /**
+     * Default implementation to return null, indicating that this viewer should
+     * not be run in a web container.
+     */
+    @Override
+    public WebAppSpecification getWebAppSpecification() {
+        return null;
+    }
+
+    public AuthenticationRequest getAuthenticationRequestViaArgs() {
+        return authenticationRequestViaArgs;
+    }
+
+    protected void clearAuthenticationRequestViaArgs() {
+        authenticationRequestViaArgs = null;
+    }
+
+    // ////////////////////////////////////////////////////////////////
+    // Post-bootstrapping
+    // ////////////////////////////////////////////////////////////////
+
+    public LogonFixture getLogonFixture() {
+        return null;
+    }
+
+    // ////////////////////////////////////////////////////////////////
+    // Dependencies (injected)
+    // ////////////////////////////////////////////////////////////////
+
+    protected void ensureDependenciesInjected() {
+        Ensure.ensureThatState(systemDependencyInjector, is(not(nullValue())));
+        Ensure.ensureThatState(isisConfigurationBuilder, is(not(nullValue())));
+    }
+
+    /**
+     * Injected by virtue of being {@link SystemDependencyInjectorAware}.
+     */
+    @Override
+    public void setSystemDependencyInjector(final SystemDependencyInjector dependencyInjector) {
+        this.systemDependencyInjector = dependencyInjector;
+    }
+
+    protected IsisConfigurationBuilder getConfigurationBuilder() {
+        return isisConfigurationBuilder;
+    }
+
+    /**
+     * Injected by virtue of being {@link IsisConfigurationBuilderAware}.
+     */
+    @Override
+    public void setConfigurationBuilder(final IsisConfigurationBuilder isisConfigurationBuilder) {
+        this.isisConfigurationBuilder = isisConfigurationBuilder;
+    }
+
+    // ////////////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // ////////////////////////////////////////////////////////////////
+
+    /**
+     * Available after {@link IsisSystem} has been bootstrapped.
+     */
+    protected static IsisConfiguration getConfiguration() {
+        return IsisContext.getConfiguration();
+    }
+
+    /**
+     * Available after {@link IsisSystem} has been bootstrapped.
+     */
+    public static AuthenticationManager getAuthenticationManager() {
+        return IsisContext.getAuthenticationManager();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerNoop.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerNoop.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerNoop.java
new file mode 100644
index 0000000..7b2ddc9
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/IsisViewerNoop.java
@@ -0,0 +1,54 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer;
+
+import org.apache.isis.core.commons.components.Noop;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilder;
+import org.apache.isis.runtimes.dflt.runtime.systemdependencyinjector.SystemDependencyInjector;
+import org.apache.isis.runtimes.dflt.runtime.viewer.web.WebAppSpecification;
+
+public class IsisViewerNoop implements IsisViewer, Noop {
+
+    @Override
+    public void init() {
+    }
+
+    @Override
+    public void shutdown() {
+    }
+
+    @Override
+    public void setConfigurationBuilder(final IsisConfigurationBuilder configurationLoader) {
+    }
+
+    @Override
+    public void setSystemDependencyInjector(final SystemDependencyInjector dependencyInjector) {
+    }
+
+    public boolean bootstrapsSystem() {
+        return false;
+    }
+
+    @Override
+    public WebAppSpecification getWebAppSpecification() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/package-info.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/package-info.java
new file mode 100644
index 0000000..45a9a7a
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/package-info.java
@@ -0,0 +1,23 @@
+/*
+ *  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.
+ */
+
+/**
+ * Viewer API.
+ */
+package org.apache.isis.runtimes.dflt.runtime.viewer;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/AbstractServletOrFilterMapping.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/AbstractServletOrFilterMapping.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/AbstractServletOrFilterMapping.java
new file mode 100644
index 0000000..6426899
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/AbstractServletOrFilterMapping.java
@@ -0,0 +1,56 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer.web;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AbstractServletOrFilterMapping {
+    private final Class<?> servletOrFilterClass;
+    private final List<String> pathSpecs;
+    private final Map<String, String> initParams;
+
+    @SuppressWarnings("unchecked")
+    public AbstractServletOrFilterMapping(final Class<?> servletOrFilterClass, final String... pathSpecs) {
+        this(servletOrFilterClass, Collections.EMPTY_MAP, pathSpecs);
+    }
+
+    public AbstractServletOrFilterMapping(final Class<?> servletOrFilterClass, final Map<String, String> initParams, final String... pathSpecs) {
+        this.servletOrFilterClass = servletOrFilterClass;
+        this.initParams = initParams;
+        this.pathSpecs = new ArrayList<String>(Arrays.asList(pathSpecs));
+    }
+
+    protected Class<?> getServletOrFilterClass() {
+        return servletOrFilterClass;
+    }
+
+    public Map<String, String> getInitParams() {
+        return Collections.unmodifiableMap(initParams);
+    }
+
+    public List<String> getPathSpecs() {
+        return Collections.unmodifiableList(pathSpecs);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/FilterSpecification.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/FilterSpecification.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/FilterSpecification.java
new file mode 100644
index 0000000..f51c732
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/FilterSpecification.java
@@ -0,0 +1,46 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer.web;
+
+import java.util.Map;
+
+public final class FilterSpecification extends AbstractServletOrFilterMapping {
+
+    /**
+     * @param filterClass
+     *            - should extend <tt>javax.servlet.Filter</tt>
+     */
+    public FilterSpecification(final Class<?> filterClass, final Map<String, String> initParams, final String... mappings) {
+        super(filterClass, initParams, mappings);
+    }
+
+    /**
+     * @param filterClass
+     *            - should extend <tt>javax.servlet.Filter</tt>
+     */
+    public FilterSpecification(final Class<?> filterClass, final String... pathSpecs) {
+        super(filterClass, pathSpecs);
+    }
+
+    public Class<?> getFilterClass() {
+        return getServletOrFilterClass();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/ServletSpecification.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/ServletSpecification.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/ServletSpecification.java
new file mode 100644
index 0000000..0a1dac6
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/ServletSpecification.java
@@ -0,0 +1,46 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer.web;
+
+import java.util.Map;
+
+public final class ServletSpecification extends AbstractServletOrFilterMapping {
+
+    /**
+     * @param servletClass
+     *            - should extend <tt>javax.servlet.Servlet</tt>
+     */
+    public ServletSpecification(final Class<?> servletClass, final Map<String, String> initParams, final String... mappings) {
+        super(servletClass, initParams, mappings);
+    }
+
+    /**
+     * @param servletClass
+     *            - should extend <tt>javax.servlet.Servlet</tt>
+     */
+    public ServletSpecification(final Class<?> servletClass, final String... pathSpecs) {
+        super(servletClass, pathSpecs);
+    }
+
+    public Class<?> getServletClass() {
+        return getServletOrFilterClass();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/WebAppSpecification.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/WebAppSpecification.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/WebAppSpecification.java
new file mode 100644
index 0000000..b00a56d
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/viewer/web/WebAppSpecification.java
@@ -0,0 +1,135 @@
+/*
+ *  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.runtimes.dflt.runtime.viewer.web;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.isis.core.commons.lang.MapUtils;
+
+/**
+ * Defines what servlets, mappings etc are required from an embedded web server.
+ */
+public final class WebAppSpecification {
+
+    private Map<String, String> contextParams = new LinkedHashMap<String, String>();
+    private final List<Class<?>> servletContextListeners = new ArrayList<Class<?>>();
+    private final List<ServletSpecification> servletSpecifications = new ArrayList<ServletSpecification>();
+    private final List<FilterSpecification> filterSpecifications = new ArrayList<FilterSpecification>();
+    private final List<String> resourcePaths = new ArrayList<String>();
+    private final List<String> welcomeFiles = new ArrayList<String>();
+    private String logHint;
+
+    // ///////////////////////////////////////////////////////////
+    // Context Params
+    // ///////////////////////////////////////////////////////////
+
+    public void addContextParams(final String... contextParams) {
+        this.contextParams = MapUtils.asMap(contextParams);
+    }
+
+    public Map<String, String> getContextParams() {
+        return Collections.unmodifiableMap(contextParams);
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Servlet Context Listeners
+    // ///////////////////////////////////////////////////////////
+
+    public void addServletContextListener(final Class<?> servletContextListenerClass) {
+        servletContextListeners.add(servletContextListenerClass);
+    }
+
+    public List<Class<?>> getServletContextListeners() {
+        return servletContextListeners;
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Servlet Mappings
+    // ///////////////////////////////////////////////////////////
+
+    public void addServletSpecification(final Class<?> servletClass, final String... pathSpecs) {
+        servletSpecifications.add(new ServletSpecification(servletClass, pathSpecs));
+    }
+
+    public void addServletSpecification(final Class<?> servletClass, final Map<String, String> initParams, final String... pathSpecs) {
+        servletSpecifications.add(new ServletSpecification(servletClass, initParams, pathSpecs));
+    }
+
+    public List<ServletSpecification> getServletSpecifications() {
+        return servletSpecifications;
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Filter Mappings
+    // ///////////////////////////////////////////////////////////
+
+    public void addFilterSpecification(final Class<?> filterClass, final String... pathSpecs) {
+        filterSpecifications.add(new FilterSpecification(filterClass, pathSpecs));
+    }
+
+    public void addFilterSpecification(final Class<?> filterClass, final Map<String, String> initParams, final String... pathSpecs) {
+        filterSpecifications.add(new FilterSpecification(filterClass, initParams, pathSpecs));
+    }
+
+    public List<FilterSpecification> getFilterSpecifications() {
+        return filterSpecifications;
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Resources
+    // ///////////////////////////////////////////////////////////
+
+    public void addResourcePath(final String path) {
+        resourcePaths.add(path);
+    }
+
+    public List<String> getResourcePaths() {
+        return resourcePaths;
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Welcome Files
+    // ///////////////////////////////////////////////////////////
+
+    public void addWelcomeFile(final String path) {
+        welcomeFiles.add(path);
+    }
+
+    public List<String> getWelcomeFiles() {
+        return welcomeFiles;
+    }
+
+    // ///////////////////////////////////////////////////////////
+    // Candifloss
+    // ///////////////////////////////////////////////////////////
+
+    public String getLogHint() {
+        return logHint;
+    }
+
+    public void setLogHint(final String logHint) {
+        this.logHint = logHint;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServer.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServer.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServer.java
new file mode 100644
index 0000000..74b7912
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServer.java
@@ -0,0 +1,29 @@
+/*
+ *  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.runtimes.dflt.runtime.web;
+
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.runtimes.dflt.runtime.viewer.web.WebAppSpecification;
+
+public interface EmbeddedWebServer extends ApplicationScopedComponent {
+
+    void addWebAppSpecification(WebAppSpecification webContainerRequirements);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServerAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServerAbstract.java
new file mode 100644
index 0000000..fd9a0bb
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebServerAbstract.java
@@ -0,0 +1,76 @@
+/*
+ *  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.runtimes.dflt.runtime.web;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.viewer.web.WebAppSpecification;
+
+public abstract class EmbeddedWebServerAbstract implements EmbeddedWebServer {
+
+    @SuppressWarnings("unused")
+    private final static Logger LOG = Logger.getLogger(EmbeddedWebServerAbstract.class);
+
+    private final List<WebAppSpecification> specifications = new ArrayList<WebAppSpecification>();
+
+    // ///////////////////////////////////////////////////////
+    // WebApp Specifications
+    // ///////////////////////////////////////////////////////
+
+    /**
+     * Must be called prior to {@link #init() initialization}.
+     */
+    @Override
+    public void addWebAppSpecification(final WebAppSpecification specification) {
+        specifications.add(specification);
+    }
+
+    protected List<WebAppSpecification> getSpecifications() {
+        return specifications;
+    }
+
+    // ///////////////////////////////////////////////////////
+    // init, shutdown
+    // ///////////////////////////////////////////////////////
+
+    @Override
+    public void init() {
+        // does nothing
+    }
+
+    @Override
+    public void shutdown() {
+        // does nothing
+    }
+
+    // ///////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // ///////////////////////////////////////////////////////
+
+    protected static IsisConfiguration getConfiguration() {
+        return IsisContext.getConfiguration();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebViewer.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebViewer.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebViewer.java
new file mode 100644
index 0000000..2432c50
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/web/EmbeddedWebViewer.java
@@ -0,0 +1,26 @@
+/*
+ *  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.runtimes.dflt.runtime.web;
+
+import org.apache.isis.runtimes.dflt.runtime.viewer.IsisViewerAbstract;
+
+public abstract class EmbeddedWebViewer extends IsisViewerAbstract {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisSessionFilter.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisSessionFilter.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisSessionFilter.java
new file mode 100644
index 0000000..1ef61ab
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisSessionFilter.java
@@ -0,0 +1,407 @@
+/*
+ *  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.runtimes.dflt.webapp;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.commons.lang.PathUtils;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.webapp.content.ResourceCachingFilter;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.webapp.auth.AuthenticationSessionStrategy;
+import org.apache.isis.runtimes.dflt.webapp.auth.AuthenticationSessionStrategyDefault;
+
+public class IsisSessionFilter implements Filter {
+
+    /**
+     * Recommended standard init parameter key for filters and servlets to
+     * lookup an implementation of {@link AuthenticationSessionStrategy}.
+     */
+    public static final String AUTHENTICATION_SESSION_STRATEGY_KEY = "authenticationSessionStrategy";
+
+    /**
+     * Default value for
+     * {@link AuthenticationSessionLookupStrategyConstants#AUTHENTICATION_SESSION_STRATEGY_KEY}
+     * if not specified.
+     */
+    public static final String AUTHENTICATION_SESSION_STRATEGY_DEFAULT = AuthenticationSessionStrategyDefault.class.getName();
+
+    /**
+     * Init parameter key for backward compatibility; if logonPage set then
+     * assume 'restricted' handling.
+     */
+    public static final String LOGON_PAGE_KEY = "logonPage";
+
+    /**
+     * Init parameter key for what should be done if no session was found.
+     * 
+     * <p>
+     * Valid values are:
+     * <ul>
+     * <li>unauthorized - issue a 401 response.
+     * <li>basicAuthChallenge - issue a basic auth 401 challenge. The idea here
+     * is that the configured logon strategy should handle the next request
+     * <li>restricted - allow access but only to a restricted (comma-separated)
+     * list of paths. Access elsewhere should be redirected to the first of
+     * these paths
+     * <li>continue - allow the request to continue (eg if there is no security
+     * requirements)
+     * </ul>
+     */
+    public static final String WHEN_NO_SESSION_KEY = "whenNoSession";
+
+    /**
+     * Init parameter key to read the restricted list of paths (if
+     * {@link #WHEN_NO_SESSION_KEY} is for {@link WhenNoSession#RESTRICTED}).
+     * 
+     * <p>
+     * The servlets mapped to these paths are expected to be able to deal with
+     * there being no session. Typically they will be logon pages.
+     */
+    public static final String RESTRICTED_KEY = "restricted";
+
+    /**
+     * Init parameter key to redirect to if an exception occurs.
+     */
+    public static final String REDIRECT_TO_ON_EXCEPTION_KEY = "redirectToOnException";
+
+    /**
+     * Init parameter key for which extensions should be ignored (typically,
+     * mappings for other viewers within the webapp context).
+     * 
+     * <p>
+     * It can also be used to specify ignored static resources (though putting
+     * the {@link ResourceCachingFilter} first in the <tt>web.xml</tt>
+     * accomplishes the same thing).
+     * 
+     * <p>
+     * The value is expected as a comma separated list, for example:
+     * 
+     * <pre>
+     * htmlviewer
+     * </pre>
+     */
+    public static final String IGNORE_EXTENSIONS_KEY = "ignoreExtensions";
+
+    private static final Function<String, Pattern> STRING_TO_PATTERN = new Function<String, Pattern>() {
+        @Override
+        public Pattern apply(final String input) {
+            return Pattern.compile(".*\\." + input);
+        }
+
+    };
+
+    static void redirect(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final String redirectTo) throws IOException {
+        httpResponse.sendRedirect(PathUtils.combine(httpRequest.getContextPath(), redirectTo));
+    }
+
+    public enum WhenNoSession {
+        UNAUTHORIZED("unauthorized") {
+            @Override
+            public void handle(final IsisSessionFilter filter, final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final FilterChain chain) throws IOException, ServletException {
+                httpResponse.sendError(401);
+            }
+        },
+        BASIC_AUTH_CHALLENGE("basicAuthChallenge") {
+            @Override
+            public void handle(final IsisSessionFilter filter, final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final FilterChain chain) throws IOException, ServletException {
+                httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"Apache Isis\"");
+                httpResponse.sendError(401);
+            }
+        },
+        /**
+         * the destination servlet is expected to know that there will be no
+         * open context
+         */
+        CONTINUE("continue") {
+            @Override
+            public void handle(final IsisSessionFilter filter, final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final FilterChain chain) throws IOException, ServletException {
+                chain.doFilter(httpRequest, httpResponse);
+            }
+        },
+        /**
+         * Allow access to a restricted list of URLs (else redirect to the first
+         * of that list of URLs)
+         */
+        RESTRICTED("restricted") {
+            @Override
+            public void handle(final IsisSessionFilter filter, final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final FilterChain chain) throws IOException, ServletException {
+
+                if (filter.restrictedPaths.contains(httpRequest.getServletPath())) {
+                    chain.doFilter(httpRequest, httpResponse);
+                    return;
+                }
+                redirect(httpRequest, httpResponse, filter.restrictedPaths.get(0));
+            }
+
+        };
+        private final String initParamValue;
+
+        private WhenNoSession(final String initParamValue) {
+            this.initParamValue = initParamValue;
+        }
+
+        public static WhenNoSession lookup(final String whenNoSessionStr) {
+            for (final WhenNoSession wns : values()) {
+                if (wns.initParamValue.equals(whenNoSessionStr)) {
+                    return wns;
+                }
+            }
+            throw new IllegalStateException("require an init-param of '" + WHEN_NO_SESSION_KEY + "', taking a value of " + WhenNoSession.values());
+        }
+
+        public abstract void handle(IsisSessionFilter filter, HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain chain) throws IOException, ServletException;
+    }
+
+    /**
+     * Used as a flag on {@link HttpServletRequest} so that if there are two
+     * {@link IsisSessionFilter}s in a request pipeline, then the second can
+     * determine what processing has already been done (and is usually then just
+     * a no-op).
+     */
+    private static final String SESSION_STATE_KEY = IsisSessionFilter.SessionState.class.getName();
+
+    private AuthenticationSessionStrategy authSessionStrategy;
+    private List<String> restrictedPaths;
+    private WhenNoSession whenNoSession;
+    private String redirectToOnException;
+    private Collection<Pattern> ignoreExtensions;
+
+    // /////////////////////////////////////////////////////////////////
+    // init, destroy
+    // /////////////////////////////////////////////////////////////////
+
+    @Override
+    public void init(final FilterConfig config) throws ServletException {
+        authSessionStrategy = lookup(config.getInitParameter(AUTHENTICATION_SESSION_STRATEGY_KEY));
+        lookupWhenNoSession(config);
+        lookupRedirectToOnException(config);
+        lookupIgnoreExtensions(config);
+    }
+
+    /**
+     * Public visibility so can also be used by servlets.
+     */
+    public static AuthenticationSessionStrategy lookup(String authLookupStrategyClassName) {
+        if (authLookupStrategyClassName == null) {
+            authLookupStrategyClassName = AUTHENTICATION_SESSION_STRATEGY_DEFAULT;
+        }
+        return (AuthenticationSessionStrategy) InstanceUtil.createInstance(authLookupStrategyClassName);
+    }
+
+    private void lookupWhenNoSession(final FilterConfig config) {
+
+        final String whenNoSessionStr = config.getInitParameter(WHEN_NO_SESSION_KEY);
+
+        // backward compatibility
+        final String logonPage = config.getInitParameter(LOGON_PAGE_KEY);
+        if (logonPage != null) {
+            if (whenNoSessionStr != null) {
+                throw new IllegalStateException("The init-param '" + LOGON_PAGE_KEY + "' is only provided for backwards compatibility; remove if the init-param '" + WHEN_NO_SESSION_KEY + "' has been specified");
+            }
+            whenNoSession = WhenNoSession.RESTRICTED;
+            this.restrictedPaths = Lists.newArrayList(logonPage);
+            return;
+        }
+
+        whenNoSession = WhenNoSession.lookup(whenNoSessionStr);
+        if (whenNoSession == WhenNoSession.RESTRICTED) {
+            final String restrictedPathsStr = config.getInitParameter(RESTRICTED_KEY);
+            if (restrictedPathsStr == null) {
+                throw new IllegalStateException("Require an init-param of '" + RESTRICTED_KEY + "' key to be set.");
+            }
+            this.restrictedPaths = Lists.newArrayList(Splitter.on(",").split(restrictedPathsStr));
+        }
+
+    }
+
+    private void lookupRedirectToOnException(final FilterConfig config) {
+        redirectToOnException = config.getInitParameter(REDIRECT_TO_ON_EXCEPTION_KEY);
+    }
+
+    private void lookupIgnoreExtensions(final FilterConfig config) {
+        ignoreExtensions = Collections.unmodifiableCollection(parseIgnorePatterns(config));
+    }
+
+    private Collection<Pattern> parseIgnorePatterns(final FilterConfig config) {
+        final String ignoreExtensionsStr = config.getInitParameter(IGNORE_EXTENSIONS_KEY);
+        if (ignoreExtensionsStr != null) {
+            final List<String> ignoreExtensions = Lists.newArrayList(Splitter.on(",").split(ignoreExtensionsStr));
+            return Collections2.transform(ignoreExtensions, STRING_TO_PATTERN);
+        }
+        return Lists.newArrayList();
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    // /////////////////////////////////////////////////////////////////
+    // doFilter
+    // /////////////////////////////////////////////////////////////////
+
+    public enum SessionState {
+
+        UNDEFINED {
+            @Override
+            public void handle(final IsisSessionFilter filter, final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+
+                final HttpServletRequest httpRequest = (HttpServletRequest) request;
+                final HttpServletResponse httpResponse = (HttpServletResponse) response;
+
+                if (requestIsIgnoreExtension(filter, httpRequest)) {
+                    try {
+                        chain.doFilter(request, response);
+                        return;
+                    } finally {
+                        closeSession();
+                    }
+                }
+
+                if (ResourceCachingFilter.isCachedResource(httpRequest)) {
+                    try {
+                        chain.doFilter(request, response);
+                        return;
+                    } finally {
+                        closeSession();
+                    }
+                }
+
+                // authenticate
+                final AuthenticationSession validSession = filter.authSessionStrategy.lookupValid(request, response);
+                if (validSession != null) {
+                    filter.authSessionStrategy.bind(request, response, validSession);
+
+                    openSession(validSession);
+                    SESSION_IN_PROGRESS.setOn(request);
+                    try {
+                        chain.doFilter(request, response);
+                    } finally {
+                        UNDEFINED.setOn(request);
+                        closeSession();
+                    }
+                    return;
+                }
+
+                try {
+                    NO_SESSION_SINCE_NOT_AUTHENTICATED.setOn(request);
+                    filter.whenNoSession.handle(filter, httpRequest, httpResponse, chain);
+                } catch (final RuntimeException ex) {
+                    // in case the destination servlet cannot cope, but we've
+                    // been told
+                    // to redirect elsewhere
+                    if (filter.redirectToOnException != null) {
+                        redirect(httpRequest, httpResponse, filter.redirectToOnException);
+                        return;
+                    }
+                    throw ex;
+                } catch (final IOException ex) {
+                    if (filter.redirectToOnException != null) {
+                        redirect(httpRequest, httpResponse, filter.redirectToOnException);
+                        return;
+                    }
+                    throw ex;
+                } catch (final ServletException ex) {
+                    // in case the destination servlet cannot cope, but we've
+                    // been told
+                    // to redirect elsewhere
+                    if (filter.redirectToOnException != null) {
+                        redirect(httpRequest, httpResponse, filter.redirectToOnException);
+                        return;
+                    }
+                    throw ex;
+                } finally {
+                    UNDEFINED.setOn(request);
+                    // nothing to do
+                }
+
+            }
+
+            private boolean requestIsIgnoreExtension(final IsisSessionFilter filter, final HttpServletRequest httpRequest) {
+                final String servletPath = httpRequest.getServletPath();
+                for (final Pattern extension : filter.ignoreExtensions) {
+                    if (extension.matcher(servletPath).matches()) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        },
+        NO_SESSION_SINCE_REDIRECTING_TO_LOGON_PAGE, NO_SESSION_SINCE_NOT_AUTHENTICATED, SESSION_IN_PROGRESS;
+
+        static SessionState lookup(final ServletRequest request) {
+            final Object state = request.getAttribute(SESSION_STATE_KEY);
+            return state != null ? (SessionState) state : SessionState.UNDEFINED;
+        }
+
+        boolean isValid(final AuthenticationSession authSession) {
+            return authSession != null && getAuthenticationManager().isSessionValid(authSession);
+        }
+
+        void setOn(final ServletRequest request) {
+            request.setAttribute(SESSION_STATE_KEY, this);
+        }
+
+        public void handle(final IsisSessionFilter filter, final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+            chain.doFilter(request, response);
+        }
+
+        AuthenticationManager getAuthenticationManager() {
+            return IsisContext.getAuthenticationManager();
+        }
+
+        void openSession(final AuthenticationSession authSession) {
+            IsisContext.openSession(authSession);
+        }
+
+        void closeSession() {
+            IsisContext.closeSession();
+        }
+
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+
+        final SessionState sessionState = SessionState.lookup(request);
+        sessionState.handle(this, request, response, chain);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisWebAppBootstrapper.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisWebAppBootstrapper.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisWebAppBootstrapper.java
new file mode 100644
index 0000000..ebcbc82
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/IsisWebAppBootstrapper.java
@@ -0,0 +1,217 @@
+/*
+ *  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.runtimes.dflt.webapp;
+
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.IsisConfigurationBuilder;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderPrimer;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderResourceStreams;
+import org.apache.isis.core.commons.config.NotFoundPolicy;
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceComposite;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceContextLoaderClassPath;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
+import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;
+import org.apache.isis.core.webapp.config.ResourceStreamSourceForWebInf;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookup;
+import org.apache.isis.runtimes.dflt.runtime.installers.InstallerLookupDefault;
+import org.apache.isis.runtimes.dflt.runtime.runner.IsisModule;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.IsisSystem;
+import org.apache.isis.runtimes.dflt.runtime.system.SystemConstants;
+
+/**
+ * Initialize the {@link IsisSystem} when the web application starts, and
+ * destroys it when it ends.
+ * <p>
+ * Implementation note: we use a number of helper builders to keep this class as
+ * small and focused as possible. The builders are available for reuse by other
+ * bootstrappers.
+ */
+public class IsisWebAppBootstrapper implements ServletContextListener {
+
+    private static final Logger LOG = Logger.getLogger(IsisWebAppBootstrapper.class);
+    private final IsisLoggingConfigurer loggingConfigurer = new IsisLoggingConfigurer();
+    private Injector injector;
+
+    /**
+     * Convenience for servlets that need to obtain the {@link IsisSystem}.
+     */
+    public static IsisSystem getSystemBoundTo(final ServletContext servletContext) {
+        final Object system = servletContext.getAttribute(WebAppConstants.ISIS_SYSTEM_KEY);
+        return (IsisSystem) system;
+    }
+
+    // /////////////////////////////////////////////////////
+    // Initialization
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void contextInitialized(final ServletContextEvent servletContextEvent) {
+        try {
+            final ServletContext servletContext = servletContextEvent.getServletContext();
+
+            final String webappDir = servletContext.getRealPath("/");
+            final String webInfDir = servletContext.getRealPath("/WEB-INF");
+            loggingConfigurer.configureLogging(webInfDir, new String[0]);
+
+            String configLocation = servletContext.getInitParameter(WebAppConstants.CONFIG_DIR_PARAM);
+            ResourceStreamSourceComposite compositeSource = null;
+            if ( configLocation == null ) {
+              LOG.info( "Config override location: No override location configured!" );
+              compositeSource = new ResourceStreamSourceComposite(ResourceStreamSourceContextLoaderClassPath.create(), new ResourceStreamSourceForWebInf(servletContext));
+            } else {
+              LOG.info( "Config override location: " + configLocation );
+              ResourceStreamSource configSourceStream = ResourceStreamSourceFileSystem.create(configLocation);
+              compositeSource = new ResourceStreamSourceComposite(ResourceStreamSourceContextLoaderClassPath.create(), new ResourceStreamSourceForWebInf(servletContext), configSourceStream);
+            }
+            // will load either from WEB-INF, from the classpath or from config directory.
+            final IsisConfigurationBuilder isisConfigurationBuilder = new IsisConfigurationBuilderResourceStreams(compositeSource);
+
+            primeConfigurationBuilder(isisConfigurationBuilder, servletContext);
+
+            final DeploymentType deploymentType = determineDeploymentType(isisConfigurationBuilder, servletContext);
+
+            addConfigurationResourcesForWebApps(isisConfigurationBuilder);
+            addConfigurationResourcesForDeploymentType(isisConfigurationBuilder, deploymentType);
+            addConfigurationResourcesForViewers(isisConfigurationBuilder, servletContext);
+
+            isisConfigurationBuilder.add(WebAppConstants.WEB_APP_DIR, webappDir);
+            isisConfigurationBuilder.add(SystemConstants.NOSPLASH_KEY, "true");
+
+            final InstallerLookup installerLookup = new InstallerLookupDefault();
+
+            injector = createGuiceInjector(isisConfigurationBuilder, deploymentType, installerLookup);
+
+            final IsisSystem system = injector.getInstance(IsisSystem.class);
+            
+            isisConfigurationBuilder.dumpResourcesToLog();
+
+            servletContext.setAttribute(WebAppConstants.ISIS_SYSTEM_KEY, system);
+        } catch (final RuntimeException e) {
+            LOG.error("startup failed", e);
+            throw e;
+        }
+        LOG.info("server started");
+    }
+
+    private Injector createGuiceInjector(final IsisConfigurationBuilder isisConfigurationBuilder, final DeploymentType deploymentType, final InstallerLookup installerLookup) {
+        final IsisModule isisModule = new IsisModule(deploymentType, isisConfigurationBuilder, installerLookup);
+        return Guice.createInjector(isisModule);
+    }
+
+    @SuppressWarnings("unchecked")
+    private void primeConfigurationBuilder(final IsisConfigurationBuilder isisConfigurationBuilder, final ServletContext servletContext) {
+        final List<IsisConfigurationBuilderPrimer> isisConfigurationBuilderPrimers = (List<IsisConfigurationBuilderPrimer>) servletContext.getAttribute(WebAppConstants.CONFIGURATION_PRIMERS_KEY);
+        if (isisConfigurationBuilderPrimers == null) {
+            return;
+        }
+        for (final IsisConfigurationBuilderPrimer isisConfigurationBuilderPrimer : isisConfigurationBuilderPrimers) {
+            isisConfigurationBuilderPrimer.primeConfigurationBuilder(isisConfigurationBuilder);
+        }
+    }
+
+    /**
+     * Checks {@link IsisConfigurationBuilder configuration} for
+     * {@value SystemConstants#DEPLOYMENT_TYPE_KEY}, (that is, from the command
+     * line), but otherwise searches in the {@link ServletContext}, first for
+     * {@value WebAppConstants#DEPLOYMENT_TYPE_KEY} and also
+     * {@value SystemConstants#DEPLOYMENT_TYPE_KEY}.
+     * <p>
+     * If no setting is found, defaults to
+     * {@value WebAppConstants#DEPLOYMENT_TYPE_DEFAULT}.
+     */
+    private DeploymentType determineDeploymentType(final IsisConfigurationBuilder isisConfigurationBuilder, final ServletContext servletContext) {
+        String deploymentTypeStr = null;
+        if (deploymentTypeStr == null) {
+            deploymentTypeStr = servletContext.getInitParameter(WebAppConstants.DEPLOYMENT_TYPE_KEY);
+        }
+        if (deploymentTypeStr == null) {
+            deploymentTypeStr = servletContext.getInitParameter(SystemConstants.DEPLOYMENT_TYPE_KEY);
+        }
+        if (deploymentTypeStr == null) {
+            deploymentTypeStr = isisConfigurationBuilder.getConfiguration().getString(SystemConstants.DEPLOYMENT_TYPE_KEY);
+        }
+        if (deploymentTypeStr == null) {
+            deploymentTypeStr = WebAppConstants.DEPLOYMENT_TYPE_DEFAULT;
+        }
+        return DeploymentType.lookup(deploymentTypeStr);
+    }
+
+    private void addConfigurationResourcesForDeploymentType(final IsisConfigurationBuilder configurationLoader, final DeploymentType deploymentType) {
+        final String type = deploymentType.name().toLowerCase();
+        configurationLoader.addConfigurationResource(type + ".properties", NotFoundPolicy.CONTINUE);
+    }
+
+    private void addConfigurationResourcesForWebApps(final IsisConfigurationBuilder configurationLoader) {
+        for (final String config : (new String[] { "web.properties", "war.properties" })) {
+            if (config != null) {
+                configurationLoader.addConfigurationResource(config, NotFoundPolicy.CONTINUE);
+            }
+        }
+    }
+
+    private void addConfigurationResourcesForViewers(final IsisConfigurationBuilder configurationLoader, final ServletContext servletContext) {
+        addConfigurationResourcesForContextParam(configurationLoader, servletContext, "isis.viewers");
+        addConfigurationResourcesForContextParam(configurationLoader, servletContext, "isis.viewer");
+    }
+
+    private void addConfigurationResourcesForContextParam(final IsisConfigurationBuilder configurationLoader, final ServletContext servletContext, final String name) {
+        final String viewers = servletContext.getInitParameter(name);
+        if (viewers == null) {
+            return;
+        }
+        for (final String viewer : viewers.split(",")) {
+            configurationLoader.addConfigurationResource("viewer_" + viewer + ".properties", NotFoundPolicy.CONTINUE);
+        }
+    }
+
+    // /////////////////////////////////////////////////////
+    // Destroy
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent ev) {
+        LOG.info("server shutting down");
+        final ServletContext servletContext = ev.getServletContext();
+
+        try {
+            final IsisSystem system = (IsisSystem) servletContext.getAttribute(WebAppConstants.ISIS_SYSTEM_KEY);
+            if (system != null) {
+                LOG.info("calling system shutdown");
+                system.shutdown();
+            }
+        } finally {
+            servletContext.removeAttribute(WebAppConstants.ISIS_SYSTEM_KEY);
+            LOG.info("server shut down");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/WebAppConstants.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/WebAppConstants.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/WebAppConstants.java
new file mode 100644
index 0000000..0cb07ce
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/WebAppConstants.java
@@ -0,0 +1,85 @@
+/*
+ *  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.runtimes.dflt.webapp;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.IsisConfigurationBuilderPrimer;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.IsisSystem;
+
+public final class WebAppConstants {
+
+    /**
+     * Name of context-param (<tt>ServletContext#getInitParameter(String)</tt>)
+     * to specify the deployment type.
+     */
+    public static final String DEPLOYMENT_TYPE_KEY = "deploymentType";
+    /**
+     * Deployment type to use if there is none {@link DEPLOYMENT_TYPE_KEY
+     * specified}.
+     */
+    public static final String DEPLOYMENT_TYPE_DEFAULT = DeploymentType.SERVER.name();
+
+    /**
+     * Key under which the list of {@link IsisConfigurationBuilderPrimer}s is
+     * bound as a servlet context attribute (
+     * <tt>ServletContext#getAttribute(String)</tt>); used to pass from the
+     * <tt>webserver</tt> module to this.
+     */
+    public static final String CONFIGURATION_PRIMERS_KEY = "isis.configurationPrimers";
+
+    /**
+     * Key under which the {@link IsisSystem} is bound as a servlet context
+     * attribute ( <tt>ServletContext#getAttribute(String)</tt>).
+     */
+    public final static String ISIS_SYSTEM_KEY = WebAppConstants.class.getPackage().getName() + ".isisSystem";
+
+    /**
+     * Key under which the {@link AuthenticationSession} is bound as a session
+     * attribute ( <tt>HttpSession#getAttribute(String)</tt>).
+     */
+    public final static String HTTP_SESSION_AUTHENTICATION_SESSION_KEY = WebAppConstants.class.getPackage().getName() + ".authenticationSession";
+
+    /**
+     * Key used to determine if a logon has already been performed implicitly
+     * using the {@link LogonFixture}, meaning that a Logout should be followed
+     * by the Logon page.
+     */
+    public final static String HTTP_SESSION_LOGGED_ON_PREVIOUSLY_USING_LOGON_FIXTURE_KEY = WebAppConstants.class.getPackage().getName() + ".loggedOnPreviouslyUsingLogonFixture";
+
+    /**
+     * Property name given to the web app directory.
+     */
+    public static final String WEB_APP_DIR = "application.webapp.dir";
+
+    /**
+     * Servlet context parameter name used to specify the location for property file 
+     * overloads. Property files in this location take precendence over property files 
+     * in other locations. Since the ResourceStreamSourceComposite is being used
+     * property files from various locations are merged together. So only overloaded
+     * properties (entries in the file) need to present.
+     */
+    public static final String CONFIG_DIR_PARAM = "isis.config.dir";
+
+    private WebAppConstants() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategy.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategy.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategy.java
new file mode 100644
index 0000000..9719c92
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategy.java
@@ -0,0 +1,43 @@
+/*
+ *  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.runtimes.dflt.webapp.auth;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.runtimes.dflt.webapp.IsisSessionFilter;
+
+/**
+ * Decouples the {@link IsisSessionFilter} from the mechanism of obtaining the
+ * {@link AuthenticationSession}.
+ */
+public interface AuthenticationSessionStrategy {
+
+    /**
+     * Returns a
+     * {@link AuthenticationManager#isSessionValid(AuthenticationSession)
+     * still-valid} {@link AuthenticationSession}.
+     */
+    AuthenticationSession lookupValid(ServletRequest servletRequest, ServletResponse servletResponse);
+
+    void bind(ServletRequest servletRequest, ServletResponse servletResponse, AuthenticationSession authSession);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategyAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategyAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategyAbstract.java
new file mode 100644
index 0000000..4d68958
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/webapp/auth/AuthenticationSessionStrategyAbstract.java
@@ -0,0 +1,46 @@
+/*
+ *  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.runtimes.dflt.webapp.auth;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+
+public abstract class AuthenticationSessionStrategyAbstract implements AuthenticationSessionStrategy {
+
+    protected HttpSession getHttpSession(final ServletRequest servletRequest) {
+        final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
+        return httpServletRequest.getSession();
+    }
+
+    protected ServletContext getServletContext(final ServletRequest servletRequest) {
+        final HttpSession httpSession = getHttpSession(servletRequest);
+        return httpSession.getServletContext();
+    }
+
+    @Override
+    public void bind(final ServletRequest servletRequest, final ServletResponse servletResponse, final AuthenticationSession authSession) {
+        // no-op
+    }
+
+}