001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.fs.http.client; 019 020import org.apache.hadoop.classification.InterfaceAudience; 021import org.apache.hadoop.fs.Path; 022import org.json.simple.parser.JSONParser; 023import org.json.simple.parser.ParseException; 024 025import java.io.IOException; 026import java.io.InputStreamReader; 027import java.net.HttpURLConnection; 028import java.net.URI; 029import java.net.URL; 030import java.net.URLEncoder; 031import java.text.MessageFormat; 032import java.util.List; 033import java.util.Map; 034 035/** 036 * Utility methods used by HttpFS classes. 037 */ 038@InterfaceAudience.Private 039public class HttpFSUtils { 040 041 public static final String SERVICE_NAME = "/webhdfs"; 042 043 public static final String SERVICE_VERSION = "/v1"; 044 045 private static final String SERVICE_PATH = SERVICE_NAME + SERVICE_VERSION; 046 047 /** 048 * Convenience method that creates an HTTP <code>URL</code> for the 049 * HttpFSServer file system operations. 050 * <p/> 051 * 052 * @param path the file path. 053 * @param params the query string parameters. 054 * 055 * @return a <code>URL</code> for the HttpFSServer server, 056 * 057 * @throws IOException thrown if an IO error occurs. 058 */ 059 static URL createURL(Path path, Map<String, String> params) 060 throws IOException { 061 return createURL(path, params, null); 062 } 063 064 /** 065 * Convenience method that creates an HTTP <code>URL</code> for the 066 * HttpFSServer file system operations. 067 * <p/> 068 * 069 * @param path the file path. 070 * @param params the query string parameters. 071 * @param multiValuedParams multi valued parameters of the query string 072 * 073 * @return URL a <code>URL</code> for the HttpFSServer server, 074 * 075 * @throws IOException thrown if an IO error occurs. 076 */ 077 static URL createURL(Path path, Map<String, String> params, Map<String, 078 List<String>> multiValuedParams) throws IOException { 079 URI uri = path.toUri(); 080 String realScheme; 081 if (uri.getScheme().equalsIgnoreCase(HttpFSFileSystem.SCHEME)) { 082 realScheme = "http"; 083 } else if (uri.getScheme().equalsIgnoreCase(HttpsFSFileSystem.SCHEME)) { 084 realScheme = "https"; 085 086 } else { 087 throw new IllegalArgumentException(MessageFormat.format( 088 "Invalid scheme [{0}] it should be '" + HttpFSFileSystem.SCHEME + "' " + 089 "or '" + HttpsFSFileSystem.SCHEME + "'", uri)); 090 } 091 StringBuilder sb = new StringBuilder(); 092 sb.append(realScheme).append("://").append(uri.getAuthority()). 093 append(SERVICE_PATH).append(uri.getPath()); 094 095 String separator = "?"; 096 for (Map.Entry<String, String> entry : params.entrySet()) { 097 sb.append(separator).append(entry.getKey()).append("="). 098 append(URLEncoder.encode(entry.getValue(), "UTF8")); 099 separator = "&"; 100 } 101 if (multiValuedParams != null) { 102 for (Map.Entry<String, List<String>> multiValuedEntry : 103 multiValuedParams.entrySet()) { 104 String name = URLEncoder.encode(multiValuedEntry.getKey(), "UTF8"); 105 List<String> values = multiValuedEntry.getValue(); 106 for (String value : values) { 107 sb.append(separator).append(name).append("="). 108 append(URLEncoder.encode(value, "UTF8")); 109 separator = "&"; 110 } 111 } 112 } 113 return new URL(sb.toString()); 114 } 115 116 /** 117 * Convenience method that JSON Parses the <code>InputStream</code> of a 118 * <code>HttpURLConnection</code>. 119 * 120 * @param conn the <code>HttpURLConnection</code>. 121 * 122 * @return the parsed JSON object. 123 * 124 * @throws IOException thrown if the <code>InputStream</code> could not be 125 * JSON parsed. 126 */ 127 static Object jsonParse(HttpURLConnection conn) throws IOException { 128 try { 129 JSONParser parser = new JSONParser(); 130 return parser.parse(new InputStreamReader(conn.getInputStream())); 131 } catch (ParseException ex) { 132 throw new IOException("JSON parser error, " + ex.getMessage(), ex); 133 } 134 } 135}