You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/08/30 12:38:56 UTC

[isis] branch master updated (a117c92 -> 9e1eeca)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from a117c92  ISIS-1895: refactoring into a new module package, also adding comments
     new ae14bae  ISIS-1895: improves java-doc
     new ba97ffd  ISIS-1841: Internal API: new debug utility
     new c45b457  ISIS-1895: aligning log output
     new 9e1eeca  ISIS-1895: splitting web-module initialization into 2 phases

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../commons/internal/exceptions/_Exceptions.java   |  22 +++-
 .../isis/commons/internal/resources/_Resource.java |  16 +++
 .../services/swagger/SwaggerServiceDefault.java    |  19 +---
 .../core/webapp/IsisWebAppContextListener.java     |  35 ++++--
 .../apache/isis/core/webapp/modules/WebModule.java | 125 ++++++++++++++++++++-
 ...et.java => WebModule_FallbackBootstrapper.java} |  13 ++-
 .../modules/WebModule_LogOnExceptionLogger.java    |  35 ++----
 .../core/webapp/modules/WebModule_RestEasy.java    |  39 ++++++-
 .../isis/core/webapp/modules/WebModule_Shiro.java  |   8 +-
 .../isis/core/webapp/modules/WebModule_Wicket.java |  41 +++++--
 .../wicket/viewer/IsisWicketApplication.java       |  95 ++++++++--------
 11 files changed, 313 insertions(+), 135 deletions(-)
 rename core/runtime/src/main/java/org/apache/isis/core/webapp/modules/{WebModule_NoWicket.java => WebModule_FallbackBootstrapper.java} (81%)


[isis] 04/04: ISIS-1895: splitting web-module initialization into 2 phases

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 9e1eecadcb83e5a28b18b0db95584e1ebf5505af
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 30 14:37:38 2018 +0200

    ISIS-1895: splitting web-module initialization into 2 phases
    
    to allow modules to share information on the ServletContext
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1895
---
 .../isis/commons/internal/resources/_Resource.java |  16 +++
 .../services/swagger/SwaggerServiceDefault.java    |  19 +---
 .../core/webapp/IsisWebAppContextListener.java     |  29 +++--
 .../apache/isis/core/webapp/modules/WebModule.java | 117 ++++++++++++++++++++-
 ...et.java => WebModule_FallbackBootstrapper.java} |  13 +--
 .../modules/WebModule_LogOnExceptionLogger.java    |  33 ++----
 .../core/webapp/modules/WebModule_RestEasy.java    |  37 ++++++-
 .../isis/core/webapp/modules/WebModule_Shiro.java  |   6 +-
 .../isis/core/webapp/modules/WebModule_Wicket.java |  39 +++++--
 .../wicket/viewer/IsisWicketApplication.java       |  95 ++++++++---------
 10 files changed, 283 insertions(+), 121 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/resources/_Resource.java b/core/commons/src/main/java/org/apache/isis/commons/internal/resources/_Resource.java
index 32be534..c36b667 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/resources/_Resource.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/resources/_Resource.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.commons.internal.resources;
 
+import static org.apache.isis.commons.internal.base._With.ifPresentElseThrow;
 import static org.apache.isis.commons.internal.base._With.requires;
 
 import java.io.IOException;
@@ -128,6 +129,19 @@ public final class _Resource {
     }
 
     /**
+     * 
+     * @return restful-path resource as stored previously by {@link #putRestfulPath(String)}
+     *  or throws if resource not found
+     * @throws NullPointerException if resource not found
+     */
+    public final static String getRestfulPathOrThrow() {
+        return ifPresentElseThrow(getRestfulPathIfAny(), 
+                ()->new NullPointerException(
+                        "Could not find BasePath for the REST Service "
+                        + "config value on the context."));
+    }
+    
+    /**
      * Stores the {@code restfulPath} as an application scoped resource-object.
      * @param restfulPath
      * @throws IllegalArgumentException if the restfulPath is empty or is the root-path.
@@ -163,5 +177,7 @@ public final class _Resource {
         return name;
     }
 
+    
+
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
index f4b0ec1..4462911 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/swagger/SwaggerServiceDefault.java
@@ -22,16 +22,16 @@ import java.util.Map;
 
 import javax.annotation.PostConstruct;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.swagger.SwaggerService;
-import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.resources._Resource;
 import org.apache.isis.core.metamodel.services.swagger.internal.SwaggerSpecGenerator;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 @DomainService(
         nature = NatureOfService.DOMAIN,
@@ -42,22 +42,13 @@ public class SwaggerServiceDefault implements SwaggerService {
     @SuppressWarnings("unused")
     private final static Logger LOG = LoggerFactory.getLogger(SwaggerServiceDefault.class);
 
-    public static final String KEY_RESTFUL_BASE_PATH = "isis.services.swagger.restfulBasePath";
-    public static final String KEY_RESTFUL_BASE_PATH_DEFAULT = "/restful";
-
     private String basePath;
 
     @PostConstruct
     public void init(final Map<String,String> properties) {
 
-        // ----------------------------------------------------------------------------------------------------------
-        // TODO [ahuber] this initialization must be done once before accessing _Resource.prependContextPathIfPresent
-        // could be done anywhere during bootstrapping
-        final String restfulPath =
-                _NullSafe.getOrDefault(properties, KEY_RESTFUL_BASE_PATH, KEY_RESTFUL_BASE_PATH_DEFAULT);
-        _Resource.putRestfulPath(restfulPath);
-        // ----------------------------------------------------------------------------------------------------------
-
+        final String restfulPath = _Resource.getRestfulPathOrThrow(); 
+        
         this.basePath = _Resource.prependContextPathIfPresent(restfulPath);
     }
 
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
index 8991c64..54808ae 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
@@ -19,9 +19,12 @@
 package org.apache.isis.core.webapp;
 
 import static org.apache.isis.commons.internal.base._With.acceptIfPresent;
+import static org.apache.isis.commons.internal.context._Context.setDefaultClassLoader;
+import static org.apache.isis.commons.internal.resources._Resource.putContextPathIfPresent;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
@@ -54,16 +57,31 @@ public class IsisWebAppContextListener implements ServletContextListener {
     
     private final List<ServletContextListener> activeListeners = new ArrayList<>();
 
-    // -- IMPLEMENTATION
+    // -- INTERFACE IMPLEMENTATION
     
     @Override
     public void contextInitialized(ServletContextEvent event) {
         
-        final ServletContext context = event.getServletContext();
+        final ServletContext servletContext = event.getServletContext();
         
-        WebModule.discoverWebModules()
-        .filter(module->module.isAvailable(context)) // filter those WebModules that are applicable
-        .forEach(module->addListener(context, module));
+        setDefaultClassLoader(this.getClass().getClassLoader(), true);
+        
+        // setting up context specific properties before bootstrapping
+        putContextPathIfPresent(servletContext.getContextPath());
+
+        // phase 1
+        final List<WebModule> webModules =
+                 WebModule.discoverWebModules()
+                 .peek(module->module.prepare(servletContext)) // prepare context
+                 .collect(Collectors.toList());
+
+        // put the list of viewer names "isis.viewers" into a context parameter
+        WebModule.ContextUtil.commitViewers(servletContext); 
+        
+        // phase 2
+        webModules.stream()
+        .filter(module->module.isApplicable(servletContext)) // filter those WebModules that are applicable
+        .forEach(module->addListener(servletContext, module));
         
         activeListeners.forEach(listener->listener.contextInitialized(event));
     }
@@ -92,6 +110,5 @@ public class IsisWebAppContextListener implements ServletContextListener {
             LOG.error(String.format("Failed to shutdown WebListener '%s'.", listener.getClass().getName()), e);
         }
     }
-    
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
index d24d0f4..3f4178e 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
@@ -18,6 +18,10 @@
  */
 package org.apache.isis.core.webapp.modules;
 
+import static org.apache.isis.commons.internal.base._Strings.isEmpty;
+import static org.apache.isis.commons.internal.base._With.ifPresentElse;
+import static org.apache.isis.commons.internal.base._With.requires;
+
 import java.util.stream.Stream;
 
 import javax.servlet.Filter;
@@ -27,6 +31,9 @@ import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebListener;
 
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.core.commons.config.IsisConfigurationDefault;
+import org.apache.isis.core.webapp.IsisWebAppBootstrapper;
 import org.apache.isis.core.webapp.IsisWebAppContextListener;
 
 /**
@@ -48,6 +55,16 @@ public interface WebModule {
     public String getName();
     
     /**
+     * Before initializing any WebModule we call each WebModule's prepare method 
+     * to allow for a WebModule to leave information useful for other modules on 
+     * the shared ServletContext.
+     * 
+     * @param ctx ServletContext
+     */
+    default public void prepare(ServletContext ctx) {}
+    
+    /**
+     * Expected to be called after all WebModules had a chance to prepare the ServletContext.
      * Sets this WebModule's {@link Filter}s, {@link Servlet}s or {@link WebListener}s 
      * up and registers them with the given {@link ServletContext} {@code ctx}.
      * @param ctx ServletContext
@@ -55,10 +72,11 @@ public interface WebModule {
     public ServletContextListener init(ServletContext ctx) throws ServletException;
     
     /**
+     * Expected to be called after all WebModules had a chance to prepare the ServletContext.
      * @param ctx ServletContext
-     * @return whether this module is available (on the class-path) and also applicable 
+     * @return whether this module is applicable/usable
      */
-    public boolean isAvailable(ServletContext ctx);
+    public boolean isApplicable(ServletContext ctx);
     
     // -- DISCOVERY 
     
@@ -75,10 +93,103 @@ public interface WebModule {
         return Stream.of(
                 new WebModule_Shiro(), // filters before all others
                 new WebModule_Wicket(),
-                new WebModule_NoWicket(), // not required if the Wicket viewer is in use
+                new WebModule_FallbackBootstrapper(), // not required if the Wicket module is in use
                 new WebModule_RestEasy(), // default REST provider
                 new WebModule_LogOnExceptionLogger() // log any logon exceptions, filters after all others
                 );
     }
     
+    // -- UTILITY
+    
+    static final class ContextUtil {
+        
+        /**
+         * Tell other modules that a bootstrapper is present.
+         * @param ctx
+         * @param bootstrapper
+         */
+        public static void registerBootstrapper(ServletContext ctx, WebModule bootstrapper) {
+            ctx.setAttribute("isis.bootstrapper", bootstrapper);    
+        }
+        
+        /**
+         * @param ctx
+         * @return whether this context has a bootstrapper registered
+         */
+        public static boolean hasBootstrapper(ServletContext ctx) {
+            return ctx.getAttribute("isis.bootstrapper")!=null;    
+        }
+        
+        /**
+         *  Adds to the list of viewer names "isis.viewers"
+         * @param ctx
+         * @param viewerName
+         */
+        public static void registerViewer(ServletContext ctx, String viewerName) {
+            String viewers = (String) ctx.getAttribute("isis.viewers");
+            if(isEmpty(viewers)) {
+                viewers = viewerName;
+            } else {
+                viewers = viewers + "," + viewerName;
+            }
+            ctx.setAttribute("isis.viewers", viewers);
+        }
+        
+        /**
+         * Puts the list of viewer names "isis.viewers" into a context parameter.
+         * @param ctx
+         */
+        public static void commitViewers(ServletContext ctx) {
+            String viewers = (String) ctx.getAttribute("isis.viewers");
+            if(!isEmpty(viewers)) {
+                ctx.setInitParameter("isis.viewers", viewers);    
+            }
+        }
+        
+        /**
+         *  Adds to the list of protected path names "isis.protected"
+         * @param ctx
+         * @param path
+         */
+        public static void registerProtectedPath(ServletContext ctx, String path) {
+            String list = (String) ctx.getAttribute("isis.protected");
+            if(isEmpty(list)) {
+                list = path;
+            } else {
+                list = list + "," + path;
+            }
+            ctx.setAttribute("isis.protected", list);
+        }
+        
+        /**
+         * Streams the protected path names "isis.protected".
+         * @param ctx
+         */
+        public static Stream<String> streamProtectedPaths(ServletContext ctx) {
+            final String list = (String) ctx.getAttribute("isis.protected");
+            return _Strings.splitThenStream(list, ",");
+        }
+
+        /**
+         * Try to fetch the value from config stored under {@code key} else fallback to {@code defaultValue}
+         * @param ctx
+         * @param key
+         * @param defaultValue
+         * @return non-null
+         */
+        public static String getConfigOrDefault(ServletContext ctx, String key, String defaultValue) {
+            requires(key, "key");
+            requires(defaultValue, "defaultValue");
+            
+            final IsisConfigurationDefault webXmlConfig = 
+                    IsisWebAppBootstrapper.lookupIsisConfigurationBuilder(ctx)
+                    .getConfiguration();
+            
+            return ifPresentElse(webXmlConfig.getProperty(key), defaultValue);
+        }
+        
+        
+    }
+    
+    
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_FallbackBootstrapper.java
similarity index 81%
rename from core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java
rename to core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_FallbackBootstrapper.java
index aea5509..e686b16 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_FallbackBootstrapper.java
@@ -28,23 +28,24 @@ import org.apache.isis.core.webapp.IsisWebAppBootstrapper;
  * Package private mixin for WebModule implementing WebModule.
  * @since 2.0.0
  */
-final class WebModule_NoWicket implements WebModule  {
+final class WebModule_FallbackBootstrapper implements WebModule  {
     
     @Override
     public String getName() {
-        return "No-Wicket";
+        return "Fallback Bootstrapper";
     }
 
     @Override
     public ServletContextListener init(ServletContext ctx) throws ServletException {
         ctx.setInitParameter("deploymentType", "SERVER_PROTOTYPE");
-        ctx.setInitParameter("isis.viewers", "restfulobjects");
         return ctx.createListener(IsisWebAppBootstrapper.class);
     }
 
     @Override
-    public boolean isAvailable(ServletContext ctx) {
-        // not required if the Wicket viewer is in use.
-        return !new WebModule_Wicket().isAvailable(ctx);
+    public boolean isApplicable(ServletContext ctx) {
+        // not required if another bootstrapper module is on the context 
+        // e.g. the Wicket module
+        return ctx.getAttribute("bootstrapper")!=null;
     }
+    
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
index 3f18e7e..e92cc70 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
@@ -19,12 +19,8 @@
 package org.apache.isis.core.webapp.modules;
 
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
-import static org.apache.isis.commons.internal.base._Strings.prefix;
-import static org.apache.isis.commons.internal.base._Strings.suffix;
-import static org.apache.isis.commons.internal.base._With.ifPresentElse;
 import static org.apache.isis.commons.internal.context._Context.getDefaultClassLoader;
 import static org.apache.isis.commons.internal.exceptions._Exceptions.unexpectedCodeReach;
-import static org.apache.isis.commons.internal.resources._Resource.getRestfulPathIfAny;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterRegistration.Dynamic;
@@ -32,6 +28,8 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
 
+import org.apache.isis.commons.internal.collections._Arrays;
+
 /**
  * Package private mixin for WebModule implementing WebModule.
  * @since 2.0.0
@@ -66,13 +64,13 @@ final class WebModule_LogOnExceptionLogger implements WebModule  {
             return null; // filter was already registered somewhere else (eg web.xml)
         }
 
-        reg.addMappingForUrlPatterns(null, true, getUrlPatterns() ); // filter is forced last
+        reg.addMappingForUrlPatterns(null, true, getProtectedUrlPatterns(ctx) ); // filter is forced last
 
         return null; // does not provide a listener
     }
 
     @Override
-    public boolean isAvailable(ServletContext ctx) {
+    public boolean isApplicable(ServletContext ctx) {
         try {
             getDefaultClassLoader().loadClass(LOGONLOGGER_FILTER_CLASS_NAME);
             return true;
@@ -83,29 +81,12 @@ final class WebModule_LogOnExceptionLogger implements WebModule  {
 
     // -- HELPER
     
-    private String[] getUrlPatterns() {
-        return new String[] {
-                getRestfulUrlPattern(),
-                getWicketUrlPattern()
-            };
+    private String[] getProtectedUrlPatterns(ServletContext ctx) {
+        return ContextUtil.streamProtectedPaths(ctx)
+        .collect(_Arrays.toArray(String.class));
     }
 
-    private String getWicketUrlPattern() {
-        final String wicketPath = getWicketPath();
-        final String wicketPathEnclosedWithSlashes = suffix(prefix(wicketPath, "/"), "/");
-        return wicketPathEnclosedWithSlashes + "*";
-    }
 
-    private String getWicketPath() {
-        // TODO[ISIS-1895] should be provided by a config value
-        return "wicket";
-    }
-
-    private String getRestfulUrlPattern() {
-        final String restfulPath = ifPresentElse(getRestfulPathIfAny(), "restful");
-        final String restfulPathEnclosedWithSlashes = suffix(prefix(restfulPath, "/"), "/");
-        return restfulPathEnclosedWithSlashes + "*";
-    }
     
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
index 3ad268c..7069461 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
@@ -18,13 +18,13 @@
  */
 package org.apache.isis.core.webapp.modules;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
 import static org.apache.isis.commons.internal.base._Strings.prefix;
 import static org.apache.isis.commons.internal.base._Strings.suffix;
-import static org.apache.isis.commons.internal.base._With.ifPresentElse;
 import static org.apache.isis.commons.internal.context._Context.getDefaultClassLoader;
 import static org.apache.isis.commons.internal.exceptions._Exceptions.unexpectedCodeReach;
-import static org.apache.isis.commons.internal.resources._Resource.getRestfulPathIfAny;
+import static org.apache.isis.commons.internal.resources._Resource.putRestfulPath;
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextListener;
@@ -37,15 +37,40 @@ import javax.servlet.ServletException;
  */
 final class WebModule_RestEasy implements WebModule  {
     
+    public static final String KEY_RESTFUL_BASE_PATH = "isis.viewer.restfulobjects.basePath";
+    public static final String KEY_RESTFUL_BASE_PATH_DEFAULT = "/restful";
+    
     private final static String RESTEASY_BOOTSTRAPPER = 
             "org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap";
     
     private final static String RESTEASY_DISPATCHER = "RestfulObjectsRestEasyDispatcher";
     
+    String restfulPathConfigValue;
+    
     @Override
     public String getName() {
         return "RestEasy";
     }
+    
+    @Override
+    public void prepare(ServletContext ctx) {
+        
+        if(!isApplicable(ctx)) {
+            return;
+        }
+        
+        // try to fetch restfulPath from config else fallback to default
+        final String restfulPath = 
+                ContextUtil.getConfigOrDefault(ctx, KEY_RESTFUL_BASE_PATH, KEY_RESTFUL_BASE_PATH_DEFAULT); 
+                
+        putRestfulPath(restfulPath);
+        
+        this.restfulPathConfigValue = restfulPath; // store locally for reuse
+        
+        // register this module as a viewer
+        ContextUtil.registerViewer(ctx, "restfulobjects");
+        ContextUtil.registerProtectedPath(ctx, suffix(prefix(restfulPath, "/"), "/") + "*" );
+    }
 
     @Override
     public ServletContextListener init(ServletContext ctx) throws ServletException {
@@ -72,7 +97,7 @@ final class WebModule_RestEasy implements WebModule  {
     }
 
     @Override
-    public boolean isAvailable(ServletContext ctx) {
+    public boolean isApplicable(ServletContext ctx) {
         try {
             getDefaultClassLoader().loadClass(RESTEASY_BOOTSTRAPPER);
             return true;
@@ -88,10 +113,12 @@ final class WebModule_RestEasy implements WebModule  {
     }
 
     private String getRestfulPath() {
-        final String restfulPath = ifPresentElse(getRestfulPathIfAny(), "restful");
-        final String restfulPathEnclosedWithSlashes = suffix(prefix(restfulPath, "/"), "/");
+        requireNonNull(restfulPathConfigValue, "This web-module needs to be prepared first.");
+        final String restfulPathEnclosedWithSlashes = suffix(prefix(restfulPathConfigValue, "/"), "/");
         return restfulPathEnclosedWithSlashes;
     }
     
     
+
+    
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
index 48cdadd..87aa79a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
@@ -46,12 +46,10 @@ final class WebModule_Shiro implements WebModule  {
     public String getName() {
         return "Shiro";
     }
-
+    
     @Override
     public ServletContextListener init(ServletContext ctx) throws ServletException {
         
-        ctx.setInitParameter("isis.viewers", "wicket,restfulobjects");
-
         final Filter filter;
         try {
             final Class<?> filterClass = getDefaultClassLoader().loadClass(SHIRO_FILTER_CLASS_NAME);
@@ -81,7 +79,7 @@ final class WebModule_Shiro implements WebModule  {
     }
 
     @Override
-    public boolean isAvailable(ServletContext ctx) {
+    public boolean isApplicable(ServletContext ctx) {
         try {
             getDefaultClassLoader().loadClass(SHIRO_LISTENER_CLASS_NAME);
             return true;
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
index b406a97..8241dca 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.core.webapp.modules;
 
+import static java.util.Objects.requireNonNull;
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
 import static org.apache.isis.commons.internal.base._Strings.prefix;
 import static org.apache.isis.commons.internal.base._Strings.suffix;
@@ -40,11 +41,37 @@ final class WebModule_Wicket implements WebModule  {
             "org.apache.wicket.protocol.http.WicketFilter";
 
     private final static String WICKET_FILTER_NAME = "WicketFilter";
+    
+    private String pathConfigValue;
+    private String modeConfigValue;
+    private String appConfigValue;
 
     @Override
     public String getName() {
         return "Wicket";
     }
+    
+    @Override
+    public void prepare(ServletContext ctx) {
+        
+        if(!isApplicable(ctx)) {
+            return;
+        }
+        
+        pathConfigValue = 
+                ContextUtil.getConfigOrDefault(ctx, "isis.viewer.wicket.basePath", "/wicket");
+        
+        modeConfigValue = 
+                ContextUtil.getConfigOrDefault(ctx, "isis.viewer.wicket.mode", "deployment");
+        
+        appConfigValue = 
+                ContextUtil.getConfigOrDefault(ctx, "isis.viewer.wicket.app", 
+                        "org.apache.isis.viewer.wicket.viewer.IsisWicketApplication");
+        
+        ContextUtil.registerBootstrapper(ctx, this);
+        ContextUtil.registerViewer(ctx, "wicket");
+        ContextUtil.registerProtectedPath(ctx, suffix(prefix(pathConfigValue, "/"), "/") + "*" );
+    }
 
     @Override
     public ServletContextListener init(ServletContext ctx) throws ServletException {
@@ -75,7 +102,7 @@ final class WebModule_Wicket implements WebModule  {
     }
 
     @Override
-    public boolean isAvailable(ServletContext ctx) {
+    public boolean isApplicable(ServletContext ctx) {
         try {
             getDefaultClassLoader().loadClass(WICKET_FILTER_CLASS_NAME);
             return true;
@@ -94,18 +121,16 @@ final class WebModule_Wicket implements WebModule  {
     }
 
     private String getWicketPath() {
-        // TODO[ISIS-1895] should be provided by a config value
-        return "wicket";
+        return requireNonNull(pathConfigValue, "This web-module needs to be prepared first.");
     }
 
     private String getWicketMode() {
-        // TODO[ISIS-1895] should be provided by a config value
-        return "development";
+        return requireNonNull(modeConfigValue, "This web-module needs to be prepared first.");
     }
 
     private String getApplicationClassName() {
-        // TODO[ISIS-1895] should be provided by a config value
-        return "domainapp.webapp.DomainApplication";
+        return requireNonNull(appConfigValue, "This web-module needs to be prepared first.");
+
     }
 
 }
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index 115ca87..ec1d105 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -32,9 +32,51 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.function.Function;
 
+import com.google.common.base.Joiner;
+import com.google.common.collect.Sets;
+import com.google.common.io.Resources;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.ConverterLocator;
+import org.apache.wicket.IConverterLocator;
+import org.apache.wicket.Page;
+import org.apache.wicket.RuntimeConfigurationType;
+import org.apache.wicket.SharedResources;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.AjaxRequestTarget.IListener;
+import org.apache.wicket.authentication.IAuthenticationStrategy;
+import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
+import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
+import org.apache.wicket.core.request.mapper.MountedMapper;
+import org.apache.wicket.devutils.debugbar.DebugBar;
+import org.apache.wicket.devutils.debugbar.InspectorDebugPanel;
+import org.apache.wicket.devutils.debugbar.PageSizeDebugPanel;
+import org.apache.wicket.devutils.debugbar.SessionSizeDebugPanel;
+import org.apache.wicket.devutils.debugbar.VersionDebugContributor;
+import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
+import org.apache.wicket.guice.GuiceComponentInjector;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.ResourceAggregator;
+import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
+import org.apache.wicket.markup.html.IHeaderContributor;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.request.cycle.IRequestCycleListener;
+import org.apache.wicket.request.cycle.PageRequestHandlerTracker;
+import org.apache.wicket.request.cycle.RequestCycleListenerCollection;
+import org.apache.wicket.request.resource.CssResourceReference;
+import org.apache.wicket.settings.DebugSettings;
+import org.apache.wicket.settings.RequestCycleSettings;
+import org.apache.wicket.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wicketstuff.select2.ApplicationSettings;
+
 import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.context._Context;
-import org.apache.isis.commons.internal.resources._Resource;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
@@ -78,49 +120,6 @@ import org.apache.isis.viewer.wicket.viewer.integration.wicket.ConverterForObjec
 import org.apache.isis.viewer.wicket.viewer.integration.wicket.ConverterForObjectAdapterMemento;
 import org.apache.isis.viewer.wicket.viewer.integration.wicket.WebRequestCycleForIsis;
 import org.apache.isis.viewer.wicket.viewer.settings.IsisResourceSettings;
-import org.apache.wicket.Application;
-import org.apache.wicket.Component;
-import org.apache.wicket.ConverterLocator;
-import org.apache.wicket.IConverterLocator;
-import org.apache.wicket.Page;
-import org.apache.wicket.RuntimeConfigurationType;
-import org.apache.wicket.SharedResources;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.AjaxRequestTarget.IListener;
-import org.apache.wicket.authentication.IAuthenticationStrategy;
-import org.apache.wicket.authentication.strategy.DefaultAuthenticationStrategy;
-import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
-import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
-import org.apache.wicket.core.request.mapper.MountedMapper;
-import org.apache.wicket.devutils.debugbar.DebugBar;
-import org.apache.wicket.devutils.debugbar.InspectorDebugPanel;
-import org.apache.wicket.devutils.debugbar.PageSizeDebugPanel;
-import org.apache.wicket.devutils.debugbar.SessionSizeDebugPanel;
-import org.apache.wicket.devutils.debugbar.VersionDebugContributor;
-import org.apache.wicket.devutils.diskstore.DebugDiskDataStore;
-import org.apache.wicket.guice.GuiceComponentInjector;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.ResourceAggregator;
-import org.apache.wicket.markup.head.filter.JavaScriptFilteredIntoFooterHeaderResponse;
-import org.apache.wicket.markup.html.IHeaderContributor;
-import org.apache.wicket.markup.html.WebPage;
-import org.apache.wicket.request.cycle.IRequestCycleListener;
-import org.apache.wicket.request.cycle.PageRequestHandlerTracker;
-import org.apache.wicket.request.cycle.RequestCycleListenerCollection;
-import org.apache.wicket.request.resource.CssResourceReference;
-import org.apache.wicket.settings.DebugSettings;
-import org.apache.wicket.settings.RequestCycleSettings;
-import org.apache.wicket.util.time.Duration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.wicketstuff.select2.ApplicationSettings;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.Sets;
-import com.google.common.io.Resources;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Module;
 
 import de.agilecoders.wicket.core.Bootstrap;
 import de.agilecoders.wicket.core.markup.html.bootstrap.behavior.BootstrapBaseBehavior;
@@ -335,8 +334,6 @@ implements ComponentFactoryRegistryAccessor, PageClassRegistryAccessor, WicketVi
         try {
             super.init();
 
-            _Context.setDefaultClassLoader(this.getClass().getClassLoader(), true);
-
             futures = startBackgroundInitializationThreads();
 
             String isisConfigDir = getServletContext().getInitParameter("isis.config.dir");
@@ -350,8 +347,6 @@ implements ComponentFactoryRegistryAccessor, PageClassRegistryAccessor, WicketVi
             final IsisConfigurationBuilder isisConfigurationBuilder = obtainConfigBuilder();
             isisConfigurationBuilder.addDefaultConfigurationResourcesAndPrimers();
 
-            _Resource.putContextPathIfPresent(getServletContext().getContextPath());
-
             final IsisConfigurationDefault configuration = isisConfigurationBuilder.getConfiguration();
 
             DeploymentTypeWicketAbstract deploymentType =
@@ -863,7 +858,7 @@ implements ComponentFactoryRegistryAccessor, PageClassRegistryAccessor, WicketVi
                     final IsisConfigurationDefault isisConfiguration) {
                 return new IsisInjectModule(deploymentCategory, isisConfiguration);
             }
-
+            
             // //////////////////////////////////////
 
 


[isis] 01/04: ISIS-1895: improves java-doc

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit ae14bae36c3ade7fd31e0127aaa6817d769f4bda
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 30 07:00:24 2018 +0200

    ISIS-1895: improves java-doc
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1895
---
 .../org/apache/isis/core/webapp/IsisWebAppContextListener.java    | 2 +-
 .../main/java/org/apache/isis/core/webapp/modules/WebModule.java  | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
index 6579f22..99a596a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
@@ -36,7 +36,7 @@ import org.apache.isis.core.webapp.modules.WebModule;
 
 /**
  * 
- * Introduced to render web.xml listener configurations obsolete.
+ * Introduced to render web.xml Filter/Listener/Servlet configurations obsolete.
  * <p> 
  * Acts as the single application entry-point for setting up the 
  * ServletContext programmatically.
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
index a7cf761..d24d0f4 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule.java
@@ -20,14 +20,17 @@ package org.apache.isis.core.webapp.modules;
 
 import java.util.stream.Stream;
 
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
+import javax.servlet.annotation.WebListener;
 
 import org.apache.isis.core.webapp.IsisWebAppContextListener;
 
 /**
- * Introduced to render web.xml listener configurations obsolete.
+ * Introduced to render web.xml Filter/Listener/Servlet configurations obsolete.
  * <p>
  * WebModule instances are used by the {@link IsisWebAppContextListener} to setup 
  * the ServletContext programmatically.
@@ -45,7 +48,8 @@ public interface WebModule {
     public String getName();
     
     /**
-     * Sets the WebListener up and registers it with the given ServletContext {@code ctx}.
+     * Sets this WebModule's {@link Filter}s, {@link Servlet}s or {@link WebListener}s 
+     * up and registers them with the given {@link ServletContext} {@code ctx}.
      * @param ctx ServletContext
      */
     public ServletContextListener init(ServletContext ctx) throws ServletException;


[isis] 03/04: ISIS-1895: aligning log output

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit c45b457c035ed80bf86fdc52c9c004695542c65d
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 30 07:51:26 2018 +0200

    ISIS-1895: aligning log output
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1895
---
 .../java/org/apache/isis/core/webapp/IsisWebAppContextListener.java   | 4 ++--
 .../isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java      | 2 +-
 .../java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java  | 2 +-
 .../java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java  | 2 +-
 .../java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java     | 2 +-
 .../java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java    | 2 +-
 6 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
index 99a596a..8991c64 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
@@ -77,11 +77,11 @@ public class IsisWebAppContextListener implements ServletContextListener {
     // -- HELPER
     
     private void addListener(ServletContext context, WebModule module) {
-        LOG.info(String.format("ServletContext: adding '%s'", module.getName()));
+        LOG.info(String.format("Setup ServletContext, adding WebModule '%s'", module.getName()));
         try {
             acceptIfPresent(module.init(context), activeListeners::add);
         } catch (ServletException e) {
-            LOG.error(String.format("Failed to add '%s' to the ServletContext.", module.getName()), e);
+            LOG.error(String.format("Failed to add WebModule '%s' to the ServletContext.", module.getName()), e);
         }  
     }
     
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
index 379c3e8..3f18e7e 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_LogOnExceptionLogger.java
@@ -46,7 +46,7 @@ final class WebModule_LogOnExceptionLogger implements WebModule  {
 
     @Override
     public String getName() {
-        return "Wicket WebFilter";
+        return "LogOn Exception Logger";
     }
 
     @Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java
index 463eb74..aea5509 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_NoWicket.java
@@ -32,7 +32,7 @@ final class WebModule_NoWicket implements WebModule  {
     
     @Override
     public String getName() {
-        return "No-Wicket WebListener";
+        return "No-Wicket";
     }
 
     @Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
index 0612f05..3ad268c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_RestEasy.java
@@ -44,7 +44,7 @@ final class WebModule_RestEasy implements WebModule  {
     
     @Override
     public String getName() {
-        return "RestEasy WebListener";
+        return "RestEasy";
     }
 
     @Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
index 8550f4d..48cdadd 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Shiro.java
@@ -44,7 +44,7 @@ final class WebModule_Shiro implements WebModule  {
 
     @Override
     public String getName() {
-        return "Shiro WebListener & WebFilter";
+        return "Shiro";
     }
 
     @Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
index e2bb66b..b406a97 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/modules/WebModule_Wicket.java
@@ -43,7 +43,7 @@ final class WebModule_Wicket implements WebModule  {
 
     @Override
     public String getName() {
-        return "Wicket WebFilter";
+        return "Wicket";
     }
 
     @Override


[isis] 02/04: ISIS-1841: Internal API: new debug utility

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit ba97ffdf22468cc89e007595abcb7da44076c794
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Aug 30 07:50:13 2018 +0200

    ISIS-1841: Internal API: new debug utility
    
    for printing current thread's StackTrace
---
 .../commons/internal/exceptions/_Exceptions.java   | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java b/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
index 6f7cca2..968f0f9 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/exceptions/_Exceptions.java
@@ -19,8 +19,10 @@
 
 package org.apache.isis.commons.internal.exceptions;
 
+import static org.apache.isis.commons.internal.base._NullSafe.stream;
 import static org.apache.isis.commons.internal.base._With.requires;
 
+import java.io.PrintStream;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
@@ -31,7 +33,6 @@ import java.util.stream.Stream;
 
 import javax.annotation.Nullable;
 
-import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.functions._Functions;
 
@@ -139,11 +140,25 @@ public final class _Exceptions {
         if(ex==null) {
             return Stream.empty();
         }
-        return _NullSafe.stream(ex.getStackTrace())
+        return stream(ex.getStackTrace())
                 .map(StackTraceElement::toString)
                 .limit(maxLines);
     }
 
+    /**
+     * Dumps the current thread's stack-trace onto the given {@code writer}.
+     * @param writer
+     * @param skipLines
+     * @param maxLines
+     */
+    public static void dumpStackTrace(PrintStream writer, int skipLines, int maxLines) {
+        stream(Thread.currentThread().getStackTrace())
+        .map(StackTraceElement::toString)
+        .skip(skipLines)
+        .limit(maxLines)
+        .forEach(writer::println);
+    }
+
     // -- CAUSAL CHAIN
 
     public static List<Throwable> getCausalChain(@Nullable Throwable ex) {
@@ -279,7 +294,4 @@ public final class _Exceptions {
     }
 
 
-
-
-
 }