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/29 13:22:25 UTC

[isis] branch master updated (5f0f542 -> 809e2a0)

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 5f0f542  ISIS-1841: bump swagger.io core to 1.5.21, also display version in UI
     new f00ec3b  ISIS-1841: fix bug in _Reflect.streamAllMethods
     new 7805604  ISIS-1841: Internal API: add utility for streaming of enumerations
     new 809e2a0  ISIS-1895: web.xml no longer needed for Listeners, Filters and Servlets

The 3 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:
 .../isis/commons/internal/base/_NullSafe.java      |  34 ++++++-
 .../isis/commons/internal/reflection/_Reflect.java |   2 +-
 .../core/webapp/IsisWebAppContextListener.java     |  94 +++++++++++++++++
 .../org/apache/isis/core/webapp/WebModule.java     |  68 +++++++++++++
 .../webapp/WebModule_LogOnExceptionLogger.java     | 111 +++++++++++++++++++++
 .../isis/core/webapp/WebModule_NoWicket.java}      |  40 ++++----
 .../isis/core/webapp/WebModule_RestEasy.java       |  97 ++++++++++++++++++
 .../apache/isis/core/webapp/WebModule_Shiro.java   |  93 +++++++++++++++++
 .../apache/isis/core/webapp/WebModule_Wicket.java  | 111 +++++++++++++++++++++
 9 files changed, 622 insertions(+), 28 deletions(-)
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule.java
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_LogOnExceptionLogger.java
 copy core/{metamodel/src/main/java/org/apache/isis/core/runtime/authentication/AuthenticationRequestAbstract.java => runtime/src/main/java/org/apache/isis/core/webapp/WebModule_NoWicket.java} (53%)
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_RestEasy.java
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Shiro.java
 create mode 100644 core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Wicket.java


[isis] 03/03: ISIS-1895: web.xml no longer needed for Listeners, Filters and Servlets

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 809e2a0f1e1894979d4461d02879de25d925c336
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Aug 29 15:10:05 2018 +0200

    ISIS-1895: web.xml no longer needed for Listeners, Filters and Servlets
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1895
---
 .../core/webapp/IsisWebAppContextListener.java     |  94 +++++++++++++++++
 .../org/apache/isis/core/webapp/WebModule.java     |  68 +++++++++++++
 .../webapp/WebModule_LogOnExceptionLogger.java     | 111 +++++++++++++++++++++
 .../isis/core/webapp/WebModule_NoWicket.java       |  48 +++++++++
 .../isis/core/webapp/WebModule_RestEasy.java       |  97 ++++++++++++++++++
 .../apache/isis/core/webapp/WebModule_Shiro.java   |  93 +++++++++++++++++
 .../apache/isis/core/webapp/WebModule_Wicket.java  | 111 +++++++++++++++++++++
 7 files changed, 622 insertions(+)

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
new file mode 100644
index 0000000..8568b28
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisWebAppContextListener.java
@@ -0,0 +1,94 @@
+/*
+ *  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.webapp;
+
+import static org.apache.isis.commons.internal.base._With.acceptIfPresent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebListener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * Introduced to render web.xml listener configurations obsolete.
+ * <p> 
+ * Acts as the single application entry-point when running within a Servlet context.
+ * Delegates the bootstrapping to appropriate 'bootstrappers' that are discovered 
+ * on the class-path. 
+ * </p>   
+ *  
+ * @since 2.0.0
+ *
+ */
+@WebListener
+public class IsisWebAppContextListener implements ServletContextListener {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(IsisWebAppContextListener.class);
+    
+    private final List<ServletContextListener> activeListeners = new ArrayList<>();
+
+    // -- IMPLEMENTATION
+    
+    @Override
+    public void contextInitialized(ServletContextEvent event) {
+        
+        final ServletContext context = event.getServletContext();
+        
+        WebModule.discoverWebModules()
+        .filter(module->module.isAvailable(context))
+        .forEach(module->addListener(context, module));
+        
+        activeListeners.forEach(listener->listener.contextInitialized(event));
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent event) {
+        activeListeners.forEach(listener->shutdownListener(event, listener));
+        activeListeners.clear();
+    }
+    
+    // -- HELPER
+    
+    private void addListener(ServletContext context, WebModule provider) {
+        LOG.info(String.format("ServletContext: adding '%s'", provider.getName()));
+        try {
+            acceptIfPresent(provider.init(context), activeListeners::add);
+        } catch (ServletException e) {
+            LOG.error(String.format("Failed to add '%s' to the ServletContext.", provider.getName()), e);
+        }  
+    }
+    
+    private void shutdownListener(ServletContextEvent event, ServletContextListener listener) {
+        try {
+            listener.contextDestroyed(event);
+        } catch (Exception e) {
+            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/WebModule.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule.java
new file mode 100644
index 0000000..8db2b6f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule.java
@@ -0,0 +1,68 @@
+/*
+ *  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.webapp;
+
+import java.util.stream.Stream;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * @since 2.0.0
+ */
+public interface WebModule {
+    
+    // -- INTERFACE
+
+    /**
+     * @return (display-) name of this provider
+     */
+    public String getName();
+    
+    /**
+     * Sets the WebListener up and registers it with the given ServletContext {@code ctx}.
+     * @param ctx ServletContext
+     */
+    public ServletContextListener init(ServletContext ctx) throws ServletException;
+    
+    /**
+     * @param ctx ServletContext
+     * @return whether this provider is available on the class-path and also applicable 
+     */
+    public boolean isAvailable(ServletContext ctx);
+    
+    // -- DISCOVERY 
+    
+    /**
+     * Searches the class-path for 'bootstrappers'. 
+     * @return stream of 'bootstrappers'
+     */
+    static Stream<WebModule> discoverWebModules() {
+        
+        return Stream.of(
+                new WebModule_Shiro(),
+                new WebModule_Wicket(),
+                new WebModule_NoWicket(), // not required if the Wicket viewer is in use
+                new WebModule_RestEasy(), // default REST provider
+                new WebModule_LogOnExceptionLogger() // log any logon exceptions
+                );
+    }
+    
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_LogOnExceptionLogger.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_LogOnExceptionLogger.java
new file mode 100644
index 0000000..f9c9423
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_LogOnExceptionLogger.java
@@ -0,0 +1,111 @@
+/*
+ *  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.webapp;
+
+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;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * Package private mixin for WebModule implementing WebModule.
+ * @since 2.0.0
+ */
+final class WebModule_LogOnExceptionLogger implements WebModule  {
+
+    private final static String LOGONLOGGER_FILTER_CLASS_NAME = 
+            "org.apache.isis.core.webapp.diagnostics.IsisLogOnExceptionFilter";
+
+    private final static String LOGONLOGGER_FILTER_NAME = "IsisLogOnExceptionFilter";
+
+
+    @Override
+    public String getName() {
+        return "Wicket WebFilter";
+    }
+
+    @Override
+    public ServletContextListener init(ServletContext ctx) throws ServletException {
+
+        final Filter filter;
+        try {
+            final Class<?> filterClass = getDefaultClassLoader().loadClass(LOGONLOGGER_FILTER_CLASS_NAME);
+            filter = ctx.createFilter(uncheckedCast(filterClass));
+        } catch (ClassNotFoundException e) {
+            // guarded against by isAvailable()
+            throw unexpectedCodeReach();
+        }
+
+        final Dynamic reg = ctx.addFilter(LOGONLOGGER_FILTER_NAME, filter);
+        if(reg==null) {
+            return null; // filter was already registered somewhere else (eg web.xml)
+        }
+
+        reg.addMappingForUrlPatterns(null, true, getUrlPatterns() ); // filter is forced last
+
+        return null; // does not provide a listener
+    }
+
+    @Override
+    public boolean isAvailable(ServletContext ctx) {
+        try {
+            getDefaultClassLoader().loadClass(LOGONLOGGER_FILTER_CLASS_NAME);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    // -- HELPER
+    
+    private String[] getUrlPatterns() {
+        return new String[] {
+                getRestfulUrlPattern(),
+                getWicketUrlPattern()
+            };
+    }
+
+    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/WebModule_NoWicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_NoWicket.java
new file mode 100644
index 0000000..10151ba
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_NoWicket.java
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.webapp;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * Package private mixin for WebModule implementing WebModule.
+ * @since 2.0.0
+ */
+final class WebModule_NoWicket implements WebModule  {
+    
+    @Override
+    public String getName() {
+        return "No-Wicket WebListener";
+    }
+
+    @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);
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_RestEasy.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_RestEasy.java
new file mode 100644
index 0000000..b9c04e1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_RestEasy.java
@@ -0,0 +1,97 @@
+/*
+ *  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.webapp;
+
+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.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * Package private mixin for WebModule implementing WebModule.
+ * 
+ * @since 2.0.0
+ */
+final class WebModule_RestEasy implements WebModule  {
+    
+    private final static String RESTEASY_BOOTSTRAPPER = 
+            "org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap";
+    
+    private final static String RESTEASY_DISPATCHER = "RestfulObjectsRestEasyDispatcher";
+    
+    @Override
+    public String getName() {
+        return "RestEasy WebListener";
+    }
+
+    @Override
+    public ServletContextListener init(ServletContext ctx) throws ServletException {
+        
+        //  used by RestEasy to determine the JAX-RS resources and other related configuration
+        ctx.setInitParameter(
+                "javax.ws.rs.Application", 
+                "org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplication");
+        
+        ctx.setInitParameter("resteasy.servlet.mapping.prefix", getRestfulPath());
+        
+        ctx.addServlet(RESTEASY_DISPATCHER, 
+                "org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher");
+        ctx.getServletRegistration(RESTEASY_DISPATCHER)
+        .addMapping(getUrlPattern());
+        
+        try {
+            final Class<?> listenerClass = getDefaultClassLoader().loadClass(RESTEASY_BOOTSTRAPPER);
+            return ctx.createListener(uncheckedCast(listenerClass));
+        } catch (ClassNotFoundException e) {
+            // guarded against by isAvailable()
+            throw unexpectedCodeReach();
+        }
+    }
+
+    @Override
+    public boolean isAvailable(ServletContext ctx) {
+        try {
+            getDefaultClassLoader().loadClass(RESTEASY_BOOTSTRAPPER);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+    
+    // -- HELPER
+    
+    private String getUrlPattern() {
+        return getRestfulPath() + "*";
+    }
+
+    private String getRestfulPath() {
+        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/WebModule_Shiro.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Shiro.java
new file mode 100644
index 0000000..12fdff3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Shiro.java
@@ -0,0 +1,93 @@
+/*
+ *  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.webapp;
+
+import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
+import static org.apache.isis.commons.internal.context._Context.getDefaultClassLoader;
+import static org.apache.isis.commons.internal.exceptions._Exceptions.unexpectedCodeReach;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterRegistration.Dynamic;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * Package private mixin for WebModule implementing WebModule.
+ * @since 2.0.0
+ */
+final class WebModule_Shiro implements WebModule  {
+
+    private final static String SHIRO_LISTENER_CLASS_NAME = 
+            "org.apache.shiro.web.env.EnvironmentLoaderListener";
+
+    private final static String SHIRO_FILTER_CLASS_NAME = 
+            "org.apache.shiro.web.servlet.ShiroFilter";
+    
+    private final static String SHIRO_FILTER_NAME = "ShiroFilter";
+
+    @Override
+    public String getName() {
+        return "Shiro WebListener & WebFilter";
+    }
+
+    @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);
+            filter = ctx.createFilter(uncheckedCast(filterClass));
+        } catch (ClassNotFoundException e) {
+            // guarded against by isAvailable()
+            throw unexpectedCodeReach();
+        }
+
+        final Dynamic reg = ctx.addFilter(SHIRO_FILTER_NAME, filter);
+        if(reg==null) {
+            return null; // filter was already registered somewhere else (eg web.xml)
+        }
+
+        final String urlPattern = "/*";
+
+        reg.addMappingForUrlPatterns(null, false, urlPattern); // filter is forced first
+        
+        try {
+            final Class<?> listenerClass = getDefaultClassLoader().loadClass(SHIRO_LISTENER_CLASS_NAME);
+            return ctx.createListener(uncheckedCast(listenerClass));
+        } catch (ClassNotFoundException e) {
+            // guarded against by isAvailable()
+            throw unexpectedCodeReach();
+        }
+      
+    }
+
+    @Override
+    public boolean isAvailable(ServletContext ctx) {
+        try {
+            getDefaultClassLoader().loadClass(SHIRO_LISTENER_CLASS_NAME);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Wicket.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Wicket.java
new file mode 100644
index 0000000..0f60704
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/WebModule_Wicket.java
@@ -0,0 +1,111 @@
+/*
+ *  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.webapp;
+
+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.context._Context.getDefaultClassLoader;
+import static org.apache.isis.commons.internal.exceptions._Exceptions.unexpectedCodeReach;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterRegistration.Dynamic;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletException;
+
+/**
+ * Package private mixin for WebModule implementing WebModule.
+ * @since 2.0.0
+ */
+final class WebModule_Wicket implements WebModule  {
+
+    private final static String WICKET_FILTER_CLASS_NAME = 
+            "org.apache.wicket.protocol.http.WicketFilter";
+
+    private final static String WICKET_FILTER_NAME = "WicketFilter";
+
+    @Override
+    public String getName() {
+        return "Wicket WebFilter";
+    }
+
+    @Override
+    public ServletContextListener init(ServletContext ctx) throws ServletException {
+        ctx.setInitParameter("isis.viewers", "wicket,restfulobjects");
+
+        final Filter filter;
+        try {
+            final Class<?> filterClass = getDefaultClassLoader().loadClass(WICKET_FILTER_CLASS_NAME);
+            filter = ctx.createFilter(uncheckedCast(filterClass));
+        } catch (ClassNotFoundException e) {
+            // guarded against by isAvailable()
+            throw unexpectedCodeReach();
+        }
+
+        final Dynamic reg = ctx.addFilter(WICKET_FILTER_NAME, filter);
+        if(reg==null) {
+            return null; // filter was already registered somewhere else (eg web.xml)
+        }
+
+        final String urlPattern = getUrlPattern();
+
+        reg.setInitParameter("applicationClassName", getApplicationClassName());
+        reg.setInitParameter("filterMappingUrlPattern", urlPattern);
+        reg.setInitParameter("configuration", getWicketMode()); 
+        reg.addMappingForUrlPatterns(null, true, urlPattern);
+
+        return null; // does not provide a listener
+    }
+
+    @Override
+    public boolean isAvailable(ServletContext ctx) {
+        try {
+            getDefaultClassLoader().loadClass(WICKET_FILTER_CLASS_NAME);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    // -- HELPER
+
+    private String getUrlPattern() {
+        final String wicketPath = getWicketPath();
+        final String wicketPathEnclosedWithSlashes = suffix(prefix(wicketPath, "/"), "/");
+        final String urlPattern = wicketPathEnclosedWithSlashes + "*";
+        return urlPattern;
+    }
+
+    private String getWicketPath() {
+        // TODO[ISIS-1895] should be provided by a config value
+        return "wicket";
+    }
+
+    private String getWicketMode() {
+        // TODO[ISIS-1895] should be provided by a config value
+        return "development";
+    }
+
+    private String getApplicationClassName() {
+        // TODO[ISIS-1895] should be provided by a config value
+        return "domainapp.webapp.DomainApplication";
+    }
+
+}


[isis] 02/03: ISIS-1841: Internal API: add utility for streaming of enumerations

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 78056049399b8a32332dbc15c2ca8273df919b8c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Aug 29 13:54:57 2018 +0200

    ISIS-1841: Internal API: add utility for streaming of enumerations
---
 .../isis/commons/internal/base/_NullSafe.java      | 34 ++++++++++++++++++----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
index ae39a5a..e28d83f 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
@@ -20,9 +20,12 @@ package org.apache.isis.commons.internal.base;
 
 import java.util.Collection;
 import java.util.Comparator;
+import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Spliterator;
+import java.util.Spliterators;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -99,13 +102,34 @@ public final class _NullSafe {
      */
     public static <T> Stream<T> stream(final Iterator<T> iterator){
         return iterator!=null
-                ? StreamSupport.stream(toIterable(iterator).spliterator(), false) //not parallel
+                ? StreamSupport.stream(
+                        Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED), 
+                        false) //not parallel
                         : Stream.empty();
     }
-
-    // [ahuber] not public, since one time use of iterator only!
-    private static <T> Iterable<T> toIterable(final Iterator<T> iterator){
-        return ()->iterator;
+    
+    /**
+     * If {@code enumeration} is {@code null} returns the empty stream,
+     * otherwise returns a stream of the enumeration's elements.
+     * @param enumeration
+     * @return non-null stream object
+     */
+    public static <T> Stream<T> stream(final Enumeration<T> enumeration){
+        return enumeration!=null
+                ? stream(toIterator(enumeration))
+                        : Stream.empty();
+    }
+    
+    // [ahuber] not public, since one time use of enumeration only!
+    private static <T> Iterator<T> toIterator(final Enumeration<T> e){
+        return new Iterator<T>() {
+            public T next() {
+                return e.nextElement();
+            }
+            public boolean hasNext() {
+                return e.hasMoreElements();
+            }
+        };
     }
 
 


[isis] 01/03: ISIS-1841: fix bug in _Reflect.streamAllMethods

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 f00ec3b4e4f4fc73495da76624af2264e56022fe
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Aug 29 12:48:41 2018 +0200

    ISIS-1841: fix bug in _Reflect.streamAllMethods
---
 .../main/java/org/apache/isis/commons/internal/reflection/_Reflect.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java b/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
index 3ff0b6a..cf4db82 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
@@ -132,7 +132,7 @@ public final class _Reflect {
      */
     public static Stream<Method> streamAllMethods(@Nullable Class<?> type) {
         return streamTypeHierarchy(type)
-                .filter(Object.class::equals) // do not process Object class.
+                .filter(t->!t.equals(Object.class)) // do not process Object class.
                 .flatMap(_Reflect::streamMethods);
     }