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/05 00:41:08 UTC
[11/52] [partial] ISIS-188: consolidating isis-core
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/InstallerAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/InstallerAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/InstallerAbstract.java
new file mode 100644
index 0000000..a8558c3
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/InstallerAbstract.java
@@ -0,0 +1,178 @@
+/*
+ * 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.core.commons.config;
+
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.components.Installer;
+
+public abstract class InstallerAbstract implements Installer, IsisConfigurationBuilderAware, IsisConfigurationAware {
+
+ private final String type;
+ private final String name;
+
+ private IsisConfigurationBuilder isisConfigurationBuilder;
+ private IsisConfiguration configuration;
+
+ /**
+ * Subclasses should pass in the type defined as a constant in the
+ * subinterface of Installer.
+ *
+ * <p>
+ * For example, <tt>PersistenceMechanismInstaller</tt> has a constant
+ * <tt>PersistenceMechanismInstaller#TYPE</tt>. Any implementation of
+ * <tt>PersistenceMechanismInstaller</tt> should pass this constant value up
+ * to this constructor.
+ */
+ public InstallerAbstract(final String type, final String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ @Override
+ public String getType() {
+ return type;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns <tt>[type.properties, type_name.properties</tt>.
+ *
+ * <p>
+ * For example,
+ * <tt>[persistor.properties, persistor_in-memory.properties]</tt>.
+ *
+ * @see #getType()
+ * @see #getName()
+ */
+ @Override
+ public List<String> getConfigurationResources() {
+ final List<String> resourceList = Lists.newArrayList();
+ final String componentFile = getType() + ".properties";
+ resourceList.add(componentFile);
+ final String componentImplementationFile = getType() + "_" + getName() + ".properties";
+ resourceList.add(componentImplementationFile);
+ addConfigurationResources(resourceList);
+ return Collections.unmodifiableList(resourceList);
+ }
+
+ /**
+ * Optional hook method to allow subclasses to specify any additional config
+ * resources.
+ */
+ protected void addConfigurationResources(final List<String> configurationResources) {
+ }
+
+ // ////////////////////////////////////////////////////
+ // init, shutdown
+ // ////////////////////////////////////////////////////
+
+ /**
+ * Default implementation does nothing.
+ */
+ @Override
+ public void init() {
+ // no-op implementation, subclasses may override!
+ }
+
+ /**
+ * Default implementation does nothing.
+ */
+ @Override
+ public void shutdown() {
+ // no-op implementation, subclasses may override!
+ }
+
+ /**
+ * Either this method or {@link #setConfiguration(IsisConfiguration)} should
+ * be called prior to calling {@link #getConfiguration()}.
+ *
+ * <p>
+ * If a {@link #setConfiguration(IsisConfiguration) configuration} has
+ * already been provided, then throws {@link IllegalStateException}.
+ */
+ @Override
+ public void setConfigurationBuilder(final IsisConfigurationBuilder isisConfigurationBuilder) {
+ if (configuration != null) {
+ throw new IllegalStateException("A IsisConfiguration has already been provided.");
+ }
+ this.isisConfigurationBuilder = isisConfigurationBuilder;
+ }
+
+ /**
+ * Either this method or
+ * {@link #setConfigurationBuilder(IsisConfigurationBuilder)} should be
+ * called prior to calling {@link #getConfiguration()}.
+ *
+ * <p>
+ * If a {@link #setConfigurationBuilder(IsisConfigurationBuilder)
+ * configuration builder} has already been provided, then throws
+ * {@link IllegalStateException}.
+ */
+ public void setConfiguration(final IsisConfiguration configuration) {
+ if (isisConfigurationBuilder != null) {
+ throw new IllegalStateException("A IsisConfigurationBuilder has already been provided.");
+ }
+ this.configuration = configuration;
+ }
+
+ /**
+ * Returns a <i>snapshot</i> of the current configuration provided by the
+ * {@link #setConfigurationBuilder(IsisConfigurationBuilder) injected}
+ * {@link IsisConfigurationBuilder}.
+ *
+ * <p>
+ * Implementation note: the implementation is in fact just
+ * {@link InstallerLookupDefault}.
+ */
+ public IsisConfiguration getConfiguration() {
+ if (isisConfigurationBuilder != null) {
+ return isisConfigurationBuilder.getConfiguration();
+ } else if (configuration != null) {
+ return configuration;
+ } else {
+ throw new IllegalStateException("Neither a ConfigurationBuilder nor Configuration has not been provided");
+ }
+ }
+
+ /**
+ * Helper for subclasses implementing {@link #getTypes()}.
+ */
+ protected static List<Class<?>> listOf(final Class<?>... classes) {
+ return Collections.unmodifiableList(Lists.<Class<?>> newArrayList(classes));
+ }
+
+ /**
+ * Helper for subclasses implementing {@link #getTypes()}.
+ */
+ protected static List<Class<?>> listOf(final List<Class<?>> classList, final Class<?>... classes) {
+ final List<Class<?>> arrayList = Lists.<Class<?>> newArrayList(classes);
+ arrayList.addAll(0, classList);
+ return Collections.unmodifiableList(arrayList);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
new file mode 100644
index 0000000..f2581f0
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfiguration.java
@@ -0,0 +1,192 @@
+/*
+ * 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.core.commons.config;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.isis.core.commons.components.Injectable;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+
+/**
+ * Immutable set of properties representing the configuration of the running
+ * system.
+ *
+ * <p>
+ * The {@link IsisConfiguration} is one part of a mutable/immutable pair pattern
+ * (cf {@link String} and {@link StringBuilder}). What this means is, as
+ * components are loaded they can discover their own configuration resources.
+ * These are added to {@link IsisConfigurationBuilder}.
+ *
+ * <p>
+ * Thus the {@link IsisConfiguration} held by different components may vary, but
+ * with each being a possible superset of the previous.
+ */
+public interface IsisConfiguration extends DebuggableWithTitle, Injectable, Iterable<String> {
+
+ /**
+ * Creates a new IsisConfiguration containing the properties starting with
+ * the specified prefix. The names of the new properties will have the
+ * prefixed stripped. This is similar to the {@link #getProperties(String)}
+ * method, except the property names have their prefixes removed.
+ *
+ * @see #getProperties(String)
+ */
+ IsisConfiguration createSubset(String prefix);
+
+ /**
+ * Gets the boolean value for the specified name where no value or 'on' will
+ * result in true being returned; anything gives false. If no boolean
+ * property is specified with this name then false is returned.
+ *
+ * @param name
+ * the property name
+ */
+ boolean getBoolean(String name);
+
+ /**
+ * Gets the boolean value for the specified name. If no property is
+ * specified with this name then the specified default boolean value is
+ * returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ boolean getBoolean(String name, boolean defaultValue);
+
+ /**
+ * Gets the color for the specified name. If no color property is specified
+ * with this name then null is returned.
+ *
+ * @param name
+ * the property name
+ */
+ Color getColor(String name);
+
+ /**
+ * Gets the color for the specified name. If no color property is specified
+ * with this name then the specified default color is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ Color getColor(String name, Color defaultValue);
+
+ /**
+ * Gets the font for the specified name. If no font property is specified
+ * with this name then null is returned.
+ *
+ * @param name
+ * the property name
+ */
+ Font getFont(String name);
+
+ /**
+ * Gets the font for the specified name. If no font property is specified
+ * with this name then the specified default font is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the color to use as a default
+ */
+ Font getFont(String name, Font defaultValue);
+
+ /**
+ * Returns a list of entries for the single configuration property with the
+ * specified name.
+ *
+ * <p>
+ * If there is no matching property then returns an empty array.
+ */
+ String[] getList(String name);
+
+ /**
+ * Gets the number value for the specified name. If no property is specified
+ * with this name then 0 is returned.
+ *
+ * @param name
+ * the property name
+ */
+ int getInteger(String name);
+
+ /**
+ * Gets the number value for the specified name. If no property is specified
+ * with this name then the specified default number value is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ int getInteger(String name, int defaultValue);
+
+ /**
+ * Creates a new IsisConfiguration containing the properties starting with
+ * the specified prefix. The names of the properties in the copy are the
+ * same as in the original, ie the prefix is not removed. This is similar to
+ * the {@link #createSubset(String)} method except the names of the
+ * properties are not altered when copied.
+ *
+ * @see #createSubset(String)
+ */
+ IsisConfiguration getProperties(String withPrefix);
+
+ /**
+ * Returns the configuration property with the specified name. If there is
+ * no matching property then null is returned.
+ */
+ String getString(String name);
+
+ String getString(String name, String defaultValue);
+
+ boolean hasProperty(String name);
+
+ boolean isEmpty();
+
+ /**
+ * Iterates over the property names of this configuration.
+ */
+ @Override
+ Iterator<String> iterator();
+
+ int size();
+
+ /**
+ * The {@link ResourceStreamSource} that was used to build this
+ * configuration.
+ *
+ * @see IsisConfigurationBuilder#getResourceStreamSource()
+ */
+ ResourceStreamSource getResourceStreamSource();
+
+ /**
+ * A mutable copy of the current set of properties (name/values) held in this configuration.
+ */
+ Map<String, String> asMap();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationAware.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationAware.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationAware.java
new file mode 100644
index 0000000..09bc9f3
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationAware.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.commons.config;
+
+/**
+ * Allows components (eg facet factories) to indicate that they have a
+ * dependency on {@link IsisConfiguration}.
+ */
+public interface IsisConfigurationAware {
+
+ /**
+ * Inject the {@link IsisConfiguration} into the component.
+ */
+ void setConfiguration(IsisConfiguration configuration);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilder.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilder.java
new file mode 100644
index 0000000..ddfa5ea
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * 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.core.commons.config;
+
+import java.util.Properties;
+
+import org.apache.isis.core.commons.components.Injectable;
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceChainOfResponsibility;
+
+/**
+ * Holds a mutable set of properties representing the configuration.
+ *
+ * <p>
+ * Mutable/immutable pair with the {@link IsisConfiguration}. To obtain the
+ * configuration, use {@link #getConfiguration()}.
+ *
+ * @see IsisConfiguration for more details on the mutable/immutable pair
+ * pattern.
+ */
+public interface IsisConfigurationBuilder extends Injectable {
+
+ /**
+ * Returns a currently known {@link IsisConfiguration}.
+ */
+ IsisConfiguration getConfiguration();
+
+ public abstract void addConfigurationResource(final String installerName, final NotFoundPolicy notFoundPolicy);
+
+ public abstract void add(final Properties properties);
+
+ public abstract void add(final String key, final String value);
+
+ /**
+ * The underlying {@link ResourceStreamSource} from which the configuration
+ * is being read.
+ *
+ * <p>
+ * Note that this may be a {@link ResourceStreamSourceChainOfResponsibility composite}.
+ */
+ public ResourceStreamSource getResourceStreamSource();
+
+ /**
+ * Log a summary of resources found or not found.
+ */
+ public void dumpResourcesToLog();
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderAware.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderAware.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderAware.java
new file mode 100644
index 0000000..07023b7
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderAware.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.core.commons.config;
+
+public interface IsisConfigurationBuilderAware {
+
+ void setConfigurationBuilder(IsisConfigurationBuilder configurationLoader);
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderDefault.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderDefault.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderDefault.java
new file mode 100644
index 0000000..ffa710e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderDefault.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.commons.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.google.common.collect.Lists;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceContextLoaderClassPath;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
+
+/**
+ * Convenience implementation of {@link IsisConfigurationBuilder} that loads
+ * configuration resource as per {@link IsisConfigurationBuilderFileSystem} and
+ * otherwise from the {@link ResourceStreamSourceContextLoaderClassPath
+ * classpath}.
+ *
+ * @see ResourceStreamSourceFileSystem
+ */
+public class IsisConfigurationBuilderDefault extends IsisConfigurationBuilderResourceStreams {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = Logger.getLogger(IsisConfigurationBuilderDefault.class);
+
+ public IsisConfigurationBuilderDefault() {
+ super(resourceStreamSources(null));
+ }
+
+ public IsisConfigurationBuilderDefault(final String firstDirectory) {
+ super(resourceStreamSources(firstDirectory));
+ }
+
+ private static ResourceStreamSource[] resourceStreamSources(final String firstDirectory) {
+ final ArrayList<ResourceStreamSource> rssList = Lists.newArrayList();
+ if (firstDirectory != null) {
+ rssList.add(fromFileSystem(firstDirectory));
+ }
+ rssList.addAll(Arrays.asList(fromFileSystem(ConfigurationConstants.DEFAULT_CONFIG_DIRECTORY), fromFileSystem(ConfigurationConstants.WEBINF_FULL_DIRECTORY), fromClassPath(), fromClassPath(ConfigurationConstants.WEBINF_DIRECTORY)));
+ return rssList.toArray(new ResourceStreamSource[0]);
+ }
+
+ private static ResourceStreamSource fromFileSystem(final String directory) {
+ return ResourceStreamSourceFileSystem.create(directory);
+ }
+
+ private static ResourceStreamSource fromClassPath() {
+ return ResourceStreamSourceContextLoaderClassPath.create();
+ }
+
+ private static ResourceStreamSource fromClassPath(final String prefix) {
+ return ResourceStreamSourceContextLoaderClassPath.create(prefix);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderFileSystem.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderFileSystem.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderFileSystem.java
new file mode 100644
index 0000000..825b25f
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderFileSystem.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.commons.config;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceChainOfResponsibility;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
+
+/**
+ * Convenience implementation of {@link IsisConfigurationBuilder} that loads
+ * configuration resource from a specified directory (or directories) on the
+ * filesystem.
+ *
+ * @see ResourceStreamSourceFileSystem
+ */
+public class IsisConfigurationBuilderFileSystem extends IsisConfigurationBuilderResourceStreams {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = Logger.getLogger(IsisConfigurationBuilderFileSystem.class);
+
+ private static ResourceStreamSource createResourceStreamSource(final String... directories) {
+ final ResourceStreamSourceChainOfResponsibility composite = new ResourceStreamSourceChainOfResponsibility();
+ for (final String directory : directories) {
+ composite.addResourceStreamSource(new ResourceStreamSourceFileSystem(directory));
+ }
+ return composite;
+ }
+
+ public IsisConfigurationBuilderFileSystem(final String... directories) {
+ super(createResourceStreamSource(directories));
+ }
+
+ public IsisConfigurationBuilderFileSystem() {
+ super(ResourceStreamSourceFileSystem.create(ConfigurationConstants.DEFAULT_CONFIG_DIRECTORY));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderPrimer.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderPrimer.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderPrimer.java
new file mode 100644
index 0000000..70e4df8
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderPrimer.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.commons.config;
+
+public interface IsisConfigurationBuilderPrimer {
+
+ void primeConfigurationBuilder(IsisConfigurationBuilder isisConfigurationBuilder);
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderResourceStreams.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderResourceStreams.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderResourceStreams.java
new file mode 100644
index 0000000..bdab1a1
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationBuilderResourceStreams.java
@@ -0,0 +1,328 @@
+/*
+ * 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.core.commons.config;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Sets;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceChainOfResponsibility;
+import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
+
+/**
+ * Adapter for {@link IsisConfigurationBuilder}, loading the specified
+ * configuration resource (file) from the given {@link ResourceStreamSource}(s).
+ *
+ * <p>
+ * If a property is in multiple configuration resources then the latter
+ * resources will overwrite the former.
+ */
+public class IsisConfigurationBuilderResourceStreams implements IsisConfigurationBuilder {
+
+ private static final Logger LOG = Logger.getLogger(IsisConfigurationBuilderResourceStreams.class);
+
+ private final Set<String> configurationResourcesFound = Sets.newLinkedHashSet();
+ private final Set<String> configurationResourcesNotFound = Sets.newLinkedHashSet();
+
+ static class ConfigurationResourceAndPolicy {
+ private final String configurationResource;
+ private final NotFoundPolicy notFoundPolicy;
+
+ public ConfigurationResourceAndPolicy(final String configurationResource, final NotFoundPolicy notFoundPolicy) {
+ this.configurationResource = configurationResource;
+ this.notFoundPolicy = notFoundPolicy;
+ }
+
+ public String getConfigurationResource() {
+ return configurationResource;
+ }
+
+ public NotFoundPolicy getNotFoundPolicy() {
+ return notFoundPolicy;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s{%s}", configurationResource, notFoundPolicy);
+ }
+ }
+
+ private final ResourceStreamSource resourceStreamSource;
+
+ private final List<ConfigurationResourceAndPolicy> configurationResources = new ArrayList<ConfigurationResourceAndPolicy>();
+ private final Properties additionalProperties = new Properties();
+ private boolean includeSystemProperties = false;
+
+ /**
+ * Most recent snapshot of {@link IsisConfiguration} obtained from
+ * {@link #configurationLoader}.
+ *
+ * <p>
+ * Whenever further configuration is merged in, this cache is invalidated.
+ */
+ private IsisConfiguration cachedConfiguration;
+
+ // ////////////////////////////////////////////////////////////
+ // Constructor, initialization
+ // ////////////////////////////////////////////////////////////
+
+ private static ResourceStreamSource createComposite(final ResourceStreamSource... resourceStreamSources) {
+ final ResourceStreamSourceChainOfResponsibility composite = new ResourceStreamSourceChainOfResponsibility();
+ for (final ResourceStreamSource rss : resourceStreamSources) {
+ if (rss == null) {
+ continue;
+ }
+ composite.addResourceStreamSource(rss);
+ }
+ return composite;
+ }
+
+ public IsisConfigurationBuilderResourceStreams() {
+ this(ResourceStreamSourceFileSystem.create(ConfigurationConstants.DEFAULT_CONFIG_DIRECTORY));
+ }
+
+ public IsisConfigurationBuilderResourceStreams(final ResourceStreamSource... resourceStreamSources) {
+ this(createComposite(resourceStreamSources));
+ }
+
+ public IsisConfigurationBuilderResourceStreams(final ResourceStreamSource resourceStreamSource) {
+ this.resourceStreamSource = resourceStreamSource;
+ addDefaultConfigurationResources();
+ }
+
+ /**
+ * May be overridden by subclasses if required.
+ */
+ protected void addDefaultConfigurationResources() {
+ addConfigurationResource(ConfigurationConstants.DEFAULT_CONFIG_FILE, NotFoundPolicy.FAIL_FAST);
+ addConfigurationResource(ConfigurationConstants.WEB_CONFIG_FILE, NotFoundPolicy.CONTINUE);
+ }
+
+ // ////////////////////////////////////////////////////////////
+ // ResourceStreamSource
+ // ////////////////////////////////////////////////////////////
+
+ @Override
+ public ResourceStreamSource getResourceStreamSource() {
+ return resourceStreamSource;
+ }
+
+ // ////////////////////////////////////////////////////////////
+ // populating or updating
+ // ////////////////////////////////////////////////////////////
+
+ /**
+ * Registers the configuration resource (usually, a file) with the specified
+ * name from the first {@link ResourceStreamSource} available.
+ *
+ * <p>
+ * If the configuration resource cannot be found then the provided
+ * {@link NotFoundPolicy} determines whether an exception is thrown or not.
+ *
+ * <p>
+ * Must be called before {@link #getConfiguration()}; the resource is
+ * actually read on {@link #getConfiguration()}.
+ */
+ @Override
+ public synchronized void addConfigurationResource(final String configurationResource, final NotFoundPolicy notFoundPolicy) {
+ configurationResources.add(new ConfigurationResourceAndPolicy(configurationResource, notFoundPolicy));
+ invalidateCache();
+ }
+
+ public synchronized void setIncludeSystemProperties(final boolean includeSystemProperties) {
+ this.includeSystemProperties = includeSystemProperties;
+ invalidateCache();
+ }
+
+ /**
+ * Adds additional property.
+ */
+ @Override
+ public synchronized void add(final String key, final String value) {
+ if (key == null || value == null) {
+ return;
+ }
+ additionalProperties.setProperty(key, value);
+ if (LOG.isInfoEnabled()) {
+ LOG.info("added " + key + "=" + value);
+ }
+ invalidateCache();
+ }
+
+ /**
+ * Adds additional properties.
+ */
+ @Override
+ public synchronized void add(final Properties properties) {
+ final Enumeration<?> keys = properties.propertyNames();
+ while (keys.hasMoreElements()) {
+ final String key = (String) keys.nextElement();
+ add(key, properties.getProperty(key));
+ }
+ invalidateCache();
+ }
+
+ // ////////////////////////////////////////////////////////////
+ // getConfiguration
+ // ////////////////////////////////////////////////////////////
+
+ /**
+ * Returns the current {@link IsisConfiguration configuration}.
+ */
+ @Override
+ public synchronized IsisConfiguration getConfiguration() {
+ if (cachedConfiguration != null) {
+ return cachedConfiguration;
+ }
+
+ final IsisConfigurationDefault configuration = new IsisConfigurationDefault(getResourceStreamSource());
+ loadConfigurationResources(configuration);
+ // TODO: this hack should move elsewhere, where the DeploymentType is
+ // known.
+ addShowExplorationOptionsIfNotSpecified(configuration);
+ addSystemPropertiesIfRequested(configuration);
+ addAdditionalProperties(configuration);
+ return cachedConfiguration = configuration;
+ }
+
+ private void loadConfigurationResources(final IsisConfigurationDefault configuration) {
+ for (final ConfigurationResourceAndPolicy configResourceAndPolicy : configurationResources) {
+ loadConfigurationResource(configuration, configResourceAndPolicy);
+ }
+ }
+
+ private void loadConfigurationResource(final IsisConfigurationDefault configuration, final ConfigurationResourceAndPolicy configResourceAndPolicy) {
+ final String configurationResource = configResourceAndPolicy.getConfigurationResource();
+ final NotFoundPolicy notFoundPolicy = configResourceAndPolicy.getNotFoundPolicy();
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("loading configuration resource: " + configurationResource + ", notFoundPolicy: " + notFoundPolicy);
+ }
+ loadConfigurationResource(configuration, configurationResource, notFoundPolicy);
+ }
+
+ /**
+ * Loads the configuration resource (usually, a file) with the specified
+ * name from the first {@link ResourceStreamSource} available.
+ *
+ * <p>
+ * If the configuration resource cannot be found then the provided
+ * {@link NotFoundPolicy} determines whether an exception is thrown or not.
+ */
+ protected void loadConfigurationResource(final IsisConfigurationDefault configuration, final String configurationResource, final NotFoundPolicy notFoundPolicy) {
+ try {
+ final PropertiesReader propertiesReader = loadConfigurationResource(resourceStreamSource, configurationResource);
+ addProperties(configuration, propertiesReader.getProperties());
+ configurationResourcesFound.add(configurationResource);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("'" + configurationResource + "' FOUND");
+ }
+ return;
+ } catch (final IOException ex) {
+ // keep going
+ }
+ if (notFoundPolicy == NotFoundPolicy.FAIL_FAST) {
+ throw new IsisException("failed to load '" + configurationResource + "'; tried using: " + resourceStreamSource.getName());
+ } else {
+ configurationResourcesNotFound.add(configurationResource);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("'" + configurationResource + "' not found, but not needed");
+ }
+ }
+ }
+
+ private PropertiesReader loadConfigurationResource(final ResourceStreamSource resourceStreamSource, final String configurationResource) throws IOException {
+ return new PropertiesReader(resourceStreamSource, configurationResource);
+ }
+
+ private void addShowExplorationOptionsIfNotSpecified(final IsisConfigurationDefault configuration) {
+ if (configuration.getString(ConfigurationConstants.SHOW_EXPLORATION_OPTIONS) == null) {
+ configuration.add(ConfigurationConstants.SHOW_EXPLORATION_OPTIONS, "yes");
+ }
+ }
+
+ private void addSystemPropertiesIfRequested(final IsisConfigurationDefault configuration) {
+ if (includeSystemProperties) {
+ addProperties(configuration, System.getProperties());
+ }
+ }
+
+ private void addAdditionalProperties(final IsisConfigurationDefault configuration) {
+ addProperties(configuration, additionalProperties);
+ }
+
+ protected void addProperties(final IsisConfigurationDefault configuration, final Properties properties) {
+ configuration.add(properties);
+ }
+
+ private void invalidateCache() {
+ cachedConfiguration = null;
+ }
+
+
+
+ // ////////////////////////////////////////////////////////////
+ // Logging
+ // ////////////////////////////////////////////////////////////
+
+ @Override
+ public void dumpResourcesToLog() {
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Configuration resources FOUND:");
+ for (String resource : configurationResourcesFound) {
+ LOG.info("* " + resource);
+ }
+ }
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Configuration resources NOT FOUND (but not needed):");
+ for (String resource : configurationResourcesNotFound) {
+ LOG.info("* " + resource);
+ }
+ }
+ }
+
+
+ // ////////////////////////////////////////////////////////////
+ // Injectable
+ // ////////////////////////////////////////////////////////////
+
+ @Override
+ public void injectInto(final Object candidate) {
+ if (IsisConfigurationBuilderAware.class.isAssignableFrom(candidate.getClass())) {
+ final IsisConfigurationBuilderAware cast = IsisConfigurationBuilderAware.class.cast(candidate);
+ cast.setConfigurationBuilder(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this).add("resourceStream", resourceStreamSource).add("configResources", configurationResources).toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationDefault.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationDefault.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationDefault.java
new file mode 100644
index 0000000..351efba
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationDefault.java
@@ -0,0 +1,397 @@
+/*
+ * 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.core.commons.config;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import com.google.common.collect.Maps;
+
+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.resource.ResourceStreamSource;
+
+public class IsisConfigurationDefault implements IsisConfiguration {
+
+ private static final Logger LOG = Logger.getLogger(IsisConfigurationDefault.class);
+ private final Properties properties = new Properties();
+ private final ResourceStreamSource resourceStreamSource;
+
+ // ////////////////////////////////////////////////
+ // Constructor
+ // ////////////////////////////////////////////////
+
+ public IsisConfigurationDefault() {
+ this(null);
+ }
+
+ public IsisConfigurationDefault(final ResourceStreamSource resourceStreamSource) {
+ this.resourceStreamSource = resourceStreamSource;
+ LOG.debug("from :" + nameOf(resourceStreamSource));
+ }
+
+ private String nameOf(final ResourceStreamSource resourceStreamSource) {
+ return resourceStreamSource != null ? resourceStreamSource.getName() : null;
+ }
+
+ // ////////////////////////////////////////////////
+ // ResourceStreamSource
+ // ////////////////////////////////////////////////
+
+ @Override
+ public ResourceStreamSource getResourceStreamSource() {
+ return resourceStreamSource;
+ }
+
+ // ////////////////////////////////////////////////
+ // add
+ // ////////////////////////////////////////////////
+
+ /**
+ * Add the properties from an existing Properties object.
+ */
+ public void add(final Properties properties) {
+ for(Object key: properties.keySet()) {
+ Object value = properties.get(key);
+ add((String)key, (String)value);
+ }
+ }
+
+ /**
+ * Adds a key-value pair to this set of properties
+ */
+ public void add(final String key, final String value) {
+ if (key == null) {
+ return;
+ }
+ if (properties.containsKey(key)) {
+ LOG.info("replacing " + key + "=" + properties.get(key) + " with " + value);
+ }
+ properties.put(key, value);
+ }
+
+ @Override
+ public IsisConfiguration createSubset(final String prefix) {
+ final IsisConfigurationDefault subset = new IsisConfigurationDefault(resourceStreamSource);
+
+ String startsWith = prefix;
+ if (!startsWith.endsWith(".")) {
+ startsWith = startsWith + '.';
+ }
+ final int prefixLength = startsWith.length();
+
+ for(Object keyObj: properties.keySet()) {
+ final String key = (String)keyObj;
+ if (key.startsWith(startsWith)) {
+ final String modifiedKey = key.substring(prefixLength);
+ subset.properties.put(modifiedKey, properties.get(key));
+ }
+ }
+ return subset;
+ }
+
+ // ////////////////////////////////////////////////
+ // getXxx
+ // ////////////////////////////////////////////////
+
+ /**
+ * Gets the boolean value for the specified name where no value or 'on' will
+ * result in true being returned; anything gives false. If no boolean
+ * property is specified with this name then false is returned.
+ *
+ * @param name
+ * the property name
+ */
+ @Override
+ public boolean getBoolean(final String name) {
+ return getBoolean(name, false);
+ }
+
+ /**
+ * Gets the boolean value for the specified name. If no property is
+ * specified with this name then the specified default boolean value is
+ * returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ @Override
+ public boolean getBoolean(final String name, final boolean defaultValue) {
+ String value = getProperty(name);
+ if (value == null) {
+ return defaultValue;
+ }
+ value = value.toLowerCase();
+ if (value.equals("on") || value.equals("yes") || value.equals("true") || value.equals("")) {
+ return true;
+ }
+ if (value.equals("off") || value.equals("no") || value.equals("false")) {
+ return false;
+ }
+
+ throw new IsisConfigurationException("Illegal flag for " + name + "; must be one of on, off, yes, no, true or false");
+ }
+
+ /**
+ * Gets the color for the specified name. If no color property is specified
+ * with this name then null is returned.
+ *
+ * @param name
+ * the property name
+ */
+ @Override
+ public Color getColor(final String name) {
+ return getColor(name, null);
+ }
+
+ /**
+ * Gets the color for the specified name. If no color property is specified
+ * with this name then the specified default color is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ @Override
+ public Color getColor(final String name, final Color defaultValue) {
+ final String color = getProperty(name);
+
+ if (color == null) {
+ return defaultValue;
+ }
+
+ return Color.decode(color);
+ }
+
+ @Override
+ public void debugData(final DebugBuilder str) {
+ str.appendln("Resource Stream Source", resourceStreamSource);
+ str.appendln();
+ final Enumeration<?> names = properties.propertyNames();
+ while (names.hasMoreElements()) {
+ final String name = (String) names.nextElement();
+ str.append(name, 55);
+ str.append(" = ");
+ str.appendln(properties.getProperty(name));
+ }
+ }
+
+ @Override
+ public String debugTitle() {
+ return "Properties Configuration";
+ }
+
+ /**
+ * Gets the font for the specified name. If no font property is specified
+ * with this name then null is returned.
+ *
+ * @param name
+ * the property name
+ */
+ @Override
+ public Font getFont(final String name) {
+ return getFont(name, null);
+ }
+
+ /**
+ * Gets the font for the specified name. If no font property is specified
+ * with this name then the specified default font is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the color to use as a default
+ */
+ @Override
+ public Font getFont(final String name, final Font defaultValue) {
+ final String font = getProperty(name);
+
+ if (font == null) {
+ return defaultValue;
+ }
+
+ return Font.decode(font);
+ }
+
+ /**
+ * Gets the number value for the specified name. If no property is specified
+ * with this name then 0 is returned.
+ *
+ * @param name
+ * the property name
+ */
+ @Override
+ public int getInteger(final String name) {
+ return getInteger(name, 0);
+ }
+
+ /**
+ * Gets the number value for the specified name. If no property is specified
+ * with this name then the specified default number value is returned.
+ *
+ * @param name
+ * the property name
+ * @param defaultValue
+ * the value to use as a default
+ */
+ @Override
+ public int getInteger(final String name, final int defaultValue) {
+ final String value = getProperty(name);
+
+ if (value == null) {
+ return defaultValue;
+ }
+
+ return Integer.valueOf(value).intValue();
+ }
+
+ @Override
+ public String[] getList(final String name) {
+ final String list = getString(name);
+ if (list == null) {
+ return new String[0];
+ } else {
+ final StringTokenizer tokens = new StringTokenizer(list, ConfigurationConstants.LIST_SEPARATOR);
+ final String array[] = new String[tokens.countTokens()];
+ int i = 0;
+ while (tokens.hasMoreTokens()) {
+ array[i++] = tokens.nextToken().trim();
+ }
+ return array;
+ }
+ }
+
+ @Override
+ public IsisConfiguration getProperties(final String withPrefix) {
+ final int prefixLength = "".length();
+
+ final Properties pp = new Properties();
+ final Enumeration<?> e = properties.keys();
+ while (e.hasMoreElements()) {
+ final String key = (String) e.nextElement();
+ if (key.startsWith(withPrefix)) {
+ final String modifiedKey = key.substring(prefixLength);
+ pp.put(modifiedKey, properties.get(key));
+ }
+ }
+ final IsisConfigurationDefault isisConfigurationDefault = new IsisConfigurationDefault(resourceStreamSource);
+ isisConfigurationDefault.add(pp);
+ return isisConfigurationDefault;
+ }
+
+ private String getProperty(final String name) {
+ return getProperty(name, null);
+ }
+
+ private String getProperty(final String name, final String defaultValue) {
+ final String key = referedToAs(name);
+ if (key.indexOf("..") >= 0) {
+ throw new IsisException("property names should not have '..' within them: " + name);
+ }
+ String property = properties.getProperty(key, defaultValue);
+ property = property != null ? property.trim() : null;
+ LOG.debug("property: '" + key + "' = '" + property + "'");
+ return property;
+ }
+
+ /**
+ * Returns the configuration property with the specified name. If there is
+ * no matching property then null is returned.
+ */
+ @Override
+ public String getString(final String name) {
+ return getProperty(name);
+ }
+
+ @Override
+ public String getString(final String name, final String defaultValue) {
+ return getProperty(name, defaultValue);
+ }
+
+ @Override
+ public boolean hasProperty(final String name) {
+ final String key = referedToAs(name);
+ return properties.containsKey(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return properties.isEmpty();
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return properties.stringPropertyNames().iterator();
+ }
+
+ /**
+ * Returns as a String that the named property is refered to as. For example
+ * in a simple properties file the property z might be specified in the file
+ * as x.y.z.
+ */
+ private String referedToAs(final String name) {
+ return name;
+ }
+
+ @Override
+ public int size() {
+ return properties.size();
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigurationParameters [properties=" + properties + "]";
+ }
+
+ // ////////////////////////////////////////////////////////////////////
+ // injectInto
+ // ////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void injectInto(final Object candidate) {
+ if (IsisConfigurationAware.class.isAssignableFrom(candidate.getClass())) {
+ final IsisConfigurationAware cast = IsisConfigurationAware.class.cast(candidate);
+ cast.setConfiguration(this);
+ }
+ }
+
+ @Override
+ public Map<String,String> asMap() {
+ final Map<String, String> map = Maps.newHashMap();
+ for(String propertyName: this) {
+ final String propertyValue = this.getProperty(propertyName);
+ map.put(propertyName, propertyValue);
+ }
+ return map;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationException.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationException.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationException.java
new file mode 100644
index 0000000..706d969
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/IsisConfigurationException.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.core.commons.config;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public class IsisConfigurationException extends IsisException {
+ private static final long serialVersionUID = 1L;
+
+ public IsisConfigurationException() {
+ super();
+ }
+
+ public IsisConfigurationException(final String s) {
+ super(s);
+ }
+
+ public IsisConfigurationException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+ public IsisConfigurationException(final Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/JmxBeanServer.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/JmxBeanServer.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/JmxBeanServer.java
new file mode 100644
index 0000000..c336267
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/JmxBeanServer.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.core.commons.config;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.apache.log4j.Logger;
+
+public class JmxBeanServer {
+
+ private static final Logger LOG = Logger.getLogger(JmxBeanServer.class);
+
+ private static JmxBeanServer instance;
+ private final MBeanServer server;
+
+ private JmxBeanServer() {
+ server = ManagementFactory.getPlatformMBeanServer();
+ instance = this;
+ }
+
+ public static JmxBeanServer getInstance() {
+ if (instance == null) {
+ LOG.info("JMX bean server created");
+ instance = new JmxBeanServer();
+ }
+ return instance;
+ }
+
+ public void register(final String name, final Object object) {
+ try {
+ final ObjectName objectName = new ObjectName("Isis:name=" + name);
+ server.registerMBean(object, objectName);
+ LOG.info(name + " JMX mbean registered: " + object);
+ } catch (final MalformedObjectNameException e) {
+ throw new RuntimeException(e);
+ } catch (final NullPointerException e) {
+ throw new RuntimeException(e);
+ } catch (final InstanceAlreadyExistsException e) {
+ LOG.info(name + " JMX mbean already registered: " + object);
+ } catch (final MBeanRegistrationException e) {
+ throw new RuntimeException(e);
+ } catch (final NotCompliantMBeanException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+}
+
+// Copyright (c) Naked Objects Group Ltd.
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/NotFoundPolicy.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/NotFoundPolicy.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/NotFoundPolicy.java
new file mode 100644
index 0000000..0ab7b81
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/NotFoundPolicy.java
@@ -0,0 +1,24 @@
+/*
+ * 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.core.commons.config;
+
+public enum NotFoundPolicy {
+ CONTINUE, FAIL_FAST
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/PropertiesReader.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/PropertiesReader.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/PropertiesReader.java
new file mode 100644
index 0000000..fa8465e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/PropertiesReader.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.core.commons.config;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.isis.core.commons.lang.IoUtils;
+import org.apache.isis.core.commons.resource.ResourceStreamSource;
+
+/**
+ * Loads properties using the specified {@link ResourceStreamSource}.
+ */
+class PropertiesReader {
+
+ private final Properties properties = new Properties();
+
+ public PropertiesReader(final ResourceStreamSource resourceStream, final String configurationResource) throws IOException {
+
+ InputStream in = null;
+ try {
+ in = resourceStream.readResource(configurationResource);
+ if (in == null) {
+ throw new IOException("Unable to find resource " + configurationResource);
+ }
+ properties.load(in);
+ } finally {
+ IoUtils.closeSafely(in);
+ }
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/package-info.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/package-info.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/package-info.java
new file mode 100644
index 0000000..db80586
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/config/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * Defines the {@link org.apache.isis.core.commons.config.IsisConfiguration}
+ * which collects an immutable set of configuration options (like a hashmap),
+ * along with a number of supporting classes.
+ *
+ * <p>
+ * Chief among these supporting classes is {@link org.apache.isis.core.commons.config.ConfigurationBuilder},
+ * which holds a (mutable) collection of properties and is used to build an
+ * {@link org.apache.isis.core.commons.config.IsisConfiguration}. The
+ * {@link org.apache.isis.core.commons.config.ConfigurationBuilder} and
+ * {@link org.apache.isis.core.commons.config.IsisConfiguration} types form
+ * an mutable/immutable pair (cf {@link java.lang.StringBuilder} / {@link java.lang.String}).
+ *
+ * <p>
+ * The {@link org.apache.isis.core.commons.config.ConfigurationBuilder} is used
+ * by {@link org.apache.isis.core.commons.config.InstallerAbstract}, an
+ * implementation of {@link org.apache.isis.core.commons.components.Installer}
+ * that allows the configuration to be added to as each component is
+ * installed.
+ */
+package org.apache.isis.core.commons.config;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugBuilder.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugBuilder.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugBuilder.java
new file mode 100644
index 0000000..6964483
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugBuilder.java
@@ -0,0 +1,139 @@
+/*
+ * 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.core.commons.debug;
+
+public interface DebugBuilder {
+
+ /**
+ * Concatenate the contents of the specified debug builder to the current
+ * builder.
+ */
+ void concat(DebugBuilder debug);
+
+ /**
+ * Append the specified number within a space (number of spaces) specified
+ * by the width. E.g. "15 " where number is 15 and width is 4.
+ */
+ void append(final int number, final int width);
+
+ /**
+ * Append the specified object by calling it <code>toString()</code> method.
+ */
+ void append(final Object object);
+
+ /**
+ * Append the specified object by calling its <code>toString()</code>
+ * method, placing it within specified space.
+ */
+ void append(final Object object, final int width);
+
+ /**
+ * Append the specified number, displayed in hexadecimal notation, with the
+ * specified label, then start a new line.
+ */
+ void appendAsHexln(final String label, final long value);
+
+ /**
+ * Append the message and trace of the specified exception.
+ */
+ void appendException(final Throwable e);
+
+ /**
+ * Start a new line.
+ *
+ * @see #blankLine()
+ */
+ void appendln();
+
+ /**
+ * Append the specified text, then start a new line.
+ */
+ void appendln(final String text);
+
+ /**
+ * Append the specified text without any formatting.
+ */
+ void appendPreformatted(final String text);
+
+ /**
+ * Append the specified value, displayed as true or false, with the
+ * specified label, then start a new line.
+ */
+ void appendln(final String label, final boolean value);
+
+ /**
+ * Append the specified number with the specified label, then start a new
+ * line.
+ */
+ void appendln(final String label, final double value);
+
+ /**
+ * Append the specified number, displayed in hexadecimal notation, with the
+ * specified label, then start a new line.
+ */
+ void appendln(final String label, final long value);
+
+ /**
+ * Append the specified preformatted text with the specified label, then
+ * start a new line.
+ */
+ void appendPreformatted(final String label, final String text);
+
+ /**
+ * Append the specified object with the specified label, then start a new
+ * line.
+ */
+ void appendln(final String label, final Object object);
+
+ /**
+ * Append the elements of the specified array with the specified label. Each
+ * element is appended on its own line, and a new line is added after the
+ * last element.
+ */
+ void appendln(final String label, final Object[] objects);
+
+ /**
+ * Append the specified title, then start a new line. A title is shown on
+ * two lines with the text on the first line and dashes on the second.
+ */
+ void appendTitle(final String title);
+
+ void startSection(final String title);
+
+ void endSection();
+
+ /**
+ * Append a blank line only if there are existing lines and the previous
+ * line is not blank.
+ */
+ void blankLine();
+
+ /**
+ * Increase indent used when appending.
+ */
+ void indent();
+
+ /**
+ * Decrease indent used when appending.
+ */
+ void unindent();
+
+ void close();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlString.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlString.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlString.java
new file mode 100644
index 0000000..54c10f5
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlString.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.core.commons.debug;
+
+public class DebugHtmlString extends DebugHtmlStringAbstract {
+
+ StringBuffer debug = new StringBuffer();
+
+ public DebugHtmlString() {
+ super(false);
+ }
+
+ public DebugHtmlString(final boolean createPage) {
+ super(createPage);
+ header();
+ }
+
+ @Override
+ public void doClose() {
+ footer();
+ }
+
+ @Override
+ protected void appendHtml(final String html) {
+ debug.append(html);
+ debug.append("\n");
+ }
+
+ @Override
+ public String toString() {
+ return debug.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlStringAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlStringAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlStringAbstract.java
new file mode 100644
index 0000000..8b1b4cc
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugHtmlStringAbstract.java
@@ -0,0 +1,262 @@
+/*
+ * 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.core.commons.debug;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public abstract class DebugHtmlStringAbstract implements DebugBuilder {
+
+ private final boolean createPage;
+ private int tableLevel;
+ private boolean isOdd;
+ private boolean titleShown;
+ private boolean endLine;
+
+ public DebugHtmlStringAbstract(final boolean createPage) {
+ this.createPage = createPage;
+ }
+
+ @Override
+ public void concat(final DebugBuilder debug) {
+ appendHtml(debug.toString());
+ }
+
+ @Override
+ public void append(final int number, final int width) {
+ appendHtml(number + "");
+ }
+
+ @Override
+ public void append(final Object object) {
+ if (object instanceof DebuggableWithTitle) {
+ DebuggableWithTitle d = (DebuggableWithTitle) object;
+ appendTitle(d.debugTitle());
+ d.debugData(this);
+ } else {
+ appendHtml(object.toString());
+ }
+ }
+
+ @Override
+ public void append(final Object object, final int width) {
+ appendHtml(object.toString());
+ }
+
+ @Override
+ public void appendln() {
+ if (tableLevel > 0) {
+ endLine = true;
+ } else {
+ appendHtml("<p></p>");
+ }
+ }
+
+ @Override
+ public void blankLine() {
+ if (tableLevel > 0) {
+ appendHtml(row() + "<td class=\"error\" colspan=\"2\" >blank line</td></tr>");
+ } else {
+ appendHtml("<p>blank line</p>");
+ }
+ }
+
+ @Override
+ public void appendln(final String label, final boolean value) {
+ appendln(label, String.valueOf(value));
+ }
+
+ @Override
+ public void appendln(final String label, final double value) {
+ appendln(label, String.valueOf(value));
+ }
+
+ @Override
+ public void appendln(final String label, final long value) {
+ appendln(label, String.valueOf(value));
+ }
+
+ @Override
+ public void appendAsHexln(final String label, final long value) {
+ appendln(label, Long.toHexString(value));
+ }
+
+ @Override
+ public void appendPreformatted(final String label, final String object) {
+ final String value = object == null ? "null" : object.toString();
+ appendln(label, "<pre>" + value + "</pre>");
+ };
+
+ @Override
+ public void appendln(final String label, final Object object) {
+ final String value = object == null ? "null" : object.toString();
+ appendln(label, value);
+ }
+
+ @Override
+ public void appendln(final String label, final Object[] object) {
+ if (object.length == 0) {
+ appendln(label, "empty array");
+ } else {
+ appendln(label, object[0]);
+ for (int i = 1; i < object.length; i++) {
+ appendHtml(row() + "<td></td><td>" + object[i] + "</td></tr>");
+ }
+ }
+ }
+
+ @Override
+ public void startSection(final String title) {
+ startTableIfNeeded(true);
+ appendTitle(title);
+ }
+
+ @Override
+ public void endSection() {
+ endTableIfStarted();
+ }
+
+ @Override
+ public void indent() {
+ if (tableLevel > 0) {
+ appendHtml(row() + "<td>indented</td><td>");
+ startTableIfNeeded(true);
+ }
+ }
+
+ @Override
+ public void unindent() {
+ if (tableLevel > 0) {
+ endTableIfStarted();
+ appendHtml("</td>");
+ }
+ }
+
+ protected void header() {
+ if (createPage) {
+ appendHtml("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
+ appendHtml("<html>");
+ appendHtml("<head>");
+ appendHtml("<title>Debug Details</title>");
+ appendHtml("<style type=\"text/css\">");
+ appendHtml("body { margin: 15px; }\n" + ".links { background: #ddd; font-size: 80%; padding-bottom:5px; }\n" + ".links > p { display: inline-block; }\n" + "td {vertical-align: top; margin-left: 15px;}\n" + "td.error {color: red; font-style: italic; }\n" + "td.code {white-space: pre; font-family: monospace;}\n"
+ + "th.title {text-align: left; padding: 0.3em 1em; font-style: italic; background: #AED1FF; }\n" + "td.label {width: 16em; text-align: right; padding-right: 1.5em; padding-top: 0.2em; font-size: 80%; font-weight: bold; }\n"
+ + "span.facet-type { font-weight: bold; padding-right: 10px; }\n");
+ appendHtml("</style>");
+ appendHtml("</head>");
+ appendHtml("<body>");
+ }
+ }
+
+ protected abstract void appendHtml(String html);
+
+ protected void footer() {
+ endTableIfStarted();
+ if (createPage) {
+ appendHtml("</body>");
+ appendHtml("</html>");
+ }
+ }
+
+ @Override
+ public void appendException(final Throwable e) {
+ appendTitle("Exception");
+ final String message = e.getMessage();
+ if (message != null) {
+ appendHtml(row() + "<td class=\"error\" colspan=\"2\" >" + message + "</td></tr>");
+ }
+ causingException(e);
+ appendHtml(row() + "<td class=\"code\" colspan=\"2\" ><pre>");
+ final StringWriter stringWriter = new StringWriter();
+ final PrintWriter printWriter = new PrintWriter(stringWriter);
+ e.printStackTrace(printWriter);
+ appendHtml(stringWriter.toString());
+ appendHtml("</pre></td></tr>");
+
+ }
+
+ private void causingException(final Throwable throwable) {
+ final Throwable cause = throwable.getCause();
+ if (cause != null && cause != throwable) {
+ appendHtml(row() + "<td colspan=\"2\" >" + cause.getMessage() + "</td></tr>");
+ causingException(cause);
+ }
+ }
+
+ @Override
+ public void appendTitle(final String title) {
+ if (tableLevel > 0) {
+ String className = titleShown ? "subtitle" : "title";
+ appendHtml(row() + "<th class=\""+ className + "\" colspan=\"2\" >" + title + "</th></tr>");
+ titleShown = true;
+ } else {
+ appendHtml("<h2>" + title + "</h2>");
+ }
+ }
+
+ private void appendln(final String name, final String value) {
+ startTableIfNeeded(false);
+ appendHtml(row() + "<td class=\"label\">" + name + "</td><td>" + value + "</td></tr>");
+ }
+
+ private String row() {
+ final String line = (isOdd ? "odd" : "even") + (endLine ? " end-line" : "");
+ isOdd = !isOdd;
+ endLine = false;
+ return "<tr class=\"" + line + "\">";
+ }
+
+ private void startTableIfNeeded(final boolean b) {
+ if (tableLevel == 0 || b) {
+ appendHtml("<table class=\"debug\" summary=\"Debug details\" >");
+ tableLevel++;
+ titleShown = false;
+ }
+ }
+
+ private void endTableIfStarted() {
+ if (tableLevel > 0) {
+ appendHtml("</table>");
+ tableLevel--;
+ }
+ }
+
+ @Override
+ public void appendPreformatted(final String text) {
+ appendln("<pre>" + text + "</pre>");
+ }
+
+ @Override
+ public void appendln(final String text) {
+ if (tableLevel > 0) {
+ appendHtml(row() + "<td colspan=\"2\">" + text + "</td></tr>");
+ } else {
+ appendHtml("<p>" + text + "</p>");
+ }
+ }
+
+ @Override
+ public void close() {
+ endTableIfStarted();
+ doClose();
+ }
+
+ protected abstract void doClose();
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugList.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugList.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugList.java
new file mode 100644
index 0000000..36e9b53
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/commons/debug/DebugList.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.core.commons.debug;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+public class DebugList {
+ private final List<String[]> names = Lists.newArrayList();
+ private final List<DebuggableWithTitle> debuggableList = Lists.newArrayList();
+
+ public DebugList(final String name) {
+ debuggableList.add(new DebuggableWithTitle() {
+ @Override
+ public void debugData(final DebugBuilder debug) {
+ for (String[] name : names) {
+ debug.appendln(name[0], name[1]);
+ }
+ }
+
+ @Override
+ public String debugTitle() {
+ return name;
+ }
+ });
+ }
+
+ public void add(final String name, final Object object) {
+ final boolean b = object instanceof DebuggableWithTitle;
+ if (b) {
+ debuggableList.add((DebuggableWithTitle) object);
+ }
+ if (object != null) {
+ String[] n = new String[2];
+ n[0] = name + (b ? "*" : "");
+ n[1] = object.toString();
+ names.add(n);
+ }
+ }
+
+ public DebuggableWithTitle[] debug() {
+ return debuggableList.toArray(new DebuggableWithTitle[debuggableList.size()]);
+ }
+}