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 1606709 2014-06-30 12:26:06Z 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            else
098            {
099                throw e;
100            }
101        }
102    }
103
104    /**
105     * Create an URL based on a base URL and a resource location suitable for loading
106     * the resource.
107     *
108     * @param resourceLocation a resource location
109     * @return the corresponding URL
110     * @throws java.net.MalformedURLException creating the URL failed
111     */
112    protected URL createUrl(final String resourceLocation) throws MalformedURLException
113    {
114        // if we get an non-existing base url than the resource can
115        // be directly used to create an URL
116        if (baseUrl == null)
117        {
118            return new URL(resourceLocation);
119        }
120
121        // if we get an non-existing location what we shall do?
122        if (resourceLocation == null || resourceLocation.length() == 0)
123        {
124            throw new IllegalArgumentException("No resource defined");
125        }
126
127        // if we get a stand-alone resource than ignore the base url
128        if (isFileUrl(resourceLocation) || isHttpUrl(resourceLocation))
129        {
130            return new URL(resourceLocation);
131        }
132
133        return new URL(getBaseUrl(), resourceLocation.replaceAll("&amp;", "&"));
134    }
135}