| /* |
| * 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.netbeans.modules.extbrowser; |
| |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.Iterator; |
| import java.net.URL; |
| import java.net.MalformedURLException; |
| import java.net.URISyntaxException; |
| |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.URLMapper; |
| import org.openide.util.Lookup; |
| |
| /** Utility class for various useful URL-related tasks. |
| * <p>There is similar class in extbrowser/webclient module doing almost the same work. |
| * @author Petr Jiricka |
| */ |
| public class URLUtil { |
| |
| /** results with URLMapper instances*/ |
| private static Lookup.Result result; |
| |
| static { |
| result = Lookup.getDefault().lookup(new Lookup.Template (URLMapper.class)); |
| } |
| |
| /** Creates a URL that is suitable for using in a different process on the |
| * same node, similarly to URLMapper.EXTERNAL. May just return the original |
| * URL if that's good enough. |
| * @param url URL that needs to be displayed in browser |
| * @param allowJar is <CODE>jar:</CODE> acceptable protocol? |
| * @return browsable URL or null |
| */ |
| public static URL createExternalURL(URL url, boolean allowJar) { |
| if (url == null) |
| return null; |
| |
| URL compliantURL = getFullyRFC2396CompliantURL(url); |
| |
| // return if the protocol is fine |
| if (isAcceptableProtocol(compliantURL, allowJar)) |
| return compliantURL; |
| |
| // remove the anchor |
| String anchor = compliantURL.getRef(); |
| String urlString = compliantURL.toString (); |
| int ind = urlString.indexOf('#'); |
| if (ind >= 0) { |
| urlString = urlString.substring(0, ind); |
| } |
| |
| // map to an external URL using the anchor-less URL |
| try { |
| FileObject fo = URLMapper.findFileObject(new URL(urlString)); |
| if (fo != null) { |
| URL newUrl = getURLOfAppropriateType(fo, allowJar); |
| if (newUrl != null) { |
| // re-add the anchor if exists |
| urlString = newUrl.toString(); |
| if (ind >=0) { |
| urlString = urlString + "#" + anchor; // NOI18N |
| } |
| return new URL(urlString); |
| } |
| } |
| } |
| catch (MalformedURLException e) { |
| Logger.getLogger("global").log(Level.INFO, null, e); |
| } |
| |
| return compliantURL; |
| } |
| |
| private static URL getFullyRFC2396CompliantURL(URL url){ |
| String urlStr = url.toString(); |
| int ind = urlStr.indexOf('#'); |
| |
| if (ind > -1) { |
| String urlWithoutRef = urlStr.substring(0, ind); |
| try { |
| String asciiURL = url.toURI().toASCIIString(); |
| // TODO: why not to use just escapedURL = new URL(asciiURL) ? |
| ind = asciiURL.indexOf('#'); |
| String anchorEscaped = asciiURL.substring(ind); |
| URL escapedURL = new URL(urlWithoutRef + anchorEscaped); |
| return escapedURL; |
| } catch (URISyntaxException | MalformedURLException ex) { |
| Logger.getLogger("global").log(Level.SEVERE, ex.getMessage(), ex); |
| } |
| } |
| |
| return url; |
| } |
| |
| /** Returns a URL for the given file object that can be correctly interpreted |
| * by usual web browsers (including Netscape 4.71, IE and Mozilla). |
| * First attempts to get an EXTERNAL URL, if that is a suitable URL, it is used; |
| * otherwise a NETWORK URL is used. |
| */ |
| private static URL getURLOfAppropriateType(FileObject fo, boolean allowJar) { |
| // PENDING - there is still the problem that the HTTP server will be started |
| // (because the HttpServerURLMapper.getURL(...) method starts it), |
| // even when it is not needed |
| URL retVal; |
| URL suitable = null; |
| |
| Iterator instances = result.allInstances ().iterator(); |
| while (instances.hasNext()) { |
| URLMapper mapper = (URLMapper) instances.next(); |
| retVal = mapper.getURL (fo, URLMapper.EXTERNAL); |
| if ((retVal != null) && isAcceptableProtocol(retVal, allowJar)) { |
| // return if this is a 'file' or 'jar' URL |
| String p = retVal.getProtocol().toLowerCase(); |
| if ("file".equals(p) || "jar".equals(p)) { // NOI18N |
| return retVal; |
| } |
| suitable = retVal; |
| } |
| } |
| |
| // if we found a suitable URL, return it |
| if (suitable != null) { |
| return suitable; |
| } |
| |
| URL url = URLMapper.findURL(fo, URLMapper.NETWORK); |
| |
| if (url == null){ |
| Logger.getLogger("global").log(Level.SEVERE, "URLMapper.findURL() failed for " + fo); //NOI18N |
| |
| return null; |
| } |
| |
| return makeURLLocal(url); |
| } |
| |
| private static URL makeURLLocal(URL input) { |
| String host = input.getHost(); |
| try { |
| if (host.equals(InetAddress.getLocalHost().getHostName())) { |
| host = "127.0.0.1"; // NOI18N |
| return new URL(input.getProtocol(), host, input.getPort(), input.getFile()); |
| } |
| else return input; |
| } catch (UnknownHostException e) { |
| return input; |
| } catch (MalformedURLException e) { |
| return input; |
| } |
| } |
| |
| /** Returns true if the protocol is acceptable for usual web browsers. |
| * Specifically, returns true for file, http(s) and ftp protocols. |
| */ |
| private static boolean isAcceptableProtocol(URL url, boolean allowJar) { |
| String protocol = url.getProtocol().toLowerCase(); |
| if ("http".equals(protocol) // NOI18N |
| || "https".equals(protocol) // NOI18N |
| || "ftp".equals(protocol) // NOI18N |
| || "file".equals(protocol)) // NOI18N |
| return true; |
| if (allowJar && "jar".equals(protocol)) { // NOI18N |
| String urlString = url.toString(); |
| if (!urlString.toLowerCase().startsWith("jar:nbinst:")) // NOI18N |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** Determines whether a given browser is capable of displaying URLs with the jar: protocol. |
| * Currently, Mozilla and Firefox can do this. |
| * @param browser browser id - one of the constants defined in ExtWebBrowser |
| * @return true if the browser handles jar URLs |
| */ |
| public static boolean browserHandlesJarURLs(String browser) { |
| return (ExtWebBrowser.MOZILLA.equals(browser) || |
| ExtWebBrowser.FIREFOX.equals(browser)); |
| } |
| |
| } |