From portal-commits at lists.jboss.org Tue Mar 6 14:38:56 2007 Content-Type: multipart/mixed; boundary="===============6846597247888375177==" MIME-Version: 1.0 From: portal-commits at lists.jboss.org To: portal-commits at lists.jboss.org Subject: [portal-commits] JBoss Portal SVN: r6559 - branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/common/util. Date: Tue, 06 Mar 2007 14:38:56 -0500 Message-ID: --===============6846597247888375177== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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/co= mmon/util/URLStreamOpeningThread.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/commo= n/util/URLStreamOpeningThread.java (rev 0) +++ branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/commo= n/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 Chris Laprun + * @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 =3D null; + + public URLStreamOpeningThread(URL url) + { + ParameterValidation.throwIllegalArgExceptionIfNull(url, "URL"); + + this.url =3D url; + } + + public void run() + { + try + { + inputStream =3D url.openStream(); + if (inputStream =3D=3D null) + { + throw new IllegalArgumentException("Cannot open stream from ["= + url + "]"); + } + } + catch (IOException e) + { + exception =3D e; + } + } + + public boolean isConnected() + { + return inputStream !=3D null; + } + + public boolean isError() + { + return exception !=3D null; + } + + public InputStream getInputStream() + { + return inputStream; + } + + public IOException getException() + { + return exception; + } +} Property changes on: branches/JBoss_Portal_Branch_2_4/common/src/main/org/j= boss/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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/commo= n/util/URLTools.java 2007-03-06 19:01:39 UTC (rev 6558) +++ branches/JBoss_Portal_Branch_2_4/common/src/main/org/jboss/portal/commo= n/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 =3D "^([a-zA-Z0-9]+(([\\= .\\-\\_]?[a-zA-Z0-9]+)+)?)\\@(([a-zA-Z0-9]+[\\.\\-\\_])+[a-zA-Z]{2,4})$"; - private static final Pattern LINK =3D Pattern.compile("(?:href|action|s= rc)\\s*=3D\\s*('|\")\\s*([^'\"]*)\\s*('|\")", + private static final Pattern LINK =3D Pattern.compile("(?:href|action|s= rc|location)\\s*=3D\\s*('|\")\\s*([^'\"]*)\\s*('|\")", Pattern.CASE_INSENSITIVE); = public static final String HTTP_PREFIX =3D "http://"; public static final String HTTPS_PREFIX =3D "https://"; + public static final String FTP_PREFIX =3D "ftp://"; public static final String FILE_PREFIX =3D "/"; = 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 =3D=3D null || url.length() =3D=3D 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 !=3D null && Pattern.matches(RE_EMAIL_VALIDATION, add= ress); } = - public static boolean exists(java.net.URL url) + /** + * Determines that the specified URL corresponds to an existing resourc= e by trying to open a stream from it. Same as + * exists(url, 1000) + * + * @param url + * @return + */ + public static boolean exists(URL url) { - if (url =3D=3D null) - { - throw new IllegalArgumentException("No null urls allowed"); - } - InputStream in =3D 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 timin= g out, 0 meaning never timing out. + * @return + * @since 2.4.2 + */ + public static boolean exists(URL url, long waitForMillis) + { + URLStreamOpeningThread thread =3D new URLStreamOpeningThread(url); + thread.start(); + try { - in =3D url.openStream(); - return true; + // Wait for the thread to finish but don't wait longer than the s= pecified time + thread.join(waitForMillis); + + if (thread.isAlive()) + { + // Timeout occurred; thread has not finished + throw new RuntimeException("Couldn't connect to " + url + " wi= thin " + 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 true if passing null wi= ll be ignored and just return + * false, false to throw a= n {@link IllegalArgumentException} is the + * given URL is null. + * @return + * @since 2.4.2 + */ + public static boolean exists(String urlAsString, boolean allowNull) + { + if (!allowNull) + { + ParameterValidation.throwIllegalArgExceptionIfNullOrEmpty(urlAsSt= ring, "URL", null); + } + + try + { + URL url =3D 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 URLReplacementGene= rator + { + private int replacementPort; + + public PortReplacementGenerator(int replacementPort) + { + this.replacementPort =3D replacementPort; + } + + public String getReplacementFor(int currentIndex, URLMatch currentMa= tch) + { + return replaceServerPortInURL(currentMatch.getURLAsString(), repl= acementPort); + } + } + + /** + * @param url + * @param newPort + * @return + * @since 2.4.2 + */ + public static String replaceServerPortInURL(String url, int newPort) + { + if (!isNetworkURL(url)) + { + return url; + } + + StringBuffer buf =3D new StringBuffer(url); + int afterProtocol =3D url.indexOf("://") + 3; + int beforePort =3D url.indexOf(':', afterProtocol); + int afterPort; + + if (beforePort !=3D -1) + { + afterPort =3D url.indexOf('/', beforePort); + buf.delete(beforePort + 1, afterPort); + buf.insert(beforePort + 1, newPort); + } + else + { + // port number was not present + afterPort =3D url.indexOf('/', afterProtocol); + buf.insert(afterPort, ":" + newPort); + } + + return buf.toString(); + } + } --===============6846597247888375177==--