Author: chris.laprun(a)jboss.com
Date: 2007-03-06 14:38:56 -0500 (Tue, 06 Mar 2007)
New Revision: 6559
Added:
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLStreamOpeningThread.java
Modified:
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLTools.java
Log:
- JBPORTAL-1279: Backported to 2.4
Added:
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLStreamOpeningThread.java
===================================================================
---
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLStreamOpeningThread.java
(rev 0)
+++
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLStreamOpeningThread.java 2007-03-06
19:38:56 UTC (rev 6559)
@@ -0,0 +1,90 @@
+/*
+* JBoss, a division of Red Hat
+* Copyright 2006, Red Hat Middleware, LLC, and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+*/
+
+package org.jboss.portal.common.util;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * A class that opens an InputStream to a URL in a thread so that it doesn't block
normal operations and can be timed
+ * out if needed.
+ *
+ * @author <a href="mailto:chris.laprun@jboss.com">Chris
Laprun</a>
+ * @version $Revision$
+ * @since 2.4.2
+ */
+public class URLStreamOpeningThread extends Thread
+{
+ volatile private URL url;
+
+ /** */
+ private InputStream inputStream;
+
+ /** Exception in the event a connection error occurs */
+ private IOException exception = null;
+
+ public URLStreamOpeningThread(URL url)
+ {
+ ParameterValidation.throwIllegalArgExceptionIfNull(url, "URL");
+
+ this.url = url;
+ }
+
+ public void run()
+ {
+ try
+ {
+ inputStream = url.openStream();
+ if (inputStream == null)
+ {
+ throw new IllegalArgumentException("Cannot open stream from [" +
url + "]");
+ }
+ }
+ catch (IOException e)
+ {
+ exception = e;
+ }
+ }
+
+ public boolean isConnected()
+ {
+ return inputStream != null;
+ }
+
+ public boolean isError()
+ {
+ return exception != null;
+ }
+
+ public InputStream getInputStream()
+ {
+ return inputStream;
+ }
+
+ public IOException getException()
+ {
+ return exception;
+ }
+}
Property changes on:
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLStreamOpeningThread.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
Modified:
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLTools.java
===================================================================
---
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLTools.java 2007-03-06
19:01:39 UTC (rev 6558)
+++
branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util/URLTools.java 2007-03-06
19:38:56 UTC (rev 6559)
@@ -20,12 +20,11 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
* 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
******************************************************************************/
-
package org.jboss.portal.common.util;
-import java.io.IOException;
-import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
@@ -41,19 +40,35 @@
public class URLTools
{
public static final String RE_EMAIL_VALIDATION =
"^([a-zA-Z0-9]+(([\\.\\-\\_]?[a-zA-Z0-9]+)+)?)\\(a)(([a-zA-Z0-9]+[\\.\\-\\_])+[a-zA-Z]{2,4})$";
- private static final Pattern LINK =
Pattern.compile("(?:href|action|src)\\s*=\\s*('|\")\\s*([^'\"]*)\\s*('|\")",
+ private static final Pattern LINK =
Pattern.compile("(?:href|action|src|location)\\s*=\\s*('|\")\\s*([^'\"]*)\\s*('|\")",
Pattern.CASE_INSENSITIVE);
public static final String HTTP_PREFIX = "http://";
public static final String HTTPS_PREFIX = "https://";
+ public static final String FTP_PREFIX = "ftp://";
public static final String FILE_PREFIX = "/";
public static boolean isURLAbsolute(String url)
{
- return url.startsWith(HTTP_PREFIX) || url.startsWith(HTTPS_PREFIX) ||
url.startsWith(FILE_PREFIX);
+ return isNetworkURL(url) || url.startsWith(FILE_PREFIX);
}
/**
+ * @param url
+ * @return
+ * @since 2.4.2
+ */
+ public static boolean isNetworkURL(String url)
+ {
+ if (url == null || url.length() == 0)
+ {
+ return false;
+ }
+
+ return url.startsWith(HTTP_PREFIX) || url.startsWith(HTTPS_PREFIX) ||
url.startsWith(FTP_PREFIX);
+ }
+
+ /**
* Enforces that the given URL is absolute
*
* @param url the String representation of the URL to be checked
@@ -97,28 +112,89 @@
return address != null && Pattern.matches(RE_EMAIL_VALIDATION, address);
}
- public static boolean exists(java.net.URL url)
+ /**
+ * Determines that the specified URL corresponds to an existing resource by trying to
open a stream from it. Same as
+ * <code>exists(url, 1000)</code>
+ *
+ * @param url
+ * @return
+ */
+ public static boolean exists(URL url)
{
- if (url == null)
- {
- throw new IllegalArgumentException("No null urls allowed");
- }
- InputStream in = null;
+ ParameterValidation.throwIllegalArgExceptionIfNull(url, "URL");
+
+ return exists(url, 1000);
+ }
+
+ /**
+ * Determines if the specified URL corresponds to an existing resource by trying to
open a stream from it. The
+ * connection attempt is made from a different thread on which we wait for the
specified amount of time before timing
+ * out.
+ *
+ * @param url the URL to be tested
+ * @param waitForMillis the number of milliseconds to wait before timing out, 0
meaning never timing out.
+ * @return
+ * @since 2.4.2
+ */
+ public static boolean exists(URL url, long waitForMillis)
+ {
+ URLStreamOpeningThread thread = new URLStreamOpeningThread(url);
+ thread.start();
+
try
{
- in = url.openStream();
- return true;
+ // Wait for the thread to finish but don't wait longer than the specified
time
+ thread.join(waitForMillis);
+
+ if (thread.isAlive())
+ {
+ // Timeout occurred; thread has not finished
+ throw new RuntimeException("Couldn't connect to " + url +
" within " + waitForMillis / 1000
+ + " seconds. Check your connection parameters or the URL.");
+ }
+ else
+ {
+ // Finished
+ return thread.isConnected() && !thread.isError();
+ }
}
- catch (IOException e)
+ catch (InterruptedException e)
{
- return false;
+ // Thread was interrupted
+ throw new RuntimeException("Connection thread to " + url + " was
interrupted!", e);
}
finally
{
- Tools.safeClose(in);
+ Tools.safeClose(thread.getInputStream());
}
}
+ /**
+ * @param urlAsString
+ * @param allowNull <code>true</code> if passing
<code>null</code> will be ignored and just return
+ * <code>false</code>, <code>false</code>
to throw an {@link IllegalArgumentException} is the
+ * given URL is <code>null</code>.
+ * @return
+ * @since 2.4.2
+ */
+ public static boolean exists(String urlAsString, boolean allowNull)
+ {
+ if (!allowNull)
+ {
+ ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(urlAsString,
"URL", null);
+ }
+
+ try
+ {
+ URL url = new URL(urlAsString);
+ return exists(url);
+ }
+ catch (MalformedURLException e)
+ {
+ return false;
+ }
+ }
+
public static URLMatch[] extractURLsFrom(String markup)
{
// todo: will need to re-write without regex after 2.4
@@ -232,4 +308,55 @@
{
public abstract String getReplacementFor(int currentIndex, URLMatch currentMatch);
}
+
+ /** @since 2.4.2 */
+ public static class PortReplacementGenerator extends URLReplacementGenerator
+ {
+ private int replacementPort;
+
+ public PortReplacementGenerator(int replacementPort)
+ {
+ this.replacementPort = replacementPort;
+ }
+
+ public String getReplacementFor(int currentIndex, URLMatch currentMatch)
+ {
+ return replaceServerPortInURL(currentMatch.getURLAsString(), replacementPort);
+ }
+ }
+
+ /**
+ * @param url
+ * @param newPort
+ * @return
+ * @since 2.4.2
+ */
+ public static String replaceServerPortInURL(String url, int newPort)
+ {
+ if (!isNetworkURL(url))
+ {
+ return url;
+ }
+
+ StringBuffer buf = new StringBuffer(url);
+ int afterProtocol = url.indexOf("://") + 3;
+ int beforePort = url.indexOf(':', afterProtocol);
+ int afterPort;
+
+ if (beforePort != -1)
+ {
+ afterPort = url.indexOf('/', beforePort);
+ buf.delete(beforePort + 1, afterPort);
+ buf.insert(beforePort + 1, newPort);
+ }
+ else
+ {
+ // port number was not present
+ afterPort = url.indexOf('/', afterProtocol);
+ buf.insert(afterPort, ":" + newPort);
+ }
+
+ return buf.toString();
+ }
+
}