Skip to content

Commit

Permalink
Add DataSourcePathResolver
Browse files Browse the repository at this point in the history
Add PathDataSource
  • Loading branch information
garydgregory committed Dec 16, 2023
1 parent b866e15 commit 7cff388
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
<action type="add" due-to="Gary Gregory" dev="ggregory">Add EmailConstants.SOCKET_TIMEOUT and deprecate SOCKET_TIMEOUT_MS.</action>
<action type="add" due-to="Gary Gregory" dev="ggregory">Add Email.setSocketConnectionTimeout(Duration) and deprecate setSocketConnectionTimeout(int).</action>
<action type="add" due-to="Gary Gregory" dev="ggregory">Add Email.setSocketTimeout(Duration) and deprecate setSocketTimeout(int).</action>
<action type="add" due-to="Gary Gregory" dev="ggregory">Add PathDataSource.</action>
<action type="add" due-to="Gary Gregory" dev="ggregory">Add DataSourcePathResolver.</action>
<!-- UPDATE -->
<action type="update" due-to="Dependabot" dev="sebb">Bump org.slf4j:slf4j-jdk14 from 1.7.7 to 2.0.9 #165.</action>
<action type="update" due-to="Dependabot" dev="sebb">Bump mockito-core from 4.11.0 to 5.8.0 #187.</action>
Expand Down
129 changes: 129 additions & 0 deletions src/main/java/org/apache/commons/mail/activation/PathDataSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* 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.commons.mail.activation;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;

import javax.activation.DataSource;
import javax.activation.FileTypeMap;

/**
* Implements a simple DataSource object that encapsulates a Path. It provides data typing services via a FileTypeMap object.
*
* @see javax.activation.DataSource
* @see javax.activation.FileTypeMap
* @see javax.activation.MimetypesFileTypeMap
*
* @since 1.6.0
*/
public class PathDataSource implements DataSource {

private final Path path;
private final FileTypeMap typeMap;

/**
* Creates a new instance from a Path.
* <p>
* The file will not actually be opened until a method is called that requires the path to be opened.
* </p>
* <p>
* The type map defaults to {@link FileTypeMap#getDefaultFileTypeMap()}.
*
* @param path the path
*/
public PathDataSource(final Path path) {
this(path, FileTypeMap.getDefaultFileTypeMap());
}

/**
* Creates a new instance from a Path.
* <p>
* The file will not actually be opened until a method is called that requires the path to be opened.
* </p>
*
* @param path the path, non-null.
* @param typeMap the type map, non-null.
*/
public PathDataSource(final Path path, final FileTypeMap typeMap) {
this.path = Objects.requireNonNull(path, "path");
this.typeMap = Objects.requireNonNull(typeMap, "typeMap");
}

/**
* Gets the MIME type of the data as a String. This method uses the currently installed FileTypeMap. If there is no FileTypeMap explicitly set, the
* FileDataSource will call the <code>getDefaultFileTypeMap</code> method on FileTypeMap to acquire a default FileTypeMap.
* <p>
* By default, the FileTypeMap used will be a MimetypesFileTypeMap.
* </p>
*
* @return the MIME Type
* @see javax.activation.FileTypeMap#getDefaultFileTypeMap
*/
@Override
public String getContentType() {
return typeMap.getContentType(getName());
}

/**
* Gets an InputStream representing the the data and will throw an IOException if it can not do so. This method will return a new instance of InputStream
* with each invocation.
*
* @return an InputStream
*/
@Override
public InputStream getInputStream() throws IOException {
return Files.newInputStream(path);
}

/**
* Gets the <i>name</i> of this object. The FileDataSource will return the file name of the object.
*
* @return the name of the object.
* @see javax.activation.DataSource
*/
@Override
public String getName() {
return path.getFileName().toString();
}

/**
* Gets an OutputStream representing the the data and will throw an IOException if it can not do so. This method will return a new instance of OutputStream
* with each invocation.
*
* @return an OutputStream
*/
@Override
public OutputStream getOutputStream() throws IOException {
return Files.newOutputStream(path);
}

/**
* Gets the File object that corresponds to this FileDataSource.
*
* @return the File object for the file represented by this object.
*/
public Path getPath() {
return path;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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.commons.mail.resolver;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.activation.DataSource;

import org.apache.commons.mail.activation.PathDataSource;

/**
* Creates a {@code DataSource} based on a Path. The implementation also resolves file resources.
*
* @since 1.6.0
*/
public final class DataSourcePathResolver extends DataSourceBaseResolver {

/** The base directory of the resource when resolving relative paths */
private final Path baseDir;

/**
* Constructs a new instance.
*/
public DataSourcePathResolver() {
baseDir = Paths.get(".");
}

/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
*/
public DataSourcePathResolver(final Path baseDir) {
this.baseDir = baseDir;
}

/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
* @param lenient shall we ignore resources not found or complain with an exception
*/
public DataSourcePathResolver(final Path baseDir, final boolean lenient) {
super(lenient);
this.baseDir = baseDir;
}

/**
* Gets the base directory used for resolving relative resource locations.
*
* @return the baseUrl
*/
public Path getBaseDir() {
return baseDir;
}

/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
return resolve(resourceLocation, isLenient());
}

/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
Path file;
DataSource result = null;

if (!isCid(resourceLocation)) {
file = Paths.get(resourceLocation);

if (!file.isAbsolute()) {
file = getBaseDir() != null ? getBaseDir().resolve(resourceLocation) : Paths.get(resourceLocation);
}

if (Files.exists(file)) {
result = new PathDataSource(file);
} else if (!isLenient) {
throw new IOException("Cant resolve the following file resource :" + file.toAbsolutePath());
}
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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.commons.mail.resolver;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.io.IOException;
import java.nio.file.Paths;

import org.apache.commons.mail.DataSourceResolver;
import org.junit.jupiter.api.Test;

/**
* JUnit test case for DateSourceResolver.
*/
public class DataSourcePathResolverTest extends AbstractDataSourceResolverTest {

@Test
public void testResolveLenient() throws Exception {
final DataSourceResolver dataSourceResolver = new DataSourcePathResolver(Paths.get("./src/test/resources"), true);
assertEquals(IMG_SIZE, toByteArray(dataSourceResolver.resolve("images/asf_logo_wide.gif")).length);
assertEquals(IMG_SIZE, toByteArray(dataSourceResolver.resolve("./images/asf_logo_wide.gif")).length);
assertEquals(IMG_SIZE, toByteArray(dataSourceResolver.resolve("../resources/images/asf_logo_wide.gif")).length);
assertNull(toByteArray(dataSourceResolver.resolve("/images/does-not-exist.gif")));
assertNull(dataSourceResolver.resolve("./images/does-not-exist.gif"));
}

@Test
public void testResolveStrict() throws Exception {
final DataSourceResolver dataSourceResolver = new DataSourcePathResolver(Paths.get("."), false);
assertNotNull(dataSourceResolver.resolve("./src/test/resources/images/asf_logo_wide.gif"));

assertThrows(IOException.class, () -> dataSourceResolver.resolve("asf_logo_wide.gif"));
}

}

0 comments on commit 7cff388

Please sign in to comment.