View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
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, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package com.isenshi.util;
17  
18  import java.io.File;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.io.UnsupportedEncodingException;
24  import java.net.HttpURLConnection;
25  import java.net.URL;
26  import java.net.URLEncoder;
27  
28  import javax.servlet.http.HttpServletRequest;
29  import javax.servlet.http.HttpServletResponse;
30  
31  import org.apache.commons.io.IOUtils;
32  import org.apache.commons.logging.Log;
33  import org.apache.commons.logging.LogFactory;
34  
35  /***
36   * @author someda
37   */
38  public class HttpUtils {
39  
40  	// request header key
41  	private static final String REQUEST_HEADER_USERAGENT = "User-Agent";
42  
43  	private static final String REQUEST_HEADER_ACCEPTLANGUAGE = "accept-language";
44  
45  	private static final String REQUEST_HEADER_ACCEPTCHARSET = "accept-charset";
46  
47  	// response header key
48  	private static final String RESPONSE_HEADER_CONTENT_DISPOSITION_ATTACHPREFIX = "attachment;filename";
49  
50  	private static final String RESPONSE_HEADER_CONTENT_DISPOSITION = "Content-Disposition";
51  	
52  	private static final String RESPONSE_HEADER_PRAGMA = "Pragma";
53  	
54  	private static final String RESPONSE_HEADER_CACHE_CONTROL = "Cache-Control";
55  	
56  	private static final String RESPONSE_HEADER_VALUE_NOCACHE = "no-cache";
57  
58  	private static final String[] USERAGENT_IECOMPATIBLES = { "MSIE" };
59  
60  	private static Log log = LogFactory.getLog(HttpUtils.class);
61  	
62  	
63  	public static final void write(HttpServletRequest request,
64  			HttpServletResponse response, String contentType, byte[] bytes, String fileName){
65  		setResponseHeader(request, response, contentType, fileName);
66  		doWrite(response, bytes);
67  	}
68  	
69  	public static final void write(HttpServletRequest request,
70  			HttpServletResponse response, String contentType, byte[] bytes){
71  		write(request, response, contentType, bytes, null);
72  	}
73  	
74  	public static final void setResponseHeader(HttpServletRequest request,
75  			HttpServletResponse response, String contentType) {
76  		setResponseHeader(request, response, contentType, null);
77  	}
78  	
79  	public static final void setResponseHeader(HttpServletRequest request,
80  				HttpServletResponse response, String contentType, String fileName) {
81  			
82  		response.setContentType(contentType);
83  		
84  		if (fileName != null) {
85  			String extension = PathUtils.getExtension(fileName);
86  			fileName = PathUtils.getFileName(fileName);
87  			String value = getContentDispositionHeaderValue(request, fileName,
88  					extension);
89  			response.setHeader(RESPONSE_HEADER_CONTENT_DISPOSITION, value);
90  		}
91  	}
92  	
93  	public static final void setNocacheResponseHeader(HttpServletResponse response){
94  		response.setHeader(RESPONSE_HEADER_PRAGMA,RESPONSE_HEADER_VALUE_NOCACHE);
95  		response.setHeader(RESPONSE_HEADER_CACHE_CONTROL,RESPONSE_HEADER_VALUE_NOCACHE);		
96  	}
97  	
98  	/***
99  	 * The filename in specified in content-dispostion, is not allowed to use
100 	 * multibyte character, and should follows RFC2231 style. also IE has the
101 	 * following problem,
102 	 * http://support.microsoft.com/default.aspx?scid=kb;ja;436616
103 	 * 
104 	 * @see <a href="http://www.ietf.org/rfc/rfc2231.txt">RFC2231 MIME Parameter
105 	 *      Value and Encoded Word Extensions: Character Sets, Languages, and
106 	 *      Continuations</a>
107 	 */
108 	public static String getContentDispositionHeaderValue(
109 			HttpServletRequest request, String filename, String extension) {
110 
111 		StringBuffer buf = new StringBuffer();
112 		buf.append(RESPONSE_HEADER_CONTENT_DISPOSITION_ATTACHPREFIX);
113 
114 		if (isAsciiFilename(filename)) {
115 			buf.append("=");
116 			buf.append(filename);
117 		} else {
118 			if (isIECompatibleBrowser(request)) {
119 				buf.append("=");
120 				buf.append(encodeFileName(filename, "UTF-8"));
121 			} else {
122 				String enc = getEncoding(request);
123 				String lang = getAcceptLanguage(request);
124 				buf.append("*=");
125 				buf.append(enc);
126 				if (lang != null) {
127 					buf.append("'" + lang + "'");
128 				}
129 				buf.append(encodeFileName(filename, enc));
130 			}
131 		}
132 
133 		if (extension != null && extension.length() > 0) {
134 			extension = CharUtil.charpop(extension, '.');
135 			buf.append("." + extension);
136 		}
137 
138 		String headerValue = buf.toString();
139  		log.info("attachment header value : " + headerValue);
140 		return headerValue;
141 	}
142 
143 	public static String getLocalContextPath() {
144 		String ctxRoot = null;
145 		File webinf = ResourceUtils.getUpwardFileByName("WEB-INF");
146 		if (webinf != null) {
147 			ctxRoot = webinf.getParentFile().getPath();
148 		}
149 		return ctxRoot;
150 	}
151 
152 	public static File downloadFile(URL url) throws IOException {
153 
154 		String protocol = url.getProtocol();
155 		if (!"http".equals(protocol) && !"https".equals(protocol)) {
156 			return null;
157 		}
158 
159 		String outputPath = "tmp.gif";
160 		HttpURLConnection con = (HttpURLConnection) url.openConnection();
161 		con.setRequestMethod("GET");
162 		InputStream is = con.getInputStream();
163 
164 		FileOutputStream fos = new FileOutputStream(outputPath);
165 		byte[] buf = new byte[1024];
166 		while (true) {
167 			int length = is.read(buf);
168 
169 			if (length == -1)
170 				break;
171 			fos.write(buf, 0, length);
172 		}
173 		fos.flush();
174 		fos.close();
175 
176 		is.close();
177 		con.disconnect();
178 		return new File(outputPath);
179 	}
180 
181 	// ----- [Start] private methods -----
182 
183 	private static boolean isAsciiFilename(String filename) {
184 		boolean flag = true;
185 		char[] names = filename.toCharArray();
186 		for (int i = 0; i < names.length; i++) {
187 			if (names[i] > 0x7F) { // char is unsinged int
188 				flag = false;
189 				break;
190 			}
191 		}
192 		return flag;
193 	}
194 
195 	private static boolean isIECompatibleBrowser(HttpServletRequest request) {
196 		boolean flag = false;
197 		String userAgent = request.getHeader(REQUEST_HEADER_USERAGENT);
198 		if (userAgent != null) {
199 			for (int i = 0; i < USERAGENT_IECOMPATIBLES.length; i++) {
200 				if (userAgent.indexOf(USERAGENT_IECOMPATIBLES[i]) != -1) {
201 					flag = true;
202 					break;
203 				}
204 			}
205 		}
206 		return flag;
207 	}
208 
209 	private static String getEncoding(HttpServletRequest request) {
210 		String enc = request.getCharacterEncoding();
211 
212 		String acceptenc = request.getHeader(REQUEST_HEADER_ACCEPTCHARSET);
213 		if (acceptenc != null) {
214 			int idx = acceptenc.indexOf(",");
215 			enc = acceptenc.substring(0, idx);
216 		} else {
217 			log.warn("unknown type of charset "
218 					+ request.getHeader(REQUEST_HEADER_USERAGENT));
219 		}
220 		return enc;
221 	}
222 
223 	private static String getAcceptLanguage(HttpServletRequest request) {
224 		String lang = null;
225 
226 		String acceptlang = request.getHeader(REQUEST_HEADER_ACCEPTLANGUAGE);
227 		if (acceptlang != null) {
228 			int idx = acceptlang.indexOf(",");
229 			if (idx != -1) {
230 				lang = acceptlang.substring(0, idx);
231 			} else {
232 				lang = acceptlang;
233 			}
234 		}
235 		return lang;
236 	}
237 
238 	private static String encodeFileName(String fileName, String encode) {
239 		String encodeName = null;
240 		try {
241 			encodeName = URLEncoder.encode(fileName, encode);
242 		} catch (UnsupportedEncodingException uee) {
243 			log.error("encoding filename " + fileName + " with encode "
244 					+ encode);
245 		}
246 		return (encodeName == null) ? fileName : encodeName;
247 	}
248 
249 	
250 	private static void doWrite(HttpServletResponse response, byte[] b) {
251 		OutputStream os = null;		
252 		try {
253 			os = response.getOutputStream();
254 			os.write(b);
255 		} catch (IOException ioe) {
256 			log.error("getOutputStream failed");
257 		} finally {
258 			IOUtils.closeQuietly(os);
259 		}
260 	}
261 		
262 	// ----- [End] private methods -----
263 
264 }