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 2013/03/28 11:35:30 UTC

[06/20] ISIS-381: mothballing HTML viewer, SQL security, LDAP security

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectHistory.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectHistory.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectHistory.java
new file mode 100644
index 0000000..9dfa7cc
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectHistory.java
@@ -0,0 +1,109 @@
+/*
+ *  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.context;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.exceptions.UnknownTypeException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.html.component.Block;
+import org.apache.isis.viewer.html.component.Component;
+
+public class ObjectHistory implements Iterable<HistoryEntry> {
+
+    private static final Logger LOG = Logger.getLogger(ObjectHistory.class);
+    private static final int MAX = 8;
+    private final List<HistoryEntry> history = new ArrayList<HistoryEntry>();
+
+    private void add(final HistoryEntry entry) {
+        history.remove(entry);
+        history.add(entry);
+        LOG.debug("added to history: " + entry);
+        if (history.size() > MAX) {
+            LOG.debug("purging from history: " + history.get(0));
+            history.remove(0);
+        }
+    }
+
+    public void debug(final DebugBuilder debug) {
+        for (int i = history.size() - 1; i >= 0; i--) {
+            final HistoryEntry object = history.get(i);
+            debug.appendln(object.toString());
+        }
+    }
+
+    public void listObjects(final Context context, final Block navigation) {
+        final Block taskBar = context.getComponentFactory().createBlock("history", null);
+        taskBar.add(context.getComponentFactory().createHeading("History"));
+        for (int i = history.size() - 1; i >= 0; i--) {
+            try {
+                final HistoryEntry item = history.get(i);
+                Component icon;
+                if (item.type == HistoryEntry.OBJECT) {
+                    final ObjectAdapter object = context.getMappedObject(item.id);
+
+                    IsisContext.getPersistenceSession().resolveImmediately(object);
+
+                    icon = context.getComponentFactory().createObjectIcon(object, item.id, "item");
+                } else if (item.type == HistoryEntry.COLLECTION) {
+                    final ObjectAdapter object = context.getMappedCollection(item.id);
+                    icon = context.getComponentFactory().createCollectionIcon(object, item.id);
+                } else {
+                    throw new UnknownTypeException(item);
+                }
+                taskBar.add(icon);
+            } catch (final IsisException e) { // Catch resolveImmediately
+                                              // exception when object is
+                                              // deleted.
+
+            }
+        }
+        navigation.add(taskBar);
+    }
+
+    public void addObject(final String idString) {
+        add(new HistoryEntry(idString, HistoryEntry.OBJECT));
+    }
+
+    public void addCollection(final String idString) {
+        add(new HistoryEntry(idString, HistoryEntry.COLLECTION));
+    }
+
+    public Iterator<HistoryEntry> iterator() {
+        return history.iterator();
+    }
+
+    public void remove(final String existingId) {
+        for (final HistoryEntry entry : history) {
+            if (entry.id.equals(existingId)) {
+                history.remove(entry);
+                break;
+            }
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectLookupException.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectLookupException.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectLookupException.java
new file mode 100644
index 0000000..5a616d1
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/ObjectLookupException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.context;
+
+import org.apache.isis.viewer.html.action.ActionException;
+
+public class ObjectLookupException extends ActionException {
+    private static final long serialVersionUID = 1L;
+
+    public ObjectLookupException() {
+    }
+
+    public ObjectLookupException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+
+    public ObjectLookupException(final String msg) {
+        super(msg);
+    }
+
+    public ObjectLookupException(final Throwable cause) {
+        super(cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/PersistentRootAdapterMapping.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/PersistentRootAdapterMapping.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/PersistentRootAdapterMapping.java
new file mode 100644
index 0000000..9ac5a4c
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/PersistentRootAdapterMapping.java
@@ -0,0 +1,119 @@
+/*
+ *  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.context;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+public class PersistentRootAdapterMapping extends RootAdapterMappingAbstract {
+    
+    private static final long serialVersionUID = 1L;
+    
+    private Version version;
+
+    public PersistentRootAdapterMapping(final ObjectAdapter adapter) {
+        super(adapter);
+        Assert.assertFalse("OID is for transient", adapter.getOid().isTransient());
+        Assert.assertFalse("adapter is for transient", adapter.isTransient());
+    }
+
+
+    // /////////////////////////////////////////////////////
+    // version
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public Version getVersion() {
+        return version;
+    }
+
+    @Override
+    public void checkVersion(final ObjectAdapter object) {
+        object.checkLock(getVersion());
+    }
+
+    @Override
+    public void updateVersion() {
+        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(getOid());
+        version = adapter.getVersion();
+    }
+
+
+    // /////////////////////////////////////////////////////
+    // restoreToLoader
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void restoreToLoader() {
+        final RootOidDefault oid = RootOidDefault.deString(getOidStr(), getOidMarshaller());
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(oid);
+        adapter.setVersion(getVersion());
+    }
+
+
+    // /////////////////////////////////////////////////////
+    // value semantics
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (!(obj instanceof PersistentRootAdapterMapping)) {
+            return false;
+        } 
+        return ((PersistentRootAdapterMapping) obj).getOidStr().equals(getOidStr());
+    }
+
+
+    // /////////////////////////////////////////////////////
+    // debugging, toString
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(getOidStr());
+        if (version != null) {
+            debug.appendln(version.toString());
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getOidStr() + " : " + version;
+    }
+
+    // /////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // /////////////////////////////////////////////////////
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMapping.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMapping.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMapping.java
new file mode 100644
index 0000000..d0a6bda
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMapping.java
@@ -0,0 +1,41 @@
+/*
+ *  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.context;
+
+import java.io.Serializable;
+
+import org.apache.isis.core.commons.debug.Debuggable;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+
+public interface RootAdapterMapping extends Serializable, Debuggable {
+
+    String getOidStr();
+
+    ObjectAdapter getObject();
+
+    Version getVersion();
+
+    void checkVersion(ObjectAdapter object);
+
+    void restoreToLoader();
+
+    void updateVersion();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMappingAbstract.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMappingAbstract.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMappingAbstract.java
new file mode 100644
index 0000000..0c7e1f3
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/RootAdapterMappingAbstract.java
@@ -0,0 +1,114 @@
+/*
+ *  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.context;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.Persistor;
+
+public abstract class RootAdapterMappingAbstract implements RootAdapterMapping {
+    
+    private static final long serialVersionUID = 1L;
+    
+    private final String oidStr;
+
+    public RootAdapterMappingAbstract(final ObjectAdapter adapter) {
+        final Oid oid = adapter.getOid();
+        oidStr = oid.enString(getOidMarshaller());
+    }
+
+    @Override
+    public String getOidStr() {
+        return oidStr;
+    }
+
+    RootOidDefault getOid() {
+        return RootOidDefault.deString(oidStr, getOidMarshaller());
+    }
+
+    @Override
+    public ObjectAdapter getObject() {
+        return getPersistenceSession().loadObject(getOid());
+    }
+
+
+    // /////////////////////////////////////////////////////
+    // version
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public abstract Version getVersion();
+
+    @Override
+    public abstract void checkVersion(final ObjectAdapter object);
+
+    @Override
+    public abstract void updateVersion();
+
+    
+    // /////////////////////////////////////////////////////
+    // restoreToLoader
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public abstract void restoreToLoader();
+
+
+    // /////////////////////////////////////////////////////
+    // value semantics
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public int hashCode() {
+        return oidStr.hashCode();
+    }
+
+    @Override
+    public abstract boolean equals(final Object obj);
+
+
+    // /////////////////////////////////////////////////////
+    // debugging, toString
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public abstract void debugData(final DebugBuilder debug);
+
+    @Override
+    public abstract String toString();
+
+    // /////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // /////////////////////////////////////////////////////
+
+    private static Persistor getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected OidMarshaller getOidMarshaller() {
+		return IsisContext.getOidMarshaller();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/TransientRootAdapterMapping.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/TransientRootAdapterMapping.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/TransientRootAdapterMapping.java
new file mode 100644
index 0000000..7656f23
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/context/TransientRootAdapterMapping.java
@@ -0,0 +1,95 @@
+/*
+ *  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.context;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.runtime.memento.Memento;
+
+public class TransientRootAdapterMapping extends RootAdapterMappingAbstract {
+    
+    private static final long serialVersionUID = 1L;
+    
+    private final Memento memento;
+
+    public TransientRootAdapterMapping(final ObjectAdapter adapter) {
+        super(adapter);
+        Assert.assertFalse("OID is for persistent", !adapter.getOid().isTransient());
+        Assert.assertFalse("adapter is for persistent", !adapter.isTransient());
+        memento = new Memento(adapter);
+    }
+
+    // /////////////////////////////////////////////////////
+    // version
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public Version getVersion() {
+        return null;
+    }
+
+    @Override
+    public void checkVersion(final ObjectAdapter object) {
+    }
+
+    @Override
+    public void updateVersion() {
+    }
+
+    // /////////////////////////////////////////////////////
+    // restoreToLoader
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void restoreToLoader() {
+        memento.recreateObject();
+    }
+
+    // /////////////////////////////////////////////////////
+    // value semantics
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (!(obj instanceof TransientRootAdapterMapping)) {
+            return false;
+        } 
+        return ((TransientRootAdapterMapping) obj).getOidStr().equals(getOidStr());
+    }
+
+    
+
+    // /////////////////////////////////////////////////////
+    // debugging, toString
+    // /////////////////////////////////////////////////////
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        memento.debug(debug);
+    }
+
+    @Override
+    public String toString() {
+        return "TRANSIENT : " + getOidStr() + " : " + memento;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/CollectionCrumb.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/CollectionCrumb.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/CollectionCrumb.java
new file mode 100644
index 0000000..d177118
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/CollectionCrumb.java
@@ -0,0 +1,58 @@
+/*
+ *  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.crumb;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.html.request.ForwardRequest;
+import org.apache.isis.viewer.html.request.Request;
+
+public class CollectionCrumb implements Crumb {
+    private final String collectionId;
+    private final String title;
+
+    public CollectionCrumb(final String collectionId, final ObjectAdapter collection) {
+        this.collectionId = collectionId;
+        title = collection.titleString();
+    }
+
+    @Override
+    public void debug(final DebugBuilder string) {
+        string.appendln("Collection Crumb");
+        string.appendln("object", collectionId);
+        string.appendln("title", title);
+    }
+
+    @Override
+    public String title() {
+        return title;
+    }
+
+    @Override
+    public String toString() {
+        return new ToString(this).append(title()).toString();
+    }
+
+    @Override
+    public Request changeContext() {
+        return ForwardRequest.listCollection(collectionId);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/Crumb.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/Crumb.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/Crumb.java
new file mode 100644
index 0000000..b64a583
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/Crumb.java
@@ -0,0 +1,33 @@
+/*
+ *  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.crumb;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.viewer.html.request.Request;
+
+public interface Crumb {
+    // TODO add icons to crumbs
+
+    String title();
+
+    void debug(DebugBuilder string);
+
+    Request changeContext();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectCrumb.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectCrumb.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectCrumb.java
new file mode 100644
index 0000000..b0e3c54
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectCrumb.java
@@ -0,0 +1,66 @@
+/*
+ *  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.crumb;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.viewer.html.request.ForwardRequest;
+import org.apache.isis.viewer.html.request.Request;
+
+public class ObjectCrumb implements Crumb {
+    private final String objectId;
+    private final boolean isService;
+    private final String title;
+
+    public ObjectCrumb(final String objectId, final ObjectAdapter object) {
+        this.objectId = objectId;
+        title = object.titleString();
+        isService = object.getSpecification().isService();
+    }
+
+    @Override
+    public void debug(final DebugBuilder string) {
+        string.appendln("Object Crumb");
+        string.appendln("object", objectId);
+        string.appendln("title", title);
+        string.appendln("for service", isService);
+    }
+
+    @Override
+    public String title() {
+        return title;
+    }
+
+    @Override
+    public String toString() {
+        return new ToString(this).append(title()).toString();
+    }
+
+    @Override
+    public Request changeContext() {
+        if (isService) {
+            return ForwardRequest.viewService(objectId);
+        } else {
+            return ForwardRequest.viewObject(objectId);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectFieldCrumb.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectFieldCrumb.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectFieldCrumb.java
new file mode 100644
index 0000000..5fbd48d
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/ObjectFieldCrumb.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.viewer.html.crumb;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.viewer.html.request.Request;
+
+public class ObjectFieldCrumb implements Crumb {
+    private final String fieldName;
+
+    public ObjectFieldCrumb(final String fieldName) {
+        this.fieldName = fieldName;
+    }
+
+    @Override
+    public void debug(final DebugBuilder string) {
+        string.appendln("Object Field Crumb");
+        string.appendln("field name", fieldName);
+    }
+
+    @Override
+    public String title() {
+        return fieldName;
+    }
+
+    @Override
+    public String toString() {
+        return new ToString(this).append(title()).toString();
+    }
+
+    @Override
+    public Request changeContext() {
+        throw new NotYetImplementedException();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/TaskCrumb.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/TaskCrumb.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/TaskCrumb.java
new file mode 100644
index 0000000..c61233d
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/crumb/TaskCrumb.java
@@ -0,0 +1,62 @@
+/*
+ *  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.crumb;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.viewer.html.request.ForwardRequest;
+import org.apache.isis.viewer.html.request.Request;
+import org.apache.isis.viewer.html.task.Task;
+
+public class TaskCrumb implements Crumb {
+    private final Task task;
+
+    public TaskCrumb(final Task task) {
+        this.task = task;
+    }
+
+    public Task getTask() {
+        return task;
+    }
+
+    @Override
+    public void debug(final DebugBuilder string) {
+        string.appendln("Task Crumb");
+        string.appendln("task", task);
+
+        task.debug(string);
+    }
+
+    @Override
+    public String title() {
+        return task.getName();
+    }
+
+    @Override
+    public String toString() {
+        return new ToString(this).append(title()).toString();
+    }
+
+    @Override
+    public Request changeContext() {
+        return ForwardRequest.task(task);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageLookup.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageLookup.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageLookup.java
new file mode 100644
index 0000000..670205b
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageLookup.java
@@ -0,0 +1,66 @@
+/*
+ *  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.image;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+/**
+ * ImageLookup provides an efficient way of finding the most suitable image to
+ * use.
+ * 
+ * <p>
+ * It ensures that an image is always available, providing a default image if
+ * needed. All requests are cached to improve performance.
+ */
+// TODO allow for multiple extension types
+public class ImageLookup {
+
+    private static ImageProvider imageProvider = new ImageProviderResourceBased();
+
+    public static ImageProvider getInstance() {
+        return imageProvider;
+    }
+
+    public static void setImageDirectory(final String imageDirectory) {
+        if (getInstance() instanceof ImageProviderDirectoryBased) {
+            final ImageProviderDirectoryBased imageProviderDirectoryBased = (ImageProviderDirectoryBased) imageProvider;
+            imageProviderDirectoryBased.setImageDirectory(imageDirectory);
+        }
+    }
+
+    public static void debug(final DebugBuilder debug) {
+        getInstance().debug(debug);
+    }
+
+    public static String image(final ObjectAdapter object) {
+        return getInstance().image(object);
+    }
+
+    public static String image(final ObjectSpecification specification) {
+        return getInstance().image(specification);
+    }
+
+    public static String image(final String name) {
+        return getInstance().image(name);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProvider.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProvider.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProvider.java
new file mode 100644
index 0000000..2f0912c
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProvider.java
@@ -0,0 +1,47 @@
+/*
+ *  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.image;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+/**
+ * Factors out the {@link ImageLookup} responsibilities into an interface, with
+ * a view to moving towards alternative mechanisms.
+ */
+public interface ImageProvider {
+
+    public void debug(final DebugBuilder debug);
+
+    /**
+     * For an object, the icon name from the object is return if it is not null,
+     * otherwise the specification is used to look up a suitable image name.
+     * 
+     * @see ObjectAdapter#getIconName()
+     * @see #image(ObjectSpecification)
+     */
+    public String image(final ObjectAdapter object);
+
+    public String image(final ObjectSpecification specification);
+
+    public String image(final String name);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderAbstract.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderAbstract.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderAbstract.java
new file mode 100644
index 0000000..27c7a9e
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderAbstract.java
@@ -0,0 +1,123 @@
+/*
+ *  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.image;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public abstract class ImageProviderAbstract implements ImageProvider {
+
+    private final String DEFAULT_IMAGE = "Default";
+
+    /**
+     * The extensions we'll search for.
+     */
+    private final String[] EXTENSIONS = { "png", "gif", "jpg", "jpeg" };
+
+    private final Map<String, String> images = new HashMap<String, String>();
+
+    @Override
+    public final String image(final ObjectAdapter object) {
+
+        if (object == null) {
+            return image((String) null);
+        }
+
+        final String iconName = object.getIconName();
+        if (iconName != null) {
+            return image(iconName);
+        } else {
+            return image(object.getSpecification());
+        }
+    }
+
+    @Override
+    public final String image(final ObjectSpecification specification) {
+
+        if (specification == null) {
+            return image((String) null);
+        }
+
+        final String specShortName = specification.getShortIdentifier();
+        final String imageName = image(specShortName);
+        if (imageName != null) {
+            return imageName;
+        }
+
+        // search up the hierarchy
+        return image(specification.superclass());
+    }
+
+    @Override
+    public String image(final String name) {
+
+        if (name == null) {
+            return findImage(DEFAULT_IMAGE, EXTENSIONS);
+        }
+
+        // look up from cache
+        String imageName = images.get(name);
+        if (imageName != null) {
+            return imageName;
+        }
+
+        // delegate to subclass to see if can find the image.
+        imageName = findImage(name, EXTENSIONS);
+
+        if (imageName != null) {
+            // cache and return
+            images.put(name, imageName);
+            return imageName;
+        }
+
+        // ie loop round to return the default.
+        return image((String) null);
+    }
+
+    @Override
+    public final void debug(final DebugBuilder debug) {
+        debug.appendTitle("Image Lookup");
+        debug.indent();
+        final Iterator<String> keys = images.keySet().iterator();
+        while (keys.hasNext()) {
+            final Object key = keys.next();
+            final Object value = images.get(key);
+            debug.appendln(key + " -> " + value);
+        }
+        debug.unindent();
+    }
+
+    /**
+     * Hook method for subclass to actually return the image, else <tt>null</tt>
+     * .
+     * 
+     * @param className
+     *            - the short name of the class to search for.
+     * @param extensions
+     *            - the extensions to search for.
+     */
+    protected abstract String findImage(final String className, String[] extensions);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBased.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBased.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBased.java
new file mode 100644
index 0000000..73d41b0
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBased.java
@@ -0,0 +1,160 @@
+/*
+ *  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.image;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class ImageProviderDirectoryBased implements ImageProvider {
+
+	private final static String UNKNOWN_IMAGE = "Default";
+    private final static String[] EXTENSIONS = { "png", "gif", "jpg", "jpeg" };
+    
+    private final Map<String,String> images = Maps.newHashMap();
+    
+    private File imageDirectory;
+    private String unknownImageFile;
+
+    public void setImageDirectory(final String imageDirectory) {
+        this.imageDirectory = new File(imageDirectory);
+        if (!this.imageDirectory.exists()) {
+            throw new IsisException("No image directory found: " + imageDirectory);
+        }
+        unknownImageFile = imageFile(UNKNOWN_IMAGE);
+    }
+
+    ///////////////////////////////////////////////////
+    // API
+    ///////////////////////////////////////////////////
+
+    /**
+     * For an object, the icon name from the object is return if it is not null,
+     * otherwise the specification is used to look up a suitable image name.
+     * 
+     * @see ObjectAdapter#getIconName()
+     * @see #image(ObjectSpecification)
+     */
+    @Override
+    public String image(final ObjectAdapter object) {
+        final String iconName = object.getIconName();
+        if (iconName != null) {
+            return image(iconName);
+        } else {
+            return image(object.getSpecification());
+        }
+    }
+
+    @Override
+    public String image(final ObjectSpecification specification) {
+        final String name = specification.getShortIdentifier();
+        final String imageName = (String) images.get(name);
+        if (imageName != null) {
+            return imageName;
+        } else {
+            return findImage(specification);
+        }
+    }
+
+    @Override
+    public String image(final String name) {
+        final String imageName = (String) images.get(name);
+        if (imageName != null) {
+            return imageName;
+        } else {
+            final String fileName = imageFile(name);
+            return fileName == null ? unknownImageFile : fileName;
+        }
+    }
+
+
+    ///////////////////////////////////////////////////
+    // helpers
+    ///////////////////////////////////////////////////
+
+    private String imageFile(final String imageName) {
+        final String[] files = imageDirectory.list(new FilenameMatchesNamePlusExtension(imageName));
+
+        return files.length == 0 ? null : files[0];
+    }
+
+    private String findImage(final ObjectSpecification specification) {
+        final String name = specification.getShortIdentifier();
+        final String fileName = imageFile(name);
+        if (fileName != null) {
+            images.put(name, fileName);
+            return fileName;
+        } 
+        
+        final ObjectSpecification superclass = specification.superclass();
+		if (superclass != null) {
+		    return findImage(superclass);
+		}
+		
+		return unknownImageFile;
+    }
+
+
+    final static class FilenameMatchesNamePlusExtension implements FilenameFilter {
+		private final String imageName;
+
+		private FilenameMatchesNamePlusExtension(final String imageName) {
+			this.imageName = imageName;
+		}
+
+		@Override
+		public boolean accept(final File dir, final String name) {
+		    final int dot = name.lastIndexOf('.');
+		    if (dot <= 0) {
+		    	return false;
+		    }
+		    for (final String extension : EXTENSIONS) {
+			    if (name.substring(0, dot).equalsIgnoreCase(imageName) && name.substring(dot + 1).equalsIgnoreCase(extension)) {
+			        return true;
+			    }
+			}
+			return false;
+		}
+	}
+
+
+    ///////////////////////////////////////////////////
+    // debugging
+    ///////////////////////////////////////////////////
+
+    @Override
+    public void debug(final DebugBuilder debug) {
+        debug.appendTitle("Image Lookup");
+        debug.indent();
+        for (Map.Entry<String, String> entry: images.entrySet()) {
+            debug.appendln(entry.getKey() + " -> " + entry.getValue());
+        }
+        debug.unindent();
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBasedReworked.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBasedReworked.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBasedReworked.java
new file mode 100644
index 0000000..16d8a83
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderDirectoryBasedReworked.java
@@ -0,0 +1,60 @@
+/*
+ *  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.image;
+
+import java.io.File;
+import java.io.FilenameFilter;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public class ImageProviderDirectoryBasedReworked extends ImageProviderAbstract {
+
+    private File imageDirectory;
+
+    public void setImageDirectory(final String imageDirectory) {
+        this.imageDirectory = new File(imageDirectory);
+        if (!this.imageDirectory.exists()) {
+            throw new IsisException("No image directory found: " + imageDirectory);
+        }
+    }
+
+    @Override
+    protected String findImage(final String imageName, final String[] extensions) {
+        final String[] files = imageDirectory.list(new FilenameFilter() {
+            @Override
+            public boolean accept(final File dir, final String name) {
+                final int dot = name.lastIndexOf('.');
+                if (dot > 0) {
+                    final String nameWithoutExtension = name.substring(0, dot);
+                    final String nameExtension = name.substring(dot + 1);
+                    for (final String extension : extensions) {
+                        if (nameWithoutExtension.equalsIgnoreCase(imageName) && nameExtension.equalsIgnoreCase(extension)) {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+        });
+
+        return files.length == 0 ? null : files[0];
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderResourceBased.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderResourceBased.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderResourceBased.java
new file mode 100644
index 0000000..c1ed289
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/image/ImageProviderResourceBased.java
@@ -0,0 +1,72 @@
+/*
+ *  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.image;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.isis.core.commons.lang.Resources;
+
+public class ImageProviderResourceBased extends ImageProviderAbstract {
+
+    /**
+     * Is an array since easy to maintain
+     */
+    public final static String[] DEFAULT_LOCATIONS = { "images", "src/main/resources", "src/main/java" };
+
+    /**
+     * Is a list since easy to inject.
+     */
+    private List<String> locations = new ArrayList<String>();
+
+    /**
+     * Initializes {@link #locations} with {@link #DEFAULT_LOCATIONS}, but can
+     * be overridden using {@link #setLocations(List)}.
+     */
+    public ImageProviderResourceBased() {
+        locations.addAll(Arrays.asList(DEFAULT_LOCATIONS));
+    }
+
+    @Override
+    protected String findImage(final String className, final String[] extensions) {
+
+        for (final String location : locations) {
+            for (final String extension : extensions) {
+                final String candidate = location + "/" + className + "." + extension;
+                if (Resources.getResourceAsFile(candidate) != null) {
+                    return candidate;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Optionally inject the locations where the provider will search.
+     * 
+     * <p>
+     * If not specified, will use the locations in {@link #DEFAULT_LOCATIONS}.
+     */
+    public void setLocations(final List<String> locations) {
+        this.locations = locations;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ForwardRequest.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ForwardRequest.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ForwardRequest.java
new file mode 100644
index 0000000..bfb1808
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ForwardRequest.java
@@ -0,0 +1,138 @@
+/*
+ *  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.request;
+
+import org.apache.isis.viewer.html.task.Task;
+
+public class ForwardRequest implements Request {
+
+    public static Request editObject(final String objectId) {
+        return new ForwardRequest(EDIT_COMMAND, objectId);
+    }
+
+    public static Request listCollection(final String collectionId) {
+        return new ForwardRequest(COLLECTION_COMMAND, collectionId);
+    }
+
+    public static ForwardRequest viewObject(final String objectId) {
+        return new ForwardRequest(OBJECT_COMMAND, objectId);
+    }
+
+    public static Request viewObject(final String objectId, final String collectionField) {
+        return new ForwardRequest(OBJECT_COMMAND, objectId, collectionField);
+    }
+
+    public static Request viewService(final String objectId) {
+        return new ForwardRequest(SERVICE_COMMAND, objectId);
+    }
+
+    public static Request task(final Task task) {
+        final ForwardRequest forwardRequest = new ForwardRequest(TASK_COMMAND, null);
+        forwardRequest.taskId = task.getId();
+        return forwardRequest;
+    }
+
+    public static Request taskComplete() {
+        final ForwardRequest forwardRequest = new ForwardRequest(TASK_COMMAND, null);
+        forwardRequest.submitName = "Ok";
+        return forwardRequest;
+    }
+
+    private final String actionName;
+    private Request forwardedRequest;
+    private final String objectId;
+    private final String fieldName;
+    private String submitName;
+    private String taskId;
+
+    private ForwardRequest(final String actionName, final String id) {
+        this(actionName, id, null);
+    }
+
+    private ForwardRequest(final String actionName, final String objectId, final String fieldName) {
+        this.actionName = actionName;
+        this.objectId = objectId;
+        this.fieldName = fieldName;
+    }
+
+    @Override
+    public void forward(final Request forwardedRequest) {
+        this.forwardedRequest = forwardedRequest;
+    }
+
+    @Override
+    public String getActionId() {
+        return null;
+    }
+
+    @Override
+    public String getElementId() {
+        return null;
+    }
+
+    @Override
+    public String getName() {
+        return null;
+    }
+
+    @Override
+    public String getRequestType() {
+        return actionName;
+    }
+
+    @Override
+    public String getButtonName() {
+        return submitName;
+    }
+
+    @Override
+    public String getProperty() {
+        return fieldName;
+    }
+
+    @Override
+    public String getFieldEntry(final int i) {
+        return null;
+    }
+
+    @Override
+    public String getTaskId() {
+        return taskId;
+    }
+
+    @Override
+    public Request getForward() {
+        return forwardedRequest;
+    }
+
+    @Override
+    public String getObjectId() {
+        return objectId;
+    }
+
+    @Override
+    public String toString() {
+        return "ForwardRequest " + actionName + " " + forwardedRequest;
+    }
+
+    public static Request logon() {
+        return new ForwardRequest("logon", null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/Request.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/Request.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/Request.java
new file mode 100644
index 0000000..8681660
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/Request.java
@@ -0,0 +1,72 @@
+/*
+ *  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.request;
+
+/**
+ * The Request object represents all the information collected from the user
+ * when requesting the server do something.
+ */
+public interface Request {
+    public static final String EDIT_COMMAND = "edit";
+    public static final String COLLECTION_COMMAND = "collection";
+    public static final String FIELD_COLLECTION_COMMAND = "fieldCollection";
+    public static final String OBJECT_COMMAND = "object";
+    public static final String SERVICE_COMMAND = "serviceOption";
+    public static final String TASK_COMMAND = "task";
+    public static final String LOGON_COMMAND = "task";
+
+    void forward(Request object);
+
+    String getActionId();
+
+    /**
+     * Name of a property within an object.
+     */
+    String getProperty();
+
+    /**
+     * The element within a collection.
+     */
+    String getElementId();
+
+    /**
+     * The users entry into a field on the form.
+     */
+    String getFieldEntry(int i);
+
+    Request getForward();
+
+    String getObjectId();
+
+    /**
+     * Name of the request. See the constants defined in this class.
+     */
+    String getRequestType();
+
+    String getTaskId();
+
+    /**
+     * Name of the button pressed on the form.
+     */
+    String getButtonName();
+
+    String getName();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ServletRequest.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ServletRequest.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ServletRequest.java
new file mode 100644
index 0000000..0ca1bda
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/request/ServletRequest.java
@@ -0,0 +1,98 @@
+/*
+ *  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.request;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class ServletRequest implements Request {
+    private Request forwardRequest;
+    private final HttpServletRequest request;
+    private final String requestType;
+
+    public ServletRequest(final HttpServletRequest request) {
+        this.request = request;
+
+        final String path = request.getServletPath();
+        final int from = path.lastIndexOf('/');
+        final int to = path.lastIndexOf('.');
+        requestType = path.substring(from + 1, to);
+    }
+
+    @Override
+    public void forward(final Request forwardRequest) {
+        this.forwardRequest = forwardRequest;
+    }
+
+    @Override
+    public String getActionId() {
+        return request.getParameter("action");
+    }
+
+    @Override
+    public String getProperty() {
+        return request.getParameter("field");
+    }
+
+    @Override
+    public String getElementId() {
+        return request.getParameter("element");
+    }
+
+    @Override
+    public String getFieldEntry(final int i) {
+        return request.getParameter("fld" + i);
+    }
+
+    @Override
+    public String getTaskId() {
+        return request.getParameter("id");
+    }
+
+    @Override
+    public Request getForward() {
+        return forwardRequest;
+    }
+
+    @Override
+    public String getName() {
+        return request.getParameter("name");
+    }
+
+    @Override
+    public String getObjectId() {
+        return request.getParameter("id");
+    }
+
+    @Override
+    public String getRequestType() {
+        return requestType;
+    }
+
+    @Override
+    public String getButtonName() {
+        return request.getParameter("button");
+    }
+
+    @Override
+    public String toString() {
+        return "ServletRequest " + request.getRequestURI() + "?" + request.getQueryString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/AbstractHtmlViewerServlet.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/AbstractHtmlViewerServlet.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/AbstractHtmlViewerServlet.java
new file mode 100644
index 0000000..a4cda01
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/AbstractHtmlViewerServlet.java
@@ -0,0 +1,82 @@
+/*
+ *  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;
+
+import javax.servlet.http.HttpServlet;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.core.runtime.system.DeploymentType;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.viewer.html.PathBuilder;
+import org.apache.isis.viewer.html.PathBuilderDefault;
+import org.apache.isis.viewer.html.component.html.HtmlComponentFactory;
+
+public abstract class AbstractHtmlViewerServlet extends HttpServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    private PathBuilder pathBuilder;
+    private HtmlComponentFactory componentFactory;
+
+    protected HtmlComponentFactory getHtmlComponentFactory() {
+        if(componentFactory == null) {
+            componentFactory = new HtmlComponentFactory(getPathBuilder());
+        }
+        return componentFactory;
+    }
+
+    protected PathBuilder getPathBuilder() {
+        if (pathBuilder != null) {
+            return pathBuilder;
+        }
+        return pathBuilder = new PathBuilderDefault(getServletContext());
+    }
+
+
+    /**
+     * Convenience.
+     */
+    protected String pathTo(final String prefix) {
+        return getPathBuilder().pathTo(prefix);
+    }
+
+    // //////////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // //////////////////////////////////////////////////////////////
+
+    protected AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+    protected IsisConfiguration getConfiguration() {
+        return IsisContext.getConfiguration();
+    }
+
+    protected AuthenticationManager getAuthenticationManager() {
+        return IsisContext.getAuthenticationManager();
+    }
+
+    protected DeploymentType getDeploymentType() {
+        return IsisContext.getDeploymentType();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/ControllerServlet.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/ControllerServlet.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/ControllerServlet.java
new file mode 100644
index 0000000..3c84343
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/ControllerServlet.java
@@ -0,0 +1,154 @@
+/*
+ *  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;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.viewer.html.PathBuilder;
+import org.apache.isis.viewer.html.component.Page;
+import org.apache.isis.viewer.html.context.Context;
+import org.apache.isis.viewer.html.request.Request;
+import org.apache.isis.viewer.html.request.ServletRequest;
+import org.apache.isis.viewer.html.servlet.internal.WebController;
+
+public class ControllerServlet extends AbstractHtmlViewerServlet {
+
+    private static final long serialVersionUID = 1L;
+    private static final Logger LOG = Logger.getLogger(ControllerServlet.class);
+
+    private String encoding;
+    private WebController controller;
+
+    // //////////////////////////////////////////////////////////////////
+    // init
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    public void init(final ServletConfig servletConfig) throws ServletException {
+        super.init(servletConfig);
+        encoding =
+            getConfiguration().getString(HtmlServletConstants.ENCODING_KEY, HtmlServletConstants.ENCODING_DEFAULT);
+
+        controller = getWebController(getPathBuilder());
+
+        final boolean debugEnabled = getConfiguration().getBoolean(HtmlServletConstants.DEBUG_KEY);
+        controller.setDebug(debugEnabled);
+
+        controller.init();
+    }
+
+    // Don't remove this - It allows other implementations of HtmlViewer to replace the WebController
+    protected WebController getWebController(PathBuilder pathBuilder) {
+        if (controller == null) {
+            controller = new WebController(getPathBuilder());
+        }
+        return controller;
+    }
+
+    // //////////////////////////////////////////////////////////////////
+    // doGet, doPost
+    // //////////////////////////////////////////////////////////////////
+
+    @Override
+    protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
+        throws ServletException, IOException {
+        request.setCharacterEncoding(encoding);
+        processRequest(request, response);
+    }
+
+    @Override
+    protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
+        IOException {
+        processRequest(request, response);
+    }
+
+    private void processRequest(final HttpServletRequest request, final HttpServletResponse response)
+        throws ServletException, IOException {
+        LOG.info("request: " + request.getServletPath() + "?" + request.getQueryString());
+
+        final Request req = new ServletRequest(request);
+
+        if (req.getRequestType() == null) {
+            throw new ServletException("No action specified");
+        } else if (!controller.actionExists(req)) {
+            throw new ServletException("No such action " + req.getRequestType());
+        } else {
+            try {
+                final Context context = getContextForRequest(request);
+                processRequest(request, response, req, context);
+            } catch (final Exception e) {
+                LOG.error("exception during request handling", e);
+                throw new ServletException("Internal exception", e);
+            }
+        }
+    }
+
+    private Context getContextForRequest(final HttpServletRequest request) {
+        final AuthenticationSession authSession = getAuthenticationSession();
+        Context context = (Context) authSession.getAttribute(HtmlServletConstants.AUTHENTICATION_SESSION_CONTEXT_KEY);
+        if (context == null || !context.isValid()) {
+            context = new Context(getHtmlComponentFactory());
+            authSession.setAttribute(HtmlServletConstants.AUTHENTICATION_SESSION_CONTEXT_KEY, context);
+        }
+        return context;
+    }
+
+    private void processRequest(final HttpServletRequest request, final HttpServletResponse response,
+        final Request req, final Context context) throws IOException, ServletException {
+        response.setContentType("text/html");
+        response.setCharacterEncoding(encoding);
+        // no need to check if logged in; the IsisSessionFilter would
+        // have prevented us from getting here.
+
+        final Page page = controller.generatePage(context, req);
+        if (context.isValid()) {
+            if (controller.isDebug()) {
+                controller.addDebug(page, req);
+                addDebug(request, page);
+            }
+            PrintWriter writer;
+            writer = response.getWriter();
+            page.write(writer);
+        } else {
+            response.sendRedirect(getLogonPage());
+        }
+    }
+
+    protected String getLogonPage() {
+        return pathTo(HtmlServletConstants.LOGON_PAGE);
+    }
+
+    private void addDebug(final HttpServletRequest request, final Page page) {
+        page.addDebug("Servlet path", request.getServletPath());
+        page.addDebug("Query string", request.getQueryString());
+        page.addDebug("Context path", request.getContextPath());
+        page.addDebug("Path info", request.getPathInfo());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/HtmlServletConstants.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/HtmlServletConstants.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/HtmlServletConstants.java
new file mode 100644
index 0000000..4f40f75
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/HtmlServletConstants.java
@@ -0,0 +1,48 @@
+/*
+ *  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;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+
+public final class HtmlServletConstants {
+
+    static final String PROPERTY_BASE = ConfigurationConstants.ROOT + "viewer.html.";
+
+    static final String DEBUG_KEY = PROPERTY_BASE + "debug";
+
+    static final String ENCODING_KEY = PROPERTY_BASE + "encoding";
+    static final String ENCODING_DEFAULT = "ISO-8859-1";
+
+    public static final String SUFFIX_INIT_PARAM = "viewer-html.suffix";
+    public static final String SUFFIX_INIT_PARAM_VALUE_DEFAULT = "app";
+
+    /**
+     * Binding to the {@link AuthenticationSession}.
+     */
+    static final String AUTHENTICATION_SESSION_CONTEXT_KEY = "isis-context";
+
+    public static final String LOGON_PAGE = "logon";
+    static final String START_PAGE = "start";
+
+    private HtmlServletConstants() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/91a8000b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/LogonServlet.java
----------------------------------------------------------------------
diff --git a/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/LogonServlet.java b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/LogonServlet.java
new file mode 100644
index 0000000..79d5859
--- /dev/null
+++ b/mothballed/component/viewer/html/impl/src/main/java/org/apache/isis/viewer/html/servlet/LogonServlet.java
@@ -0,0 +1,124 @@
+/*
+ *  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;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequest;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestPassword;
+import org.apache.isis.core.runtime.authentication.exploration.AuthenticationRequestExploration;
+import org.apache.isis.core.runtime.authentication.standard.RegistrationDetailsPassword;
+import org.apache.isis.core.runtime.system.DeploymentType;
+import org.apache.isis.core.webapp.IsisSessionFilter;
+import org.apache.isis.core.webapp.auth.AuthenticationSessionStrategy;
+import org.apache.isis.viewer.html.component.html.HtmlComponentFactory;
+import org.apache.isis.viewer.html.component.html.LogonFormPage;
+import org.apache.isis.viewer.html.context.Context;
+import org.apache.isis.viewer.html.monitoring.servermonitor.Monitor;
+
+public class LogonServlet extends AbstractHtmlViewerServlet {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final Logger LOG = Logger.getLogger(LogonServlet.class);
+
+    private AuthenticationSessionStrategy authenticationSessionStrategy;
+
+    @Override
+    public void init() throws ServletException {
+        authenticationSessionStrategy = IsisSessionFilter.lookup(getServletConfig().getInitParameter(IsisSessionFilter.AUTHENTICATION_SESSION_STRATEGY_KEY));
+    }
+
+    @Override
+    protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
+        doPost(request, response);
+    }
+
+    @Override
+    protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
+
+        // look for existing valid session
+        final AuthenticationSession existingAuthSession = authenticationSessionStrategy.lookupValid(request, response);
+        if (existingAuthSession != null) {
+            redirectToStartPage(response, existingAuthSession.getUserName());
+            return;
+        }
+
+        // prompt
+        final String user = request.getParameter("username");
+        final String password = request.getParameter("password");
+        if (user == null && !getDeploymentType().isExploring()) {
+            renderPrompt(response, "", "", null);
+            return;
+        }
+
+        // authenticate; re-prompt if required
+        final AuthenticationSession authSession = authenticate(user, password);
+        if (authSession == null) {
+            renderPrompt(response, user, password, "user/password invalid");
+            return;
+        }
+
+        // authenticated
+        authenticationSessionStrategy.bind(request, response, authSession);
+
+        final Context context = new Context(getHtmlComponentFactory());
+        context.setSession(authSession);
+        authSession.setAttribute(HtmlServletConstants.AUTHENTICATION_SESSION_CONTEXT_KEY, context);
+
+        LOG.info("created session");
+        redirectToStartPage(response, user);
+    }
+
+    protected HtmlComponentFactory getHtmlComponentFactory() {
+        return new HtmlComponentFactory(getPathBuilder());
+    }
+
+    private void redirectToStartPage(final HttpServletResponse response, final String user) throws IOException {
+        Monitor.addEvent("Web", "Logon - " + user);
+        response.sendRedirect(pathTo(HtmlServletConstants.START_PAGE));
+    }
+
+    private void renderPrompt(final HttpServletResponse response, final String user, final String password, final String error) throws IOException {
+        response.setContentType("text/html");
+        final HtmlComponentFactory factory = getHtmlComponentFactory();
+        final boolean registerLink = getAuthenticationManager().supportsRegistration(RegistrationDetailsPassword.class);
+        final LogonFormPage page = factory.createLogonPage(user, password, registerLink, error);
+        page.write(response.getWriter());
+    }
+
+    protected AuthenticationSession authenticate(final String user, final String password) {
+        AuthenticationRequest request;
+        if (getDeploymentType() == DeploymentType.EXPLORATION) {
+            request = new AuthenticationRequestExploration();
+        } else {
+            request = new AuthenticationRequestPassword(user, password);
+        }
+        return getAuthenticationManager().authenticate(request);
+    }
+
+}