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

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit 8be5bb57231e7c36745d3ae897a7376b22949af1
Author: Robert Lazarski <[email protected]>
AuthorDate: Fri Sep 4 08:59:11 2026 -1000

    Filter the service listing in the model, not only in the view
    
    The servlet listing did exclude hiddenService services, but in 
listServices.jsp
    rather than before the model reached the request, so anything else rendering
    that model would name them. Apply both controls where the model is built, as
    HTTPTransportReceiver does for the standalone transport, and drop a null
    service instead of carrying one: isHiddenService would throw on it, and the
    previous putAll had the same hazard.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 .../apache/axis2/transport/http/ListingAgent.java  |  13 ++-
 .../transport/http/ServiceListingFilterTest.java   | 111 +++++++++++++++++++++
 2 files changed, 122 insertions(+), 2 deletions(-)

diff --git 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
index cece74534c..a81408c414 100644
--- 
a/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
+++ 
b/modules/transport/http/src/main/java/org/apache/axis2/transport/http/ListingAgent.java
@@ -358,8 +358,17 @@ public class ListingAgent extends AbstractAgent {
                 // either: the listing gives its name, EPR and every 
operation, which
                 // is what those routes were hidden to withhold.
                 for (java.util.Map.Entry<String, AxisService> entry : 
services.entrySet()) {
-                    if (entry.getValue() == null || 
entry.getValue().isMetadataExposed()) {
-                        sortedServices.put(entry.getKey(), entry.getValue());
+                    AxisService service = entry.getValue();
+                    // Filter here rather than relying on the view: a hidden 
service
+                    // that reaches the request attributes can still be 
rendered by
+                    // any other consumer of it. hiddenService and metadata 
exposure
+                    // are separate controls and both withhold the listing, 
which is
+                    // the same pair HTTPTransportReceiver applies for the 
standalone
+                    // transport. A null cannot be rendered at all -- 
isHiddenService
+                    // would throw on it -- so it is dropped rather than 
carried.
+                    if (service != null && !Utils.isHiddenService(service)
+                            && service.isMetadataExposed()) {
+                        sortedServices.put(entry.getKey(), service);
                     }
                 }
             }
diff --git 
a/modules/transport/http/src/test/java/org/apache/axis2/transport/http/ServiceListingFilterTest.java
 
b/modules/transport/http/src/test/java/org/apache/axis2/transport/http/ServiceListingFilterTest.java
new file mode 100644
index 0000000000..a302276f59
--- /dev/null
+++ 
b/modules/transport/http/src/test/java/org/apache/axis2/transport/http/ServiceListingFilterTest.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.axis2.transport.http;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+import org.apache.axis2.Constants;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.description.AxisService;
+
+/**
+ * The service listing is filtered before it reaches the request attributes 
rather
+ * than only in the view, so that a service the operator withheld cannot be 
rendered
+ * by any other consumer of the model.
+ *
+ * <p>Two separate controls withhold a service: the {@code hiddenService} 
parameter,
+ * and {@code exposeServiceMetadata}. The standalone transport's lister 
applies both,
+ * and so does this one.
+ */
+public class ServiceListingFilterTest extends TestCase {
+
+    private ConfigurationContext configContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        configContext = 
ConfigurationContextFactory.createEmptyConfigurationContext();
+
+        configContext.getAxisConfiguration().addService(new 
AxisService("Visible"));
+
+        AxisService notExposed = new AxisService("NotExposed");
+        notExposed.addParameter(AxisService.EXPOSE_SERVICE_METADATA, "false");
+        configContext.getAxisConfiguration().addService(notExposed);
+
+        AxisService hidden = new AxisService("HiddenParam");
+        hidden.addParameter(Constants.HIDDEN_SERVICE_PARAM_NAME, "true");
+        configContext.getAxisConfiguration().addService(hidden);
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, AxisService> listedServices() throws Exception {
+        HttpServletRequest req = mock(HttpServletRequest.class);
+        HttpServletResponse res = mock(HttpServletResponse.class);
+        when(req.getRequestURL())
+                .thenReturn(new 
StringBuffer("http://localhost:8080/axis2/services/";));
+        final Map<String, AxisService>[] captured = new Map[1];
+        // renderView needs a container, so capture the model the JSP would 
receive.
+        org.mockito.Mockito.doAnswer(invocation -> {
+            if ("sortedServices".equals(invocation.getArgument(0))) {
+                captured[0] = (Map<String, AxisService>) 
invocation.getArgument(1);
+            }
+            return null;
+        }).when(req).setAttribute(org.mockito.ArgumentMatchers.anyString(),
+                org.mockito.ArgumentMatchers.any());
+        try {
+            new ListingAgent(configContext).processListServices(req, res);
+        } catch (Exception rendering) {
+            // The view cannot render without a container; the model is what 
matters.
+        }
+        assertNotNull("the listing model should have been populated", 
captured[0]);
+        return captured[0];
+    }
+
+    public void testAnExposedServiceIsListed() throws Exception {
+        assertTrue(listedServices().containsKey("Visible"));
+    }
+
+    public void testAServiceWithMetadataExposureDisabledIsNotListed() throws 
Exception {
+        assertFalse("the listing names the service, its EPR and its 
operations",
+                listedServices().containsKey("NotExposed"));
+    }
+
+    /**
+     * The hiddenService parameter is a separate control, and the servlet 
listing has
+     * to apply it in the model too -- not only in listServices.jsp.
+     */
+    public void testAServiceHiddenByParameterIsNotListed() throws Exception {
+        assertFalse(listedServices().containsKey("HiddenParam"));
+    }
+
+    /** Nothing null reaches the model, since the view would throw on it. */
+    public void testNoNullServiceReachesTheModel() throws Exception {
+        for (AxisService service : listedServices().values()) {
+            assertNotNull("a null service would break rendering the page", 
service);
+        }
+    }
+}

Reply via email to