001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.mail.resolver;
018
019import javax.activation.DataSource;
020import javax.activation.URLDataSource;
021import java.io.IOException;
022import java.net.MalformedURLException;
023import java.net.URL;
024
025/**
026 * Creates a <code>DataSource</code> based on an URL.
027 *
028 * @since 1.3
029 * @version $Id: DataSourceUrlResolver.java 1632035 2014-10-15 13:54:53Z ggregory $
030 */
031public class DataSourceUrlResolver extends DataSourceBaseResolver
032{
033    /** the base url of the resource when resolving relative paths */
034    private final URL baseUrl;
035
036    /**
037     * Constructor.
038     *
039     * @param baseUrl the base URL used for resolving relative resource locations
040     */
041    public DataSourceUrlResolver(final URL baseUrl)
042    {
043        super();
044        this.baseUrl = baseUrl;
045    }
046
047    /**
048     * Constructor.
049     *
050     * @param baseUrl the base URL used for resolving relative resource locations
051     * @param lenient shall we ignore resources not found or complain with an exception
052     */
053    public DataSourceUrlResolver(final URL baseUrl, final boolean lenient)
054    {
055        super(lenient);
056        this.baseUrl = baseUrl;
057    }
058
059    /**
060     * Get the base URL used for resolving relative resource locations.
061     *
062     * @return the baseUrl
063     */
064    public URL getBaseUrl()
065    {
066        return baseUrl;
067    }
068
069    /** {@inheritDoc} */
070    public DataSource resolve(final String resourceLocation) throws IOException
071    {
072        return resolve(resourceLocation, isLenient());
073    }
074
075    /** {@inheritDoc} */
076    public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException
077    {
078        DataSource result = null;
079
080        try
081        {
082            if (!isCid(resourceLocation))
083            {
084                final URL url = createUrl(resourceLocation);
085                result = new URLDataSource(url);
086                result.getInputStream();
087            }
088
089            return result;
090        }
091        catch (final IOException e)
092        {
093            if (isLenient)
094            {
095                return null;
096            }
097            throw e;
098        }
099    }
100
101    /**
102     * Create an URL based on a base URL and a resource location suitable for loading
103     * the resource.
104     *
105     * @param resourceLocation a resource location
106     * @return the corresponding URL
107     * @throws java.net.MalformedURLException creating the URL failed
108     */
109    protected URL createUrl(final String resourceLocation) throws MalformedURLException
110    {
111        // if we get an non-existing base url than the resource can
112        // be directly used to create an URL
113        if (baseUrl == null)
114        {
115            return new URL(resourceLocation);
116        }
117
118        // if we get an non-existing location what we shall do?
119        if (resourceLocation == null || resourceLocation.length() == 0)
120        {
121            throw new IllegalArgumentException("No resource defined");
122        }
123
124        // if we get a stand-alone resource than ignore the base url
125        if (isFileUrl(resourceLocation) || isHttpUrl(resourceLocation))
126        {
127            return new URL(resourceLocation);
128        }
129
130        return new URL(getBaseUrl(), resourceLocation.replaceAll("&amp;", "&"));
131    }
132}