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

reiern70 pushed a commit to branch reiern70/systemmapper
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 9f8f5f099d8ad3afa36a2251547af65c375a5ea1
Author: reiern70 <[email protected]>
AuthorDate: Sat Apr 12 13:35:30 2025 -0500

    [WICKET-7153] 1) make system mapper more reusable by making 
newResourceReferenceMapper protected and 2) roll a hash code version of 
ResourceReferenceMapper that encodes class names by using their hash code.
---
 .../main/java/org/apache/wicket/SystemMapper.java  |   6 +-
 .../mapper/HashBasedResourceReferenceMapper.java   | 121 +++++++++++++++++++++
 2 files changed, 124 insertions(+), 3 deletions(-)

diff --git a/wicket-core/src/main/java/org/apache/wicket/SystemMapper.java 
b/wicket-core/src/main/java/org/apache/wicket/SystemMapper.java
index 6f0084ca93..2140372003 100644
--- a/wicket-core/src/main/java/org/apache/wicket/SystemMapper.java
+++ b/wicket-core/src/main/java/org/apache/wicket/SystemMapper.java
@@ -51,7 +51,7 @@ public class SystemMapper extends CompoundRequestMapper
                add(newBookmarkableMapper());
                add(newHomePageMapper(new HomePageProvider(application)));
                add(newResourceReferenceMapper(new PageParametersEncoder(),
-                       new ParentFolderPlaceholderProvider(application), 
getResourceCachingStrategy()));
+                       new ParentFolderPlaceholderProvider(application), 
getResourceCachingStrategy(), application));
                add(newUrlResourceReferenceMapper());
                add(RestartResponseAtInterceptPageException.MAPPER);
                add(newBufferedResponseMapper());
@@ -67,9 +67,9 @@ public class SystemMapper extends CompoundRequestMapper
                return new UrlResourceReferenceMapper();
        }
 
-       private IRequestMapper newResourceReferenceMapper(PageParametersEncoder 
pageParametersEncoder,
+       protected IRequestMapper 
newResourceReferenceMapper(PageParametersEncoder pageParametersEncoder,
                                                          
ParentFolderPlaceholderProvider parentFolderPlaceholderProvider,
-                                                         
Supplier<IResourceCachingStrategy> resourceCachingStrategy)
+                                                         
Supplier<IResourceCachingStrategy> resourceCachingStrategy, Application 
application)
        {
                return new ResourceReferenceMapper(pageParametersEncoder, 
parentFolderPlaceholderProvider,resourceCachingStrategy);
        }
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/HashBasedResourceReferenceMapper.java
 
b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/HashBasedResourceReferenceMapper.java
new file mode 100644
index 0000000000..9e2bffa455
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/HashBasedResourceReferenceMapper.java
@@ -0,0 +1,121 @@
+/*
+ * 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.wicket.core.request.mapper;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.mapper.ParentPathReferenceRewriter;
+import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder;
+import org.apache.wicket.request.resource.caching.IResourceCachingStrategy;
+
+/**
+ * <p>
+ * Resource reference {@link org.apache.wicket.request.IRequestMapper} that 
encodes class names as hash codes.
+ * This allows hiding the class name from resource references. i.e., instead 
of <em>/wicket/resource/org.xxx.yyy.ZPanel/a.js</em> the
+ * URL will display  <em>/wicket/resource/ddd/a.js</em>, where ddd = 
hash(org.xxx.yyy.ZPanel). This allows globally hiding
+ * class structure of your application (not displaying it via URLs).
+ * </p>
+ *
+ * <p>
+ *     Caveat: we don't take into account has collisions. I.e. to to different 
class names having the same hash code.
+ * </p>
+ * <p>
+ *     Note: if you want to hide the "wicket" part of URL for "xxx" you can do:
+ *        <code>
+ *    protected IMapperContext newMapperContext() {
+ *             return new DefaultMapperContext(this) {
+ *            public String getNamespace() {
+ *                             return "xxx";
+ *            }
+ *        };
+ *    }
+ *    </code>
+ *    on your Application class.
+ * </p>
+ */
+public class HashBasedResourceReferenceMapper extends 
ParentPathReferenceRewriter
+{
+
+       private static class HashBasedBasicResourceReferenceMapper extends 
BasicResourceReferenceMapper
+       {
+
+               private final Map<Long, String> hashMap = new 
ConcurrentHashMap<>();
+
+               private final boolean checkHashCollision;
+
+               /**
+                * Construct.
+                *
+                * @param pageParametersEncoder {@link IPageParametersEncoder}
+                * @param cachingStrategy {@link 
Supplier<IResourceCachingStrategy>}
+                */
+               public 
HashBasedBasicResourceReferenceMapper(IPageParametersEncoder 
pageParametersEncoder, Supplier<? extends IResourceCachingStrategy> 
cachingStrategy, boolean checkHashCollision)
+               {
+                       super(pageParametersEncoder, cachingStrategy);
+            this.checkHashCollision = checkHashCollision;
+        }
+
+               @Override
+               protected Class<?> resolveClass(String name)
+               {
+                       try
+                       {
+                               long hash = Long.parseLong(name);
+                               String className = hashMap.get(hash);
+                               if (className == null)
+                               {
+                                       return super.getPageClass(name);
+                               }
+                               return super.resolveClass(className);
+                       }
+                       catch (NumberFormatException e)
+                       {
+                               return super.getPageClass(name);
+                       }
+               }
+
+               @Override
+               protected String getClassName(Class<?> scope)
+               {
+                       String name = super.getClassName(scope);
+                       long hash = scope.hashCode();
+                       if (checkHashCollision) {
+                               String existing = hashMap.get(hash);
+                               if (existing != null && !existing.equals(name)) 
{
+                                       throw new WicketRuntimeException("Class 
" + name + " has collision with " + existing);
+                               }
+                       }
+                       hashMap.putIfAbsent(hash, name);
+                       return Long.toString(hash);
+               }
+       }
+
+       /**
+        * Construct.
+        *
+        * @param pageParametersEncoder {@link IPageParametersEncoder}
+        * @param parentPathPartEscapeSequence {@link Supplier<String>}
+        * @param cachingStrategy Supplier<IResourceCachingStrategy>
+        */
+       public HashBasedResourceReferenceMapper(IPageParametersEncoder 
pageParametersEncoder, Supplier<String> parentPathPartEscapeSequence, 
Supplier<IResourceCachingStrategy> cachingStrategy, boolean checkHashCollision)
+       {
+               super(new 
HashBasedBasicResourceReferenceMapper(pageParametersEncoder, cachingStrategy, 
checkHashCollision), parentPathPartEscapeSequence);
+       }
+
+}

Reply via email to