1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.mail2.jakarta.resolver;
18
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.net.URL;
22
23 import jakarta.activation.DataSource;
24 import jakarta.activation.FileTypeMap;
25 import jakarta.mail.util.ByteArrayDataSource;
26
27 /**
28 * Creates a {@code DataSource} based on an class path.
29 *
30 * @since 1.3
31 */
32 public class DataSourceClassPathResolver extends DataSourceBaseResolver {
33 /** The base string of the resource relative to the classpath when resolving relative paths */
34 private final String classPathBase;
35
36 /**
37 * Constructs a new instance.
38 */
39 public DataSourceClassPathResolver() {
40 this("/");
41 }
42
43 /**
44 * Constructs a new instance.
45 *
46 * @param classPathBase a base class path
47 */
48 public DataSourceClassPathResolver(final String classPathBase) {
49 this(classPathBase, false);
50 }
51
52 /**
53 * Constructs a new instance.
54 *
55 * @param classPathBase a base class path
56 * @param lenient shall we ignore resources not found or throw an exception?
57 */
58 public DataSourceClassPathResolver(final String classPathBase, final boolean lenient) {
59 super(lenient);
60 this.classPathBase = classPathBase.endsWith("/") ? classPathBase : classPathBase + "/";
61 }
62
63 /**
64 * Gets the class path base.
65 *
66 * @return the classPathBase
67 */
68 public String getClassPathBase() {
69 return classPathBase;
70 }
71
72 /**
73 * Returns the resource name for a given resource location.
74 *
75 * @param resourceLocation the resource location
76 * @return {@link #getClassPathBase()} + {@code resourceLocation}
77 * @see #getClassPathBase()
78 */
79 private String getResourceName(final String resourceLocation) {
80 return (getClassPathBase() + resourceLocation).replace("//", "/");
81 }
82
83 /** {@inheritDoc} */
84 @Override
85 public DataSource resolve(final String resourceLocation) throws IOException {
86 return resolve(resourceLocation, isLenient());
87 }
88
89 /** {@inheritDoc} */
90 @Override
91 public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
92 try {
93 if (!isCid(resourceLocation) && !isHttpUrl(resourceLocation)) {
94 final String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(resourceLocation);
95 final String resourceName = getResourceName(resourceLocation);
96 try (InputStream inputStream = DataSourceClassPathResolver.class.getResourceAsStream(resourceName)) {
97 if (inputStream == null) {
98 if (isLenient) {
99 return null;
100 }
101 throw new IOException("The following class path resource was not found : " + resourceLocation);
102 }
103 final ByteArrayDataSource ds = new ByteArrayDataSource(inputStream, mimeType);
104 // EMAIL-125: set the name of the DataSource to the normalized resource URL
105 // similar to other DataSource implementations, e.g. FileDataSource, URLDataSource
106 final URL resource = DataSourceClassPathResolver.class.getResource(resourceName);
107 if (resource != null) {
108 ds.setName(resource.toString());
109 } else if (isLenient) {
110 return null;
111 } else {
112 throw new IOException("The following class path resource was not found : " + resourceName);
113 }
114 return ds;
115 }
116 }
117 return null;
118 } catch (final IOException e) {
119 if (isLenient) {
120 return null;
121 }
122 throw e;
123 }
124 }
125 }