You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2012/03/08 14:27:15 UTC
git commit: WICKET-4443 AbstractClassResolver recreates URL
incorrectly
Updated Branches:
refs/heads/wicket-1.5.x b58a5ea76 -> 6791d1abc
WICKET-4443 AbstractClassResolver recreates URL incorrectly
Use a custom comparator when using Set<URL>.
Add a comment explaining how to deal with URLs with custom schemes in UrlResourceStreamReference.
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/6791d1ab
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/6791d1ab
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/6791d1ab
Branch: refs/heads/wicket-1.5.x
Commit: 6791d1abc13deddccbfd74e00583b53ddb27eae8
Parents: b58a5ea
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Thu Mar 8 15:12:17 2012 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Thu Mar 8 15:12:17 2012 +0200
----------------------------------------------------------------------
.../wicket/application/AbstractClassResolver.java | 27 ++++-------
.../wicket/application/CompoundClassResolver.java | 16 ++-----
.../wicket/application/ReloadingClassLoader.java | 5 +-
.../caching/UrlResourceStreamReference.java | 15 +++++-
.../collections/UrlExternalFormComparator.java | 38 +++++++++++++++
5 files changed, 66 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/6791d1ab/wicket-core/src/main/java/org/apache/wicket/application/AbstractClassResolver.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/application/AbstractClassResolver.java b/wicket-core/src/main/java/org/apache/wicket/application/AbstractClassResolver.java
index 5ded671..584d928 100644
--- a/wicket-core/src/main/java/org/apache/wicket/application/AbstractClassResolver.java
+++ b/wicket-core/src/main/java/org/apache/wicket/application/AbstractClassResolver.java
@@ -18,17 +18,16 @@ package org.apache.wicket.application;
import java.lang.ref.WeakReference;
import java.net.URL;
-import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.wicket.Application;
import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.util.collections.UrlExternalFormComparator;
/**
* An abstract implementation of a {@link IClassResolver} which uses a {@link ClassLoader} for
@@ -126,35 +125,28 @@ public abstract class AbstractClassResolver implements IClassResolver
public Iterator<URL> getResources(final String name)
{
- List<URL> resultList = new ArrayList<URL>();
+ Set<URL> resultSet = new TreeSet<URL>(new UrlExternalFormComparator());
- // URL's externalForm should be used instead of URLs as Set keys. See WICKET-3867/4203.
- Set<String> loadedResources = new HashSet<String>();
try
{
// Try the classloader for the wicket jar/bundle
Enumeration<URL> resources = Application.class.getClassLoader().getResources(name);
- loadResources(resources, loadedResources);
+ loadResources(resources, resultSet);
// Try the classloader for the user's application jar/bundle
resources = Application.get().getClass().getClassLoader().getResources(name);
- loadResources(resources, loadedResources);
+ loadResources(resources, resultSet);
// Try the context class loader
resources = getClassLoader().getResources(name);
- loadResources(resources, loadedResources);
-
- for (String urlExternalForm : loadedResources)
- {
- resultList.add(new URL(urlExternalForm));
- }
+ loadResources(resources, resultSet);
}
catch (Exception e)
{
throw new WicketRuntimeException(e);
}
- return resultList.iterator();
+ return resultSet.iterator();
}
/**
@@ -162,15 +154,14 @@ public abstract class AbstractClassResolver implements IClassResolver
* @param resources
* @param loadedResources
*/
- private void loadResources(Enumeration<URL> resources, Set<String> loadedResources)
+ private void loadResources(Enumeration<URL> resources, Set<URL> loadedResources)
{
if (resources != null)
{
while (resources.hasMoreElements())
{
final URL url = resources.nextElement();
- String externalForm = url.toExternalForm();
- loadedResources.add(externalForm);
+ loadedResources.add(url);
}
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/6791d1ab/wicket-core/src/main/java/org/apache/wicket/application/CompoundClassResolver.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/application/CompoundClassResolver.java b/wicket-core/src/main/java/org/apache/wicket/application/CompoundClassResolver.java
index 3676308..dfd5cc5 100644
--- a/wicket-core/src/main/java/org/apache/wicket/application/CompoundClassResolver.java
+++ b/wicket-core/src/main/java/org/apache/wicket/application/CompoundClassResolver.java
@@ -17,13 +17,13 @@
package org.apache.wicket.application;
import java.net.URL;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
+import org.apache.wicket.util.collections.UrlExternalFormComparator;
import org.apache.wicket.util.lang.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -91,23 +91,15 @@ public class CompoundClassResolver implements IClassResolver
{
Args.notNull(name, "name");
- Set<String> externalForms = new TreeSet<String>();
- List<URL> urls = new ArrayList<URL>();
+ Set<URL> urls = new TreeSet<URL>(new UrlExternalFormComparator());
+
for (IClassResolver resolver : resolvers)
{
Iterator<URL> it = resolver.getResources(name);
while (it.hasNext())
{
URL url = it.next();
-
- // use URL's external form to make the check for equality/containment
- // because URL makes domain name resolution and is slow
- String externalForm = url.toExternalForm();
- if (externalForms.contains(externalForm) == false)
- {
- externalForms.add(externalForm);
- urls.add(url);
- }
+ urls.add(url);
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/6791d1ab/wicket-core/src/main/java/org/apache/wicket/application/ReloadingClassLoader.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/application/ReloadingClassLoader.java b/wicket-core/src/main/java/org/apache/wicket/application/ReloadingClassLoader.java
index 9036e57..13ac77d 100644
--- a/wicket-core/src/main/java/org/apache/wicket/application/ReloadingClassLoader.java
+++ b/wicket-core/src/main/java/org/apache/wicket/application/ReloadingClassLoader.java
@@ -21,11 +21,12 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
+import org.apache.wicket.util.collections.UrlExternalFormComparator;
import org.apache.wicket.util.file.File;
import org.apache.wicket.util.listener.IChangeListener;
import org.apache.wicket.util.time.Duration;
@@ -45,7 +46,7 @@ public class ReloadingClassLoader extends URLClassLoader
{
private static final Logger log = LoggerFactory.getLogger(ReloadingClassLoader.class);
- private static final Set<URL> urls = new HashSet<URL>();
+ private static final Set<URL> urls = new TreeSet<URL>(new UrlExternalFormComparator());
private static final List<String> patterns = new ArrayList<String>();
http://git-wip-us.apache.org/repos/asf/wicket/blob/6791d1ab/wicket-core/src/main/java/org/apache/wicket/util/resource/locator/caching/UrlResourceStreamReference.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/util/resource/locator/caching/UrlResourceStreamReference.java b/wicket-core/src/main/java/org/apache/wicket/util/resource/locator/caching/UrlResourceStreamReference.java
index ddbae63..a9f158b 100644
--- a/wicket-core/src/main/java/org/apache/wicket/util/resource/locator/caching/UrlResourceStreamReference.java
+++ b/wicket-core/src/main/java/org/apache/wicket/util/resource/locator/caching/UrlResourceStreamReference.java
@@ -23,7 +23,13 @@ import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.util.resource.UrlResourceStream;
/**
- * A reference which may be used to recreate {@link UrlResourceStream}
+ * A reference which may be used to recreate {@link UrlResourceStream}.
+ * <p>
+ * If the UrlResourceStream deals with URLs with custom {@link java.net.URLStreamHandler}
+ * then you will need to export <em>java.protocol.handler.pkgs</em> system property
+ * so that the JVM can automatically use them to re-create the URL from its cached
+ * external form.
+ * </p>
*/
class UrlResourceStreamReference extends AbstractResourceStreamReference
{
@@ -45,8 +51,11 @@ class UrlResourceStreamReference extends AbstractResourceStreamReference
}
catch (MalformedURLException e)
{
- // should not ever happen. The cached url is created by previously existing URL
- // instance
+ // It can happen when the previously existing URL had a non-standard protocol, and
+ // had a custom URLStreamHandler associated with it, which knew how to deal with
+ // said protocol. When the URL is recreated from the external form, the
+ // URLStreamHandler is no longer associated, and, if the URL has a non-standard
+ // protocol for which Java has no handler, a MalformedURLException will be thrown.
throw new WicketRuntimeException(e);
}
}
http://git-wip-us.apache.org/repos/asf/wicket/blob/6791d1ab/wicket-util/src/main/java/org/apache/wicket/util/collections/UrlExternalFormComparator.java
----------------------------------------------------------------------
diff --git a/wicket-util/src/main/java/org/apache/wicket/util/collections/UrlExternalFormComparator.java b/wicket-util/src/main/java/org/apache/wicket/util/collections/UrlExternalFormComparator.java
new file mode 100644
index 0000000..d79e2d8
--- /dev/null
+++ b/wicket-util/src/main/java/org/apache/wicket/util/collections/UrlExternalFormComparator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.util.collections;
+
+import java.net.URL;
+import java.util.Comparator;
+
+/**
+ * A comparator of URL instances.
+ *
+ * Comparing URLs with their implementation of #equals() is
+ * bad because it may cause problems like DNS resolving, or other
+ * slow checks. This comparator uses the external form of an URL
+ * to make a simple comparison of two Strings.
+ *
+ * @since 1.5.6
+ */
+public class UrlExternalFormComparator implements Comparator<URL>
+{
+ public int compare(URL url1, URL url2)
+ {
+ return url1.toExternalForm().compareTo(url2.toExternalForm());
+ }
+}