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:35 UTC

[33/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/bytecode/ObjectResolveAndObjectChangedEnhancerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/bytecode/ObjectResolveAndObjectChangedEnhancerAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/bytecode/ObjectResolveAndObjectChangedEnhancerAbstract.java
new file mode 100644
index 0000000..40a437a
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/bytecode/ObjectResolveAndObjectChangedEnhancerAbstract.java
@@ -0,0 +1,107 @@
+/*
+ *  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.bytecode;
+
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.specloader.specimpl.dflt.ObjectSpecificationDefault;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectfactory.ObjectChanger;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectfactory.ObjectResolver;
+
+public abstract class ObjectResolveAndObjectChangedEnhancerAbstract {
+
+    protected final ObjectResolver objectResolver;
+    protected final ObjectChanger objectChanger;
+    protected final SpecificationLoaderSpi specificationLoader;
+
+    public ObjectResolveAndObjectChangedEnhancerAbstract(final ObjectResolver objectResolver, final ObjectChanger objectChanger, final SpecificationLoaderSpi specificationLoader) {
+        ensureThatArg(objectResolver, is(notNullValue()));
+        ensureThatArg(objectChanger, is(notNullValue()));
+        ensureThatArg(specificationLoader, is(notNullValue()));
+
+        this.objectResolver = objectResolver;
+        this.objectChanger = objectChanger;
+        this.specificationLoader = specificationLoader;
+    }
+
+    /**
+     * Subclasses should call from their constructor, and setup their
+     * implementation-specific callback mechanism.
+     */
+    protected abstract void createCallback();
+
+    protected ObjectSpecificationDefault getJavaSpecificationOfOwningClass(final Method method) {
+        return getJavaSpecification(method.getDeclaringClass());
+    }
+
+    protected ObjectSpecificationDefault getJavaSpecification(final Class<?> cls) {
+        final ObjectSpecification nos = getSpecification(cls);
+        if (!(nos instanceof ObjectSpecificationDefault)) {
+            throw new UnsupportedOperationException("Only Java is supported (specification is '" + nos.getClass().getCanonicalName() + "')");
+        }
+        return (ObjectSpecificationDefault) nos;
+    }
+
+    protected boolean impliesResolve(final ImperativeFacet[] imperativeFacets) {
+        for (final ImperativeFacet imperativeFacet : imperativeFacets) {
+            if (imperativeFacet.impliesResolve()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected boolean impliesObjectChanged(final ImperativeFacet[] imperativeFacets) {
+        for (final ImperativeFacet imperativeFacet : imperativeFacets) {
+            if (imperativeFacet.impliesObjectChanged()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private ObjectSpecification getSpecification(final Class<?> type) {
+        return specificationLoader.loadSpecification(type);
+    }
+
+    // /////////////////////////////////////////////////////////////
+    // Dependencies (from constructor)
+    // /////////////////////////////////////////////////////////////
+
+    public final ObjectResolver getObjectResolver() {
+        return objectResolver;
+    }
+
+    public final ObjectChanger getObjectChanger() {
+        return objectChanger;
+    }
+
+    public final SpecificationLoaderSpi getSpecificationLoader() {
+        return specificationLoader;
+    }
+
+}
\ 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/fixturedomainservice/FixtureException.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/FixtureException.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/FixtureException.java
new file mode 100644
index 0000000..de2710e
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/FixtureException.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.runtime.fixturedomainservice;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public class FixtureException extends IsisException {
+    private static final long serialVersionUID = 1L;
+
+    public FixtureException() {
+        super();
+    }
+
+    public FixtureException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+
+    public FixtureException(final String msg) {
+        super(msg);
+    }
+
+    public FixtureException(final Throwable cause) {
+        super(cause);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureFilePersistor.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureFilePersistor.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureFilePersistor.java
new file mode 100644
index 0000000..fdd202b
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureFilePersistor.java
@@ -0,0 +1,241 @@
+/*
+ *  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.fixturedomainservice;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.core.metamodel.facets.object.parseable.ParseableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.Persistor;
+
+public class ObjectFixtureFilePersistor {
+
+    private static final Logger LOG = Logger.getLogger(ObjectFixtureFilePersistor.class);
+
+    public Set<Object> loadData(final Reader reader) throws IOException {
+        final Set<Object> objects = new HashSet<Object>();
+
+        final BufferedReader buffer = new BufferedReader(reader);
+        final LoadedObjects loaded = new LoadedObjects(objects);
+        String line;
+        ObjectAdapter object = null;
+        int lineNo = 0;
+        try {
+            while ((line = buffer.readLine()) != null) {
+                lineNo++;
+                if (line.trim().startsWith("#")) {
+                    continue;
+                } else if (line.startsWith("  ")) {
+                    loadFieldData(object, loaded, line);
+                } else {
+                    if (object != null && !object.representsPersistent()) {
+                        getPersistenceSession().makePersistent(object);
+                    }
+                    object = loaded.get(line);
+                }
+            }
+
+            if (object != null && !object.representsPersistent()) {
+                getPersistenceSession().makePersistent(object);
+            }
+        } catch (final Exception e) {
+            throw new FixtureException("failed to load data at line " + lineNo, e);
+        }
+
+        return objects;
+    }
+
+    private void loadFieldData(final ObjectAdapter object, final LoadedObjects loaded, final String line) {
+        final int pos = line.indexOf(':');
+        if (pos == -1) {
+            throw new FixtureException("no colon (:) in: " + line.trim());
+        }
+        final String name = line.substring(0, pos).trim();
+        String data = line.substring(pos + 1).trim();
+        try {
+            final ObjectAssociation association = object.getSpecification().getAssociation(name);
+            if (data.trim().length() == 0) {
+                if (!association.isEmpty(object) && association instanceof OneToOneAssociation) {
+                    ((OneToOneAssociation) association).set(object, null);
+                }
+            } else {
+                if (association.isOneToManyAssociation()) {
+                    final String[] ids = data.split(" ");
+                    final ObjectAdapter[] elements = new ObjectAdapter[ids.length];
+                    for (int i = 0; i < ids.length; i++) {
+                        elements[i] = loaded.get(ids[i]);
+                    }
+                    final ObjectAdapter collection = association.get(object);
+                    final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
+                    facet.init(collection, elements);
+                } else if (association.getSpecification().isParseable()) {
+                    data = data.replaceAll("\\n", "\n");
+                    final ParseableFacet facet = association.getSpecification().getFacet(ParseableFacet.class);
+                    final ObjectAdapter value = facet.parseTextEntry(null, data, null);
+                    ((OneToOneAssociation) association).initAssociation(object, value);
+                } else if (association.isOneToOneAssociation()) {
+                    final ObjectAdapter value = loaded.get(data);
+                    ((OneToOneAssociation) association).initAssociation(object, value);
+                }
+            }
+        } catch (final ObjectSpecificationException e) {
+            LOG.info("no field for '" + name + "', skipping entry: " + data);
+        }
+    }
+
+    public void save(final Set<Object> objects, final Writer out) throws IOException {
+        final PrintWriter writer = new PrintWriter(out);
+        final SavedObjects saved = new SavedObjects();
+        for (final Object object : objects) {
+            final ObjectAdapter adapter = getAdapterManager().adapterFor(object);
+            saveData(writer, adapter, saved);
+        }
+        out.close();
+    }
+
+    private void saveData(final PrintWriter writer, final ObjectAdapter adapter, final SavedObjects saved) {
+        final String id = saved.getId(adapter);
+        writer.println(adapter.getSpecification().getFullIdentifier() + "#" + id);
+
+        final ObjectSpecification adapterSpec = adapter.getSpecification();
+        final List<ObjectAssociation> associations = adapterSpec.getAssociations();
+        for (final ObjectAssociation association : associations) {
+            if (association.isNotPersisted()) {
+                continue;
+            }
+
+            final ObjectAdapter associatedObject = association.get(adapter);
+            final boolean isEmpty = association.isEmpty(adapter);
+            final String associationId = association.getId();
+            writer.write("  " + associationId + ": ");
+            if (isEmpty) {
+                writer.println();
+                continue;
+            }
+
+            if (association.isOneToManyAssociation()) {
+                final CollectionFacet facet = associatedObject.getSpecification().getFacet(CollectionFacet.class);
+                for (final ObjectAdapter element : facet.iterable(associatedObject)) {
+                    final String refId = saved.getId(element);
+                    final String cls = element.getSpecification().getFullIdentifier();
+                    writer.print(cls + "#" + refId + " ");
+                }
+                writer.println();
+            } else if (association.getSpecification().isParseable()) {
+                final ParseableFacet facet = associatedObject.getSpecification().getFacet(ParseableFacet.class);
+                String encodedValue = facet.parseableTitle(associatedObject);
+                encodedValue = encodedValue.replaceAll("\n", "\\n");
+                writer.println(encodedValue);
+            } else if (association.isOneToOneAssociation()) {
+                final String refId = saved.getId(associatedObject);
+                final String cls = associatedObject.getSpecification().getFullIdentifier();
+                writer.println(cls + "#" + refId);
+            }
+        }
+    }
+
+    
+    
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected SpecificationLoaderSpi getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+}
+
+
+class LoadedObjects {
+    private final Map<String, ObjectAdapter> idMap = new HashMap<String, ObjectAdapter>();
+    private final Set<Object> objects;
+
+    public LoadedObjects(final Set<Object> objects) {
+        this.objects = objects;
+    }
+
+    public ObjectAdapter get(final String data) {
+        final int pos = data.indexOf('#');
+        if (pos == -1) {
+            throw new FixtureException("load failed - trying to read non-reference data as a reference: " + data);
+        }
+        final String id = data.substring(pos + 1);
+        ObjectAdapter object = idMap.get(id);
+        if (object == null) {
+            final String className = data.substring(0, pos);
+            final ObjectSpecification specification = getSpecificationLoader().loadSpecification(className);
+            object = getPersistenceSession().createTransientInstance(specification);
+            idMap.put(id, object);
+            objects.add(object.getObject());
+        }
+        return object;
+    }
+
+    
+    protected Persistor getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected SpecificationLoaderSpi getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
+}
+
+class SavedObjects {
+    private int id = 1;
+    private final Map<ObjectAdapter, String> idMap = new HashMap<ObjectAdapter, String>();
+
+    public String getId(final ObjectAdapter object) {
+        String idString = idMap.get(object);
+        if (idString == null) {
+            id++;
+            idMap.put(object, "" + id);
+            idString = "" + id;
+        }
+        return idString;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureService.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureService.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureService.java
new file mode 100644
index 0000000..802748f
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixturedomainservice/ObjectFixtureService.java
@@ -0,0 +1,245 @@
+/*
+ *  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.fixturedomainservice;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.applib.AbstractService;
+import org.apache.isis.applib.annotation.DescribedAs;
+import org.apache.isis.applib.annotation.Exploration;
+import org.apache.isis.applib.annotation.MemberOrder;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.Persistability;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+
+public class ObjectFixtureService {
+
+    private static final Logger LOG = Logger.getLogger(ObjectFixtureService.class);
+    private static final String DATA_FILEPATH = ConfigurationConstants.ROOT + "exploration-objects.file";
+    private static final String DEFAULT_FILEPATH = "fixture-data";
+
+    private final ObjectFixtureFilePersistor persistor = new ObjectFixtureFilePersistor();
+    private Set<Object> objects = Sets.newHashSet();
+
+    // {{ title, Id
+    public String title() {
+        return "Fixture Objects";
+    }
+
+    public String getId() {
+        return "fixtures";
+    }
+
+    public String iconName() {
+        return "Fixture";
+    }
+
+    // }}
+
+    // {{ action: save
+    @DescribedAs("Add this object to the set of saved objects")
+    @MemberOrder(sequence = "1")
+    @Exploration
+    public void save(final Object object) {
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(object);
+        if (adapter.getSpecification().persistability() != Persistability.TRANSIENT) {
+            LOG.info("Saving object for fixture: " + adapter);
+            addObjectAndAssociates(adapter);
+            saveAll();
+        }
+    }
+
+    private void addObjectAndAssociates(final ObjectAdapter adapter) {
+        if (objects.contains(adapter.getObject())) {
+            return;
+        }
+        objects.add(adapter.getObject());
+
+        final ObjectSpecification adapterSpec = adapter.getSpecification();
+        final List<ObjectAssociation> associations = adapterSpec.getAssociations();
+        for (final ObjectAssociation association : associations) {
+            if (association.isNotPersisted()) {
+                continue;
+            }
+
+            final ObjectAdapter associatedObject = association.get(adapter);
+            final boolean isEmpty = association.isEmpty(adapter);
+            if (isEmpty) {
+                continue;
+            }
+            if (association.isOneToManyAssociation()) {
+                final CollectionFacet facet = associatedObject.getSpecification().getFacet(CollectionFacet.class);
+                for (final ObjectAdapter element : facet.iterable(associatedObject)) {
+                    addObjectAndAssociates(element);
+                }
+            } else if (association.isOneToOneAssociation() && !association.getSpecification().isParseable()) {
+                addObjectAndAssociates(associatedObject);
+            }
+        }
+    }
+
+    public String validateSave(final Object object) {
+        if (object == this || object instanceof AbstractService) {
+            return "Can't add/remove a service";
+        }
+        return objects.contains(object) ? "This object has already been saved" : null;
+    }
+
+    // }}
+
+    // {{ action: remove
+    @DescribedAs("Remove this object from the set of saved objects")
+    @MemberOrder(sequence = "2")
+    @Exploration
+    public void remove(final Object object) {
+        objects.remove(object);
+        saveAll();
+    }
+
+    public String validateRemove(final Object object) {
+        if (object == this || object instanceof AbstractService) {
+            return "Can't add/remove a service";
+        }
+        return objects.contains(object) ? null : "Can't remove an object that has not been saved";
+    }
+
+    // }}
+
+    // {{ action: all Saved Objects
+    @DescribedAs("Retrieved all the saved objects")
+    @MemberOrder(sequence = "4")
+    @Exploration
+    public Set<Object> allSavedObjects() {
+        return objects;
+    }
+
+    // }}
+
+    // {{ action: saveAll
+    @DescribedAs("Save the current state of the saved objects")
+    @MemberOrder(sequence = "3")
+    @Exploration
+    public void saveAll() {
+        FileWriter out = null;
+        try {
+            final File file = file(true);
+            out = new FileWriter(file);
+            persistor.save(objects, out);
+        } catch (final IOException e) {
+            throw new IsisException(e);
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (final IOException e) {
+                    throw new IsisException(e);
+                }
+            }
+        }
+    }
+
+    // }}
+
+    // //////////////////////////////////////////////////////////////////
+    // programmatic
+    // //////////////////////////////////////////////////////////////////
+
+    // {{ loadFile (ignored)
+    @Programmatic
+    public void loadFile() {
+        FileReader reader = null;
+        try {
+            final File file = file(false);
+            reader = new FileReader(file);
+            objects = persistor.loadData(reader);
+        } catch (final FileNotFoundException e) {
+            return;
+        } catch (final IOException e) {
+            throw new IsisException(e);
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (final IOException e) {
+                    throw new IsisException(e);
+                }
+            }
+        }
+    }
+
+    private File file(final boolean createFileIfDoesntExist) throws IOException {
+        final String fixturePath = getConfiguration().getString(DATA_FILEPATH, DEFAULT_FILEPATH);
+        final File file = new File(fixturePath);
+        final File directory = file.getParentFile();
+        mkdirIfRequired(directory);
+        if (!file.exists() && createFileIfDoesntExist) {
+            createFile(file);
+        }
+        return file;
+    }
+
+    private void mkdirIfRequired(final File directory) {
+        if (directory != null && !directory.exists()) {
+            directory.mkdirs();
+        }
+    }
+
+    private void createFile(final File file) throws IOException {
+        file.createNewFile();
+    }
+    // }}
+    
+    // //////////////////////////////////////////////////////////////////
+    // from context
+    // //////////////////////////////////////////////////////////////////
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected 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/fixtures/FixturesInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstaller.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstaller.java
new file mode 100644
index 0000000..060a27e
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstaller.java
@@ -0,0 +1,49 @@
+/*
+ *  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.fixtures;
+
+import org.apache.isis.applib.fixtures.InstallableFixture;
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.components.Installer;
+
+/**
+ * A particular mechanism to install fixtures.
+ */
+public interface FixturesInstaller extends Installer {
+
+    /**
+     * NB: this has the suffix '-installer' because in the command line we must
+     * distinguish from the '--fixture' flag meaning a particular fixture to be
+     * installed.
+     */
+    static String TYPE = "fixtures-installer";
+
+    void installFixtures();
+
+    /**
+     * The {@link InstallableFixture} (if any) that is an instance of
+     * {@link LogonFixture}.
+     * 
+     * <p>
+     * If there is more than one {@link LogonFixture}, then the last one
+     * installed is returned.
+     */
+    LogonFixture getLogonFixture();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerAbstract.java
new file mode 100644
index 0000000..c10fd2c
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerAbstract.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.runtimes.dflt.runtime.fixtures;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.config.InstallerAbstract;
+
+public abstract class FixturesInstallerAbstract extends InstallerAbstract implements FixturesInstaller {
+
+    private final FixturesInstallerDelegate delegate = new FixturesInstallerDelegate();
+
+    private LogonFixture logonFixture;
+
+    public FixturesInstallerAbstract(final String name) {
+        super(FixturesInstaller.TYPE, name);
+    }
+
+    @Override
+    public void installFixtures() {
+        addFixturesTo(delegate);
+
+        delegate.installFixtures();
+        logonFixture = delegate.getLogonFixture();
+    }
+
+    /**
+     * Add fixtures to {@link FixturesInstallerDelegate#addFixture(Object)
+     * delegate}; these are then installed.
+     */
+    protected abstract void addFixturesTo(FixturesInstallerDelegate delegate);
+
+    @Override
+    public LogonFixture getLogonFixture() {
+        return logonFixture;
+    }
+
+    @Override
+    public List<Class<?>> getTypes() {
+        return Collections.emptyList();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerDelegate.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerDelegate.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerDelegate.java
new file mode 100644
index 0000000..895ebed
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerDelegate.java
@@ -0,0 +1,297 @@
+/*
+ *  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.fixtures;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.applib.fixtures.CompositeFixture;
+import org.apache.isis.applib.fixtures.FixtureType;
+import org.apache.isis.applib.fixtures.InstallableFixture;
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.applib.fixtures.userprofile.UserProfileService;
+import org.apache.isis.applib.fixtures.userprofile.UserProfileServiceAware;
+import org.apache.isis.core.commons.lang.CastUtils;
+import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+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.persistence.Persistor;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+
+/**
+ * Helper for {@link FixturesInstaller} implementations.
+ * 
+ * <p>
+ * Does the mechanics of actually installing the fixtures.
+ */
+public class FixturesInstallerDelegate {
+
+    private static final Logger LOG = Logger.getLogger(FixturesInstallerDelegate.class);
+
+    protected final List<Object> fixtures = new ArrayList<Object>();
+    private final SwitchUserServiceImpl switchUserService = new SwitchUserServiceImpl();
+    private final UserProfileService perspectivePersistenceService = new ProfileServiceImpl();
+
+    /**
+     * Optionally injected in {@link #FixtureBuilderImpl(PersistenceSession)
+     * constructor}.
+     */
+    private final PersistenceSession persistenceSession;
+
+    /**
+     * The requested {@link LogonFixture}, if any.
+     * 
+     * <p>
+     * Each fixture is inspected as it is {@link #installFixture(Object)}; if it
+     * implements {@link LogonFixture} then it is remembered so that it can be
+     * used later to automatically logon.
+     */
+    private LogonFixture logonFixture;
+
+    // /////////////////////////////////////////////////////////
+    // Constructor
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * The {@link PersistenceSession} used will be that from
+     * {@link IsisContext#getPersistenceSession() IsisContext}.
+     */
+    public FixturesInstallerDelegate() {
+        this(null);
+    }
+
+    /**
+     * For testing, supply own {@link PersistenceSession} rather than lookup
+     * from context.
+     * 
+     * @param persistenceSession
+     */
+    public FixturesInstallerDelegate(final PersistenceSession persistenceSession) {
+        this.persistenceSession = persistenceSession;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // addFixture, getFixtures, clearFixtures
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Automatically flattens any {@link List}s, recursively (depth-first) if
+     * necessary.
+     */
+    public void addFixture(final Object fixture) {
+        if (fixture instanceof List) {
+            final List<Object> fixtureList = CastUtils.listOf(fixture, Object.class);
+            for (final Object eachFixture : fixtureList) {
+                addFixture(eachFixture);
+            }
+        } else {
+            fixtures.add(fixture);
+        }
+    }
+
+    /**
+     * Returns all fixtures that have been {@link #addFixture(Object) added}.
+     */
+    protected List<Object> getFixtures() {
+        return Collections.unmodifiableList(fixtures);
+    }
+
+    /**
+     * Allows the set of fixtures to be cleared (for whatever reason).
+     */
+    public void clearFixtures() {
+        fixtures.clear();
+    }
+
+    // /////////////////////////////////////////////////////////
+    // installFixtures
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Installs all {{@link #addFixture(Object) added fixtures} fixtures (ie as
+     * returned by {@link #getFixtures()}).
+     * 
+     * <p>
+     * The set of fixtures (as per {@link #getFixtures()}) is <i>not</i> cleared
+     * after installation; this allows the {@link FixtureBuilderAbstract} to be
+     * reused across multiple tests.
+     */
+    public final void installFixtures() {
+        preInstallFixtures(getPersistenceSession());
+        installFixtures(getFixtures());
+        postInstallFixtures(getPersistenceSession());
+    }
+
+    // ///////////////////////////////////////
+    // preInstallFixtures
+    // ///////////////////////////////////////
+
+    /**
+     * Hook - default does nothing.
+     */
+    protected void preInstallFixtures(final Persistor persistenceSession) {
+    }
+
+    // ///////////////////////////////////////
+    // installFixtures, installFixture
+    // ///////////////////////////////////////
+
+    private void installFixtures(final List<Object> fixtures) {
+        for (final Object fixture : fixtures) {
+            installFixtureInTransaction(fixture);
+        }
+    }
+
+    private void installFixtureInTransaction(final Object fixture) {
+        getServicesInjector().injectServicesInto(fixture);
+
+        installFixtures(getFixtures(fixture));
+
+        // now, install the fixture itself
+        try {
+            LOG.info("installing fixture: " + fixture);
+            getTransactionManager().startTransaction();
+            installFixture(fixture);
+            saveLogonFixtureIfRequired(fixture);
+            getTransactionManager().endTransaction();
+            LOG.info("fixture installed");
+        } catch (final RuntimeException e) {
+            LOG.error("installing fixture " + fixture.getClass().getName() + " failed; aborting ", e);
+            try {
+                getTransactionManager().abortTransaction();
+            } catch (final Exception e2) {
+                LOG.error("failure during abort", e2);
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * Obtain any child fixtures for this fixture.
+     * 
+     * @param fixture
+     */
+    private List<Object> getFixtures(final Object fixture) {
+        if (fixture instanceof CompositeFixture) {
+            final CompositeFixture compositeFixture = (CompositeFixture) fixture;
+            return compositeFixture.getFixtures();
+        }
+        return Collections.emptyList();
+    }
+
+    private void installFixture(final Object fixture) {
+        switchUserService.injectInto(fixture);
+        if (fixture instanceof UserProfileServiceAware) {
+            final UserProfileServiceAware serviceAware = (UserProfileServiceAware) fixture;
+            serviceAware.setService(perspectivePersistenceService);
+        }
+
+        if (fixture instanceof InstallableFixture) {
+            final InstallableFixture installableFixture = (InstallableFixture) fixture;
+            if (shouldInstallFixture(installableFixture)) {
+                installableFixture.install();
+            }
+        }
+
+        if (fixture instanceof LogonFixture) {
+            this.logonFixture = (LogonFixture) fixture;
+        }
+    }
+
+    private boolean shouldInstallFixture(final InstallableFixture installableFixture) {
+        final FixtureType fixtureType = installableFixture.getType();
+
+        if (fixtureType == FixtureType.DOMAIN_OBJECTS) {
+            return !IsisContext.getPersistenceSession().isFixturesInstalled();
+        }
+
+        if (fixtureType == FixtureType.USER_PROFILES) {
+            return !IsisContext.getUserProfileLoader().isFixturesInstalled();
+        }
+
+        // fixtureType is OTHER; always install.
+        return true;
+    }
+
+    private void saveLogonFixtureIfRequired(final Object fixture) {
+        if (fixture instanceof LogonFixture) {
+            if (logonFixture != null) {
+                LOG.warn("Already specified logon fixture, using latest provided");
+            }
+            this.logonFixture = (LogonFixture) fixture;
+        }
+    }
+
+    // ///////////////////////////////////////
+    // postInstallFixtures
+    // ///////////////////////////////////////
+
+    /**
+     * Hook - default does nothing.
+     */
+    protected void postInstallFixtures(final Persistor persistenceSession) {
+    }
+
+    // /////////////////////////////////////////////////////////
+    // LogonFixture
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * The {@link LogonFixture}, if any.
+     * 
+     * <p>
+     * Used to automatically logon if in {@link DeploymentType#PROTOTYPE} mode.
+     */
+    public LogonFixture getLogonFixture() {
+        return logonFixture;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Dependencies (from either context or via constructor)
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Returns either the {@link IsisContext#getPersistenceSession() singleton }
+     * persistor or the persistor
+     * {@link #AbstractFixtureBuilder(PersistenceSession) specified by the
+     * constructor} if specified.
+     * 
+     * <p>
+     * Note: if a {@link PersistenceSession persistor} was specified via the
+     * constructor, this is not cached (to do so would cause the usage of tests
+     * that use the singleton to break).
+     */
+    private PersistenceSession getPersistenceSession() {
+        return persistenceSession != null ? persistenceSession : IsisContext.getPersistenceSession();
+    }
+
+    private ServicesInjectorSpi getServicesInjector() {
+        return getPersistenceSession().getServicesInjector();
+    }
+
+    private IsisTransactionManager getTransactionManager() {
+        return getPersistenceSession().getTransactionManager();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerFromConfiguration.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerFromConfiguration.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerFromConfiguration.java
new file mode 100644
index 0000000..3164853
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerFromConfiguration.java
@@ -0,0 +1,71 @@
+/*
+ *  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.fixtures;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.runtimes.dflt.runtime.fixtures.domainservice.ObjectLoaderFixture;
+
+public class FixturesInstallerFromConfiguration extends FixturesInstallerAbstract {
+
+    private static final Logger LOG = Logger.getLogger(FixturesInstallerFromConfiguration.class);
+    private static final String NAKEDOBJECTS_FIXTURES = ConfigurationConstants.ROOT + "fixtures";
+    private static final String NAKEDOBJECTS_FIXTURES_PREFIX = ConfigurationConstants.ROOT + "fixtures.prefix";
+    private static final String EXPLORATION_OBJECTS = ConfigurationConstants.ROOT + "exploration-objects";
+
+    public FixturesInstallerFromConfiguration() {
+        super("configuration");
+    }
+
+    @Override
+    protected void addFixturesTo(final FixturesInstallerDelegate delegate) {
+        String fixturePrefix = getConfiguration().getString(NAKEDOBJECTS_FIXTURES_PREFIX);
+        fixturePrefix = fixturePrefix == null ? "" : fixturePrefix.trim();
+        if (fixturePrefix.length() > 0 && !fixturePrefix.endsWith(ConfigurationConstants.DELIMITER)) {
+            fixturePrefix = fixturePrefix + ConfigurationConstants.DELIMITER;
+        }
+
+        try {
+            final String[] fixtureList = getConfiguration().getList(NAKEDOBJECTS_FIXTURES);
+            boolean fixtureLoaded = false;
+            for (final String element : fixtureList) {
+                final String fixtureFullyQualifiedName = fixturePrefix + element;
+                LOG.info("  adding fixture " + fixtureFullyQualifiedName);
+                final Object fixture = InstanceUtil.createInstance(fixtureFullyQualifiedName);
+                fixtureLoaded = true;
+                delegate.addFixture(fixture);
+            }
+            if (getConfiguration().getBoolean(EXPLORATION_OBJECTS)) {
+                delegate.addFixture(new ObjectLoaderFixture());
+            }
+            if (!fixtureLoaded) {
+                LOG.warn("No fixtures loaded from configuration");
+            }
+        } catch (final IllegalArgumentException e) {
+            throw new IsisException(e);
+        } catch (final SecurityException e) {
+            throw new IsisException(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerNoop.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerNoop.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerNoop.java
new file mode 100644
index 0000000..e549a2f
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/FixturesInstallerNoop.java
@@ -0,0 +1,44 @@
+/*
+ *  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.fixtures;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.commons.components.Noop;
+
+public class FixturesInstallerNoop extends FixturesInstallerAbstract implements Noop {
+
+    public FixturesInstallerNoop() {
+        super("noop");
+    }
+
+    @Override
+    public void installFixtures() {
+    }
+
+    @Override
+    public LogonFixture getLogonFixture() {
+        return null;
+    }
+
+    @Override
+    protected void addFixturesTo(final FixturesInstallerDelegate delegate) {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/ProfileServiceImpl.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/ProfileServiceImpl.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/ProfileServiceImpl.java
new file mode 100644
index 0000000..07d323d
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/ProfileServiceImpl.java
@@ -0,0 +1,181 @@
+/*
+ *  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.fixtures;
+
+import org.apache.isis.applib.fixtures.userprofile.UserProfileService;
+import org.apache.isis.applib.fixtures.userprofile.UserProfileServiceAware;
+import org.apache.isis.applib.profiles.Perspective;
+import org.apache.isis.applib.profiles.Profile;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.runtime.userprofile.PerspectiveEntry;
+import org.apache.isis.core.runtime.userprofile.UserProfile;
+import org.apache.isis.core.runtime.userprofile.UserProfileLoader;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+
+public class ProfileServiceImpl implements UserProfileService {
+
+    @Override
+    public Profile newUserProfile() {
+        return new ProfileImpl();
+    }
+
+    @Override
+    public Profile newUserProfile(final Profile profileTemplate) {
+        return new ProfileImpl((ProfileImpl) profileTemplate);
+    }
+
+    @Override
+    public void saveAsDefault(final Profile profile) {
+        getUserProfileLoader().saveAsDefault(createUserProfile(profile));
+    }
+
+    @Override
+    public void saveForUser(final String name, final Profile profile) {
+        getUserProfileLoader().saveForUser(name, createUserProfile(profile));
+    }
+
+    private UserProfile createUserProfile(final Profile profile) {
+        return ((ProfileImpl) profile).getUserProfile();
+    }
+
+    public void injectInto(final Object fixture) {
+        if (fixture instanceof UserProfileServiceAware) {
+            final UserProfileServiceAware serviceAware = (UserProfileServiceAware) fixture;
+            serviceAware.setService(this);
+        }
+    }
+
+    private static UserProfileLoader getUserProfileLoader() {
+        return IsisContext.getUserProfileLoader();
+    }
+
+}
+
+class ProfileImpl implements Profile {
+    private final UserProfile userProfile;
+
+    public ProfileImpl(final ProfileImpl profileTemplate) {
+        this();
+        userProfile.copy(profileTemplate.userProfile);
+    }
+
+    public ProfileImpl() {
+        userProfile = new UserProfile();
+    }
+
+    public UserProfile getUserProfile() {
+        return userProfile;
+    }
+
+    @Override
+    public void addToOptions(final String name, final String value) {
+        userProfile.addToOptions(name, value);
+    }
+
+    @Override
+    public void addToPerspectives(final Perspective perspective) {
+        userProfile.addToPerspectives(((PerspectiveImpl) perspective).getPerspectiveEntry());
+    }
+
+    @Override
+    public Perspective getPerspective(final String name) {
+        final PerspectiveEntry perspectiveEntry = userProfile.getPerspective(name);
+        if (perspectiveEntry == null) {
+            throw new IsisException("No perspective found for " + name);
+        }
+        return new PerspectiveImpl(perspectiveEntry);
+    }
+
+    @Override
+    public Perspective newPerspective(final String name) {
+        final PerspectiveEntry perspectiveEntry = userProfile.newPerspective(name);
+        return new PerspectiveImpl(perspectiveEntry);
+    }
+
+}
+
+class PerspectiveImpl implements Perspective {
+    private final PerspectiveEntry entry;
+
+    public PerspectiveImpl(final PerspectiveEntry perspectiveEntry) {
+        entry = perspectiveEntry;
+    }
+
+    public PerspectiveEntry getPerspectiveEntry() {
+        return entry;
+    }
+
+    @Override
+    public void addGenericRepository(final Class<?>... classes) {
+        for (final Class<?> cls : classes) {
+            final Object service = getPersistenceSession().getService("repository#" + cls.getName()).getObject();
+            entry.addToServices(service);
+        }
+    }
+
+    @Override
+    public void addToObjects(final Object... objects) {
+        for (final Object object : objects) {
+            entry.addToObjects(object);
+        }
+    }
+
+    @Override
+    public Object addToServices(final Class<?> serviceType) {
+        final Object service = findService(serviceType);
+        entry.addToServices(service);
+        return service;
+    }
+
+    @Override
+    public void removeFromServices(final Class<?> serviceType) {
+        final Object service = findService(serviceType);
+        entry.removeFromServices(service);
+    }
+
+    private Object findService(final Class<?> serviceType) {
+        for (final Object service : IsisContext.getServices()) {
+            if (service.getClass().isAssignableFrom(serviceType)) {
+                return service;
+            }
+        }
+        throw new IsisException("No service of type " + serviceType.getName());
+    }
+
+    @Override
+    public void addToServices(final Class<?>... classes) {
+        for (final Class<?> cls : classes) {
+            addToServices(cls);
+        }
+    }
+
+    @Override
+    public void removeFromServices(final Class<?>... classes) {
+        for (final Class<?> cls : classes) {
+            removeFromServices(cls);
+        }
+    }
+
+    protected 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/fixtures/SwitchUserServiceImpl.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/SwitchUserServiceImpl.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/SwitchUserServiceImpl.java
new file mode 100644
index 0000000..9e8ca50
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/SwitchUserServiceImpl.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.runtimes.dflt.runtime.fixtures;
+
+import java.util.List;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserService;
+import org.apache.isis.applib.fixtures.switchuser.SwitchUserServiceAware;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
+import org.apache.isis.runtimes.dflt.runtime.fixtures.authentication.AuthenticationRequestLogonFixture;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+
+public class SwitchUserServiceImpl implements SwitchUserService {
+
+    public SwitchUserServiceImpl() {
+    }
+
+    @Override
+    public void switchUser(final String username, final List<String> roles) {
+        switchUser(new LogonFixture(username, roles));
+    }
+
+    @Override
+    public void switchUser(final String username, final String... roles) {
+        switchUser(new LogonFixture(username, roles));
+    }
+
+    private void switchUser(final LogonFixture logonFixture) {
+        getTransactionManager().endTransaction();
+        IsisContext.closeSession();
+        final AuthenticationRequestLogonFixture authRequest = new AuthenticationRequestLogonFixture(logonFixture);
+        final AuthenticationSession session = getAuthenticationManager().authenticate(authRequest);
+        IsisContext.openSession(session);
+        getTransactionManager().startTransaction();
+    }
+
+    public void injectInto(final Object fixture) {
+        if (fixture instanceof SwitchUserServiceAware) {
+            final SwitchUserServiceAware serviceAware = (SwitchUserServiceAware) fixture;
+            serviceAware.setService(this);
+        }
+    }
+
+    protected AuthenticationManager getAuthenticationManager() {
+        return IsisContext.getAuthenticationManager();
+    }
+
+    protected IsisTransactionManager getTransactionManager() {
+        return IsisContext.getTransactionManager();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/authentication/AuthenticationRequestLogonFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/authentication/AuthenticationRequestLogonFixture.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/authentication/AuthenticationRequestLogonFixture.java
new file mode 100644
index 0000000..5a7dfb8
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/authentication/AuthenticationRequestLogonFixture.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.fixtures.authentication;
+
+import java.util.List;
+
+import org.apache.isis.applib.fixtures.LogonFixture;
+import org.apache.isis.core.runtime.authentication.AuthenticationRequestAbstract;
+import org.apache.isis.core.runtime.authentication.standard.AuthenticationManagerStandard;
+
+/**
+ * For testing purposes, request corresponding to a {@link LogonFixture}.
+ * 
+ * <p>
+ * Understood directly by {@link AuthenticationManagerStandard}.
+ */
+public class AuthenticationRequestLogonFixture extends AuthenticationRequestAbstract {
+
+    public AuthenticationRequestLogonFixture(final LogonFixture logonFixture) {
+        this(logonFixture.getUsername(), logonFixture.getRoles());
+    }
+
+    public AuthenticationRequestLogonFixture(final String name, final List<String> roles) {
+        super(name);
+        setRoles(roles);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/domainservice/ObjectLoaderFixture.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/domainservice/ObjectLoaderFixture.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/domainservice/ObjectLoaderFixture.java
new file mode 100644
index 0000000..cff08ff
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/domainservice/ObjectLoaderFixture.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.runtimes.dflt.runtime.fixtures.domainservice;
+
+import org.apache.isis.applib.annotation.Hidden;
+import org.apache.isis.applib.fixtures.FixtureType;
+import org.apache.isis.applib.fixtures.InstallableFixture;
+import org.apache.isis.runtimes.dflt.runtime.fixturedomainservice.ObjectFixtureService;
+
+public class ObjectLoaderFixture implements InstallableFixture {
+
+    private ObjectFixtureService service;
+
+    public void setService(final ObjectFixtureService service) {
+        this.service = service;
+    }
+
+    @Override
+    public void install() {
+        if (service != null) {
+            service.loadFile();
+        }
+    }
+
+    @Override
+    @Hidden
+    public FixtureType getType() {
+        return FixtureType.DOMAIN_OBJECTS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/package-info.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/package-info.java
new file mode 100644
index 0000000..409fc05
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/fixtures/package-info.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.
+ */
+
+/**
+ * Fixture Installer API.
+ * 
+ * <p>
+ * Used during prototyping and testing to initial objects, typically to see an
+ * in-memory object store.
+ * 
+ * @see org.apache.isis.runtimes.dflt.runtime.services.ServicesInstaller
+ */
+package org.apache.isis.runtimes.dflt.runtime.fixtures;
\ 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/installerregistry/InstallerLookup.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookup.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookup.java
new file mode 100644
index 0000000..5139848
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookup.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.runtimes.dflt.runtime.installerregistry;
+
+import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.core.commons.components.Injectable;
+import org.apache.isis.core.commons.components.Installer;
+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.metamodel.specloader.ObjectReflectorInstaller;
+import org.apache.isis.core.runtime.authentication.AuthenticationManagerInstaller;
+import org.apache.isis.core.runtime.authorization.AuthorizationManagerInstaller;
+import org.apache.isis.core.runtime.imageloader.TemplateImageLoaderInstaller;
+import org.apache.isis.runtimes.dflt.runtime.fixtures.FixturesInstaller;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.installerapi.EmbeddedWebServerInstaller;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.installerapi.IsisViewerInstaller;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.installerapi.PersistenceMechanismInstaller;
+import org.apache.isis.runtimes.dflt.runtime.services.ServicesInstaller;
+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.systemdependencyinjector.SystemDependencyInjector;
+import org.apache.isis.runtimes.dflt.runtime.userprofile.UserProfileStoreInstaller;
+
+/**
+ * The installers correspond more-or-less to the configurable top-level
+ * components of {@link IsisSystem}.
+ * 
+ * <p>
+ * The methods of {@link InstallerRepository} may be called without
+ * {@link #init() initializing} this class, but other methods may not.
+ */
+public interface InstallerLookup extends InstallerRepository, ApplicationScopedComponent, IsisConfigurationBuilderAware, Injectable, SystemDependencyInjector {
+
+    // /////////////////////////////////////////////////////////
+    // metamodel
+    // /////////////////////////////////////////////////////////
+
+    ObjectReflectorInstaller reflectorInstaller(final String requested);
+
+    // /////////////////////////////////////////////////////////
+    // framework
+    // /////////////////////////////////////////////////////////
+
+    AuthenticationManagerInstaller authenticationManagerInstaller(String requested, final DeploymentType deploymentType);
+
+    AuthorizationManagerInstaller authorizationManagerInstaller(String requested, final DeploymentType deploymentType);
+
+    FixturesInstaller fixturesInstaller(String requested);
+
+    ServicesInstaller servicesInstaller(final String requested);
+
+    TemplateImageLoaderInstaller templateImageLoaderInstaller(String requested);
+
+    PersistenceMechanismInstaller persistenceMechanismInstaller(final String requested, final DeploymentType deploymentType);
+
+    UserProfileStoreInstaller userProfilePersistenceMechanismInstaller(final String requested, DeploymentType deploymentType);
+
+    IsisViewerInstaller viewerInstaller(final String requested, final String defaultName);
+
+    IsisViewerInstaller viewerInstaller(final String requested);
+
+    EmbeddedWebServerInstaller embeddedWebServerInstaller(final String requested);
+
+    // /////////////////////////////////////////////////////////
+    // framework - generic
+    // /////////////////////////////////////////////////////////
+
+    <T extends Installer> T getInstaller(final Class<T> cls, final String requested);
+
+    <T extends Installer> T getInstaller(final Class<T> cls);
+
+    <T extends Installer> T getInstaller(final String implClassName);
+
+    // /////////////////////////////////////////////////////////
+    // configuration
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Returns a <i>snapshot</i> of the current {@link IsisConfiguration}.
+     * 
+     * <p>
+     * The {@link IsisConfiguration} could subsequently be appended to if
+     * further {@link Installer}s are loaded.
+     */
+    IsisConfiguration getConfiguration();
+
+    // /////////////////////////////////////////////////////////
+    // dependencies (injected)
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Injected.
+     */
+    IsisConfigurationBuilder getConfigurationBuilder();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookupAware.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookupAware.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookupAware.java
new file mode 100644
index 0000000..b61103e
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerLookupAware.java
@@ -0,0 +1,25 @@
+/*
+ *  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.installerregistry;
+
+public interface InstallerLookupAware {
+
+    void setInstallerLookup(final InstallerLookup installerLookup);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerRepository.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerRepository.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerRepository.java
new file mode 100644
index 0000000..8871b8e
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/InstallerRepository.java
@@ -0,0 +1,28 @@
+/*
+ *  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.installerregistry;
+
+import org.apache.isis.core.commons.components.Installer;
+
+public interface InstallerRepository {
+
+    public Installer[] getInstallers(final Class<?> cls);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/EmbeddedWebServerInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/EmbeddedWebServerInstaller.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/EmbeddedWebServerInstaller.java
new file mode 100644
index 0000000..a60ca92
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/EmbeddedWebServerInstaller.java
@@ -0,0 +1,30 @@
+/*
+ *  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.installerregistry.installerapi;
+
+import org.apache.isis.core.commons.components.Installer;
+import org.apache.isis.runtimes.dflt.runtime.web.EmbeddedWebServer;
+
+public interface EmbeddedWebServerInstaller extends Installer {
+
+    static String TYPE = "embedded-web-server";
+
+    EmbeddedWebServer createEmbeddedWebServer();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstaller.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstaller.java
new file mode 100644
index 0000000..5808dfd
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstaller.java
@@ -0,0 +1,31 @@
+/*
+ *  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.installerregistry.installerapi;
+
+import org.apache.isis.core.commons.components.Installer;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookupAware;
+import org.apache.isis.runtimes.dflt.runtime.viewer.IsisViewer;
+
+public interface IsisViewerInstaller extends Installer, InstallerLookupAware {
+
+    static String TYPE = "viewer";
+
+    IsisViewer createViewer();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstallerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstallerAbstract.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstallerAbstract.java
new file mode 100644
index 0000000..02411a9
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/IsisViewerInstallerAbstract.java
@@ -0,0 +1,63 @@
+/*
+ *  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.installerregistry.installerapi;
+
+import java.util.List;
+
+import org.apache.isis.core.commons.config.InstallerAbstract;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.InstallerLookup;
+import org.apache.isis.runtimes.dflt.runtime.systemdependencyinjector.SystemDependencyInjector;
+import org.apache.isis.runtimes.dflt.runtime.viewer.IsisViewer;
+
+public abstract class IsisViewerInstallerAbstract extends InstallerAbstract implements IsisViewerInstaller {
+
+    private SystemDependencyInjector installerLookup;
+
+    public IsisViewerInstallerAbstract(final String name) {
+        super(IsisViewerInstaller.TYPE, name);
+    }
+
+    @Override
+    public IsisViewer createViewer() {
+        return injectDependenciesInto(doCreateViewer());
+    }
+
+    /**
+     * Subclasses should override (or else override {@link #createViewer()} if
+     * they need to do anything more elaborate.
+     */
+    protected IsisViewer doCreateViewer() {
+        return null;
+    }
+
+    protected <T> T injectDependenciesInto(final T candidate) {
+        return installerLookup.injectDependenciesInto(candidate);
+    }
+
+    @Override
+    public void setInstallerLookup(final InstallerLookup installerLookup) {
+        this.installerLookup = installerLookup;
+    }
+
+    @Override
+    public List<Class<?>> getTypes() {
+        return listOf(IsisViewer.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/dbb64345/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
new file mode 100644
index 0000000..04d62ad
--- /dev/null
+++ b/framework/core/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/installerregistry/installerapi/PersistenceMechanismInstaller.java
@@ -0,0 +1,37 @@
+/*
+ *  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.installerregistry.installerapi;
+
+import org.apache.isis.core.commons.components.Installer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.PersistenceSessionFactoryDelegate;
+import org.apache.isis.runtimes.dflt.runtime.system.DeploymentType;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSessionFactory;
+
+/**
+ * Installs a {@link PersistenceSession} during system start up.
+ */
+public interface PersistenceMechanismInstaller extends Installer, PersistenceSessionFactoryDelegate {
+
+    static String TYPE = "persistor";
+
+    PersistenceSessionFactory createPersistenceSessionFactory(DeploymentType deploymentType);
+
+}