View Javadoc

1   /*
2    * Copyright 2007-2009 Medsea Business Solutions S.L.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package eu.medsea.mimeutil.detector;
17  
18  import java.io.File;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.StringWriter;
22  import java.net.URL;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  
26  import eu.medsea.mimeutil.MimeException;
27  import eu.medsea.mimeutil.MimeType;
28  import eu.medsea.mimeutil.MimeUtil;
29  
30  /**
31   * Get the content type for a file extension as stored in the Windows Registry
32   * The extensions are stored at "HKEY_CLASSES_ROOT"
33   * <p>
34   * This MimeDetector will only operate on Windows machines. On any other platform
35   * the methods throw a UnsupportedOperationException (These are swallowed by the MimeUtil class)
36   * Therefore, it is perfectly acceptable to register this MimeDetector with MimeUtil and it
37   * will only be used on a Windows Platform. On all other platforms it will just be ignored.
38   * </p>
39   * <p>
40   * To register this MimeDetector use<br/>
41   * <code>MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.WindowsRegistryMimeDetector");</code>
42   * </p>
43   * <p>
44   * The Collection returned from the getMimeTypesXXX(...) Methods with contain either a single MimeType
45   * or the collection will be empty.
46   * </p>
47   * <p>
48   * This MimeDetector only performs file extension mapping, so the methods taking an InputStream and byte array
49   * throw UnsupportedOperationException
50   * </p>
51   *
52   * @author Steven McArdle
53   *
54   */
55  public class WindowsRegistryMimeDetector extends MimeDetector {
56  
57  	private static final String REG_QUERY = "reg query ";
58  	private static final String CONTENT_TYPE = "\"Content Type\"";
59  
60  	private static final boolean isWindows = System.getProperty("os.name").startsWith("Windows");
61  
62  	public String getDescription() {
63  		return "Get the MIME types of file extensions from the Windows Registry. Will be inafective on non-Windows machines.";
64  	}
65  
66  	public Collection getMimeTypesFile(File file)
67  			throws UnsupportedOperationException {
68  		try {
69  			return getMimeTypesURL(file.toURI().toURL());
70  		}catch(Exception e) {
71  			throw new MimeException(e);
72  		}
73  	}
74  
75  	public Collection getMimeTypesFileName(String fileName)
76  			throws UnsupportedOperationException {
77  		return getMimeTypesFile(new File(fileName));
78  	}
79  
80  	public Collection getMimeTypesURL(URL url)
81  			throws UnsupportedOperationException {
82  		Collection mimeTypes = new ArrayList();
83  		if(!isWindows) {
84  			return mimeTypes;
85  		}
86  
87  		String contentType = getContentType(MimeUtil.getExtension(url.getPath()));
88  		if(contentType != null && contentType.length() > 0) {
89  			mimeTypes.add(new MimeType(contentType));
90  		}
91  		return mimeTypes;
92  	}
93  
94  	/**
95  	 * Content detection not supported
96  	 */
97  	public Collection getMimeTypesByteArray(byte[] data)
98  			throws UnsupportedOperationException {
99  		throw new UnsupportedOperationException(
100 				"WindowsRegistryMimeDetector does not support detection from byte arrays.");
101 	}
102 
103 	/**
104 	 * Content detection not supported
105 	 */
106 	public Collection getMimeTypesInputStream(InputStream in)
107 			throws UnsupportedOperationException {
108 		throw new UnsupportedOperationException(
109 				"WindowsRegistryMimeDetector does not support detection from InputStreams.");
110 	}
111 
112 	private String getContentType(String extension) {
113 		if (extension == null || extension.length() < 1) {
114 			return null;
115 		}
116 		try {
117 			String query = REG_QUERY + "\"HKEY_CLASSES_ROOT\\." + extension + "\" /v " + CONTENT_TYPE;
118 
119 			Process process = Runtime.getRuntime().exec(query);
120 			StreamReader reader = new StreamReader(process.getInputStream());
121 
122 			reader.start();
123 			process.waitFor();
124 			reader.join();
125 
126 			String result = reader.getResult();
127 			int p = result.indexOf("REG_SZ");
128 
129 			if (p == -1)
130 				return null;
131 
132 			return result.substring(p + "REG_SZ".length()).trim();
133 		} catch (Exception e) {
134 			return null;
135 		}
136 	}
137 
138 	static class StreamReader extends Thread {
139 		private InputStream is;
140 		private StringWriter sw;
141 
142 		StreamReader(InputStream is) {
143 			this.is = is;
144 			sw = new StringWriter();
145 		}
146 
147 		public void run() {
148 			try {
149 				int c;
150 				while ((c = is.read()) != -1)
151 					sw.write(c);
152 			} catch (IOException e) {
153 				;
154 			}
155 		}
156 
157 		String getResult() {
158 			return sw.toString();
159 		}
160 	}
161 }