001: /*
002: * Copyright 2002-2005 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.mail.javamail;
018:
019: import java.io.File;
020: import java.io.IOException;
021:
022: import javax.activation.FileTypeMap;
023: import javax.activation.MimetypesFileTypeMap;
024:
025: import org.springframework.beans.factory.InitializingBean;
026: import org.springframework.core.io.ClassPathResource;
027: import org.springframework.core.io.Resource;
028:
029: /**
030: * Spring-configurable <code>FileTypeMap</code> implementation that will read
031: * MIME type to file extension mappings from a standard JavaMail MIME type
032: * mapping file, using a standard <code>MimetypesFileTypeMap</code> underneath.
033: *
034: * <p>The mapping file should be in the following format, as specified by the
035: * Java Activation Framework:
036: *
037: * <pre>
038: * # map text/html to .htm and .html files
039: * text/html html htm HTML HTM</pre>
040: *
041: * Lines starting with <code>#</code> are treated as comments and are ignored. All
042: * other lines are treated as mappings. Each mapping line should contain the MIME
043: * type as the first entry and then each file extension to map to that MIME type
044: * as subsequent entries. Each entry is separated by spaces or tabs.
045: *
046: * <p>By default, the mappings in the <code>mime.types</code> file located in the
047: * same package as this class are used, which cover many common file extensions
048: * (in contrast to the out-of-the-box mappings in <code>activation.jar</code>).
049: * This can be overridden using the <code>mappingLocation</code> property.
050: *
051: * <p>Additional mappings can be added via the <code>mappings</code> bean property,
052: * as lines that follow the <code>mime.types<code> file format.
053: *
054: * @author Rob Harrop
055: * @author Juergen Hoeller
056: * @since 1.2
057: * @see #setMappingLocation
058: * @see #setMappings
059: * @see javax.activation.MimetypesFileTypeMap
060: */
061: public class ConfigurableMimeFileTypeMap extends FileTypeMap implements
062: InitializingBean {
063:
064: /**
065: * The <code>Resource</code> to load the mapping file from.
066: */
067: private Resource mappingLocation = new ClassPathResource(
068: "mime.types", getClass());
069:
070: /**
071: * Used to configure additional mappings.
072: */
073: private String[] mappings;
074:
075: /**
076: * The delegate FileTypeMap, compiled from the mappings in the mapping file
077: * and the entries in the <code>mappings</code> property.
078: */
079: private FileTypeMap fileTypeMap;
080:
081: /**
082: * Specify the <code>Resource</code> from which mappings are loaded.
083: * Needs to follow the <code>mime.types<code> file format, as specified
084: * by the Java Activation Framework, containing lines such as:<br>
085: * <code>text/html html htm HTML HTM</code>
086: */
087: public void setMappingLocation(Resource mappingLocation) {
088: this .mappingLocation = mappingLocation;
089: }
090:
091: /**
092: * Specify additional MIME type mappings as lines that follow the
093: * <code>mime.types<code> file format, as specified by the
094: * Java Activation Framework, for example:<br>
095: * <code>text/html html htm HTML HTM</code>
096: */
097: public void setMappings(String[] mappings) {
098: this .mappings = mappings;
099: }
100:
101: /**
102: * Creates the final merged mapping set.
103: */
104: public void afterPropertiesSet() {
105: getFileTypeMap();
106: }
107:
108: /**
109: * Return the delegate FileTypeMap, compiled from the mappings in the mapping file
110: * and the entries in the <code>mappings</code> property.
111: * @see #setMappingLocation
112: * @see #setMappings
113: * @see #createFileTypeMap
114: */
115: protected final FileTypeMap getFileTypeMap() {
116: if (this .fileTypeMap == null) {
117: try {
118: this .fileTypeMap = createFileTypeMap(
119: this .mappingLocation, this .mappings);
120: } catch (IOException ex) {
121: throw new IllegalStateException(
122: "Could not load specified MIME type mapping file: "
123: + this .mappingLocation);
124: }
125: }
126: return fileTypeMap;
127: }
128:
129: /**
130: * Compile a FileTypeMap from the mappings in the given mapping file and the
131: * given mapping entries.
132: * <p>Default implementation creates an Activation Framework MimetypesFileTypeMap,
133: * passing in an InputStream from the mapping resource (if any) and registering
134: * the mapping lines programmatically.
135: * @param mappingLocation a <code>mime.types</code> mapping resource (can be <code>null</code>)
136: * @param mappings MIME type mapping lines (can be <code>null</code>)
137: * @return the compiled FileTypeMap
138: * @throws IOException if resource access failed
139: * @see javax.activation.MimetypesFileTypeMap#MimetypesFileTypeMap(java.io.InputStream)
140: * @see javax.activation.MimetypesFileTypeMap#addMimeTypes(String)
141: */
142: protected FileTypeMap createFileTypeMap(Resource mappingLocation,
143: String[] mappings) throws IOException {
144: MimetypesFileTypeMap fileTypeMap = (mappingLocation != null) ? new MimetypesFileTypeMap(
145: mappingLocation.getInputStream())
146: : new MimetypesFileTypeMap();
147: if (mappings != null) {
148: for (int i = 0; i < mappings.length; i++) {
149: fileTypeMap.addMimeTypes(mappings[i]);
150: }
151: }
152: return fileTypeMap;
153: }
154:
155: /**
156: * Delegates to the underlying FileTypeMap.
157: * @see #getFileTypeMap()
158: */
159: public String getContentType(File file) {
160: return getFileTypeMap().getContentType(file);
161: }
162:
163: /**
164: * Delegates to the underlying FileTypeMap.
165: * @see #getFileTypeMap()
166: */
167: public String getContentType(String fileName) {
168: return getFileTypeMap().getContentType(fileName);
169: }
170:
171: }
|