/*
* 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.openejb.core.webservices;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.loader.IO;
import org.apache.openejb.util.Base64;
import org.apache.openejb.util.JavaSecurityManagers;
import org.apache.openejb.util.URLs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
/**
* Resolves a File, classpath resource, or URL according to the follow rules:
* <ul>
* <li>Check to see if a file exists, relative to the base URI.</li>
* <li>If the file doesn't exist, check the classpath</li>
* <li>If the classpath doesn't exist, try to create URL from the URI.</li>
* </ul>
*/
// Imported from CXF
public class UriResolver {
private File file;
private URI uri;
private URL url;
private InputStream is;
private Class calling;
public UriResolver() {
}
public UriResolver(final String path) throws IOException {
this("", path);
}
public UriResolver(final String baseUriStr, final String uriStr) throws IOException {
this(baseUriStr, uriStr, null);
}
public UriResolver(final String baseUriStr, final String uriStr, final Class calling) throws IOException {
this.calling = calling != null ? calling : getClass();
if (uriStr.startsWith("classpath:")) {
tryClasspath(uriStr);
} else if (baseUriStr != null && baseUriStr.startsWith("jar:")) {
tryJar(baseUriStr, uriStr);
} else if (uriStr.startsWith("jar:")) {
tryJar(uriStr);
} else {
tryFileSystem(baseUriStr, uriStr);
}
}
public void resolve(final String baseUriStr, final String uriStr, final Class callingCls) throws IOException {
this.calling = callingCls != null ? callingCls : getClass();
this.file = null;
this.uri = null;
this.is = null;
if (uriStr.startsWith("classpath:")) {
tryClasspath(uriStr);
} else if (baseUriStr != null && baseUriStr.startsWith("jar:")) {
tryJar(baseUriStr, uriStr);
} else if (uriStr.startsWith("jar:")) {
tryJar(uriStr);
} else {
tryFileSystem(baseUriStr, uriStr);
}
}
private void tryFileSystem(final String baseUriStr, final String uriStr) throws IOException, MalformedURLException {
final URI relative;
File uriFile = new File(uriStr);
uriFile = new File(uriFile.getAbsolutePath());
if (uriFile.exists()) {
relative = uriFile.toURI();
} else {
relative = URLs.uri(uriStr);
}
if (relative.isAbsolute()) {
uri = relative;
url = relative.toURL();
try {
final HttpURLConnection huc = (HttpURLConnection) url.openConnection();
final String host = JavaSecurityManagers.getSystemProperty("http.proxyHost");
if (host != null) {
//comment out unused port to pass pmd check
/*String ports = JavaSecurityManagers.getSystemProperty("http.proxyPort");
int port = 80;
if (ports != null) {
port = Integer.parseInt(ports);
}*/
final String username = JavaSecurityManagers.getSystemProperty("http.proxy.user");
final String password = JavaSecurityManagers.getSystemProperty("http.proxy.password");
if (username != null && password != null) {
final String encoded = new String(Base64.encodeBase64((username + ":" + password).getBytes()));
huc.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
}
}
is = huc.getInputStream();
} catch (final ClassCastException ex) {
is = IO.read(url);
}
} else if (baseUriStr != null) {
URI base;
File baseFile = new File(baseUriStr);
if (!baseFile.exists() && baseUriStr.startsWith("file:/")) {
baseFile = new File(baseUriStr.substring(6));
}
if (baseFile.exists()) {
base = baseFile.toURI();
} else {
base = URLs.uri(baseUriStr);
}
base = base.resolve(relative);
if (base.isAbsolute()) {
try {
baseFile = new File(base);
if (baseFile.exists()) {
is = IO.read(base.toURL());
uri = base;
} else {
tryClasspath(base.toString().startsWith("file:")
? base.toString().substring(5) : base.toString());
}
} catch (final Throwable th) {
tryClasspath(base.toString().startsWith("file:")
? base.toString().substring(5) : base.toString());
}
}
}
if (uri != null && "file".equals(uri.getScheme())) {
try {
file = new File(uri);
} catch (final IllegalArgumentException iae) {
file = URLs.toFile(uri.toURL());
if (!file.exists()) {
file = null;
}
}
}
if (is == null && file != null && file.exists()) {
uri = file.toURI();
try {
is = new FileInputStream(file);
} catch (final FileNotFoundException e) {
throw new OpenEJBRuntimeException("File was deleted! " + uriStr, e);
}
url = file.toURI().toURL();
} else if (is == null) {
tryClasspath(uriStr);
}
}
private void tryJar(final String baseStr, final String uriStr) throws IOException {
final int i = baseStr.indexOf('!');
if (i == -1) {
tryFileSystem(baseStr, uriStr);
}
final String jarBase = baseStr.substring(0, i + 1);
final String jarEntry = baseStr.substring(i + 1);
final URI u = URLs.uri(jarEntry).resolve(uriStr);
tryJar(jarBase + u.toString());
if (is != null) {
if (u.isAbsolute()) {
url = u.toURL();
}
return;
}
tryFileSystem("", uriStr);
}
private void tryJar(String uriStr) throws IOException {
final int i = uriStr.indexOf('!');
if (i == -1) {
return;
}
url = new URL(uriStr);
try {
is = IO.read(url);
try {
uri = url.toURI();
} catch (final URISyntaxException ex) {
// ignore
}
} catch (final IOException e) {
uriStr = uriStr.substring(i + 1);
tryClasspath(uriStr);
}
}
private void tryClasspath(String uriStr) throws IOException {
if (uriStr.startsWith("classpath:")) {
uriStr = uriStr.substring(10);
}
url = getResource(uriStr, calling);
if (url == null) {
tryRemote(uriStr);
} else {
try {
uri = url.toURI();
} catch (final URISyntaxException e) {
// processing the jar:file:/ type value
final String urlStr = url.toString();
if (urlStr.startsWith("jar:")) {
final int pos = urlStr.indexOf('!');
if (pos != -1) {
uri = URLs.uri("classpath:" + urlStr.substring(pos + 1));
}
}
}
is = IO.read(url);
}
}
private void tryRemote(final String uriStr) throws IOException {
try {
url = new URL(URLEncoder.encode(uriStr, "UTF-8"));
uri = URLs.uri(url.toString());
is = IO.read(url);
} catch (final MalformedURLException e) {
// do nothing
}
}
public URI getURI() {
return uri;
}
public URL getURL() {
return url;
}
public InputStream getInputStream() {
return is;
}
public boolean isFile() {
return file != null && file.exists();
}
public File getFile() {
return file;
}
public boolean isResolved() {
return is != null;
}
/**
* Load a given resource. <p/> This method will try to load the resource
* using the following methods (in order):
* <ul>
* <li>From Thread.currentThread().getContextClassLoader()
* <li>From ClassLoaderUtil.class.getClassLoader()
* <li>callingClass.getClassLoader()
* </ul>
*
* @param resourceName The name of the resource to load
* @param callingClass The Class object of the calling object
*/
public static URL getResource(final String resourceName, final Class callingClass) {
URL url = Thread.currentThread().getContextClassLoader().getResource(resourceName);
if (url == null) {
url = UriResolver.class.getClassLoader().getResource(resourceName);
}
if (url == null) {
final ClassLoader cl = callingClass.getClassLoader();
if (cl != null) {
url = cl.getResource(resourceName);
}
}
if (url == null) {
url = callingClass.getResource(resourceName);
}
if (url == null && resourceName != null && resourceName.charAt(0) != '/') {
return getResource('/' + resourceName, callingClass);
}
return url;
}
}