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 public static final byte[] EMPTY_BYTES = {}; 046 047 private static final String SERVICE_PATH = SERVICE_NAME + SERVICE_VERSION; 048 049 /** 050 * Convenience method that creates an HTTP <code>URL</code> for the 051 * HttpFSServer file system operations. 052 * <p/> 053 * 054 * @param path the file path. 055 * @param params the query string parameters. 056 * 057 * @return a <code>URL</code> for the HttpFSServer server, 058 * 059 * @throws IOException thrown if an IO error occurs. 060 */ 061 static URL createURL(Path path, Map<String, String> params) 062 throws IOException { 063 return createURL(path, params, null); 064 } 065 066 /** 067 * Convenience method that creates an HTTP <code>URL</code> for the 068 * HttpFSServer file system operations. 069 * <p/> 070 * 071 * @param path the file path. 072 * @param params the query string parameters. 073 * @param multiValuedParams multi valued parameters of the query string 074 * 075 * @return URL a <code>URL</code> for the HttpFSServer server, 076 * 077 * @throws IOException thrown if an IO error occurs. 078 */ 079 static URL createURL(Path path, Map<String, String> params, Map<String, 080 List<String>> multiValuedParams) throws IOException { 081 URI uri = path.toUri(); 082 String realScheme; 083 if (uri.getScheme().equalsIgnoreCase(HttpFSFileSystem.SCHEME)) { 084 realScheme = "http"; 085 } else if (uri.getScheme().equalsIgnoreCase(HttpsFSFileSystem.SCHEME)) { 086 realScheme = "https"; 087 088 } else { 089 throw new IllegalArgumentException(MessageFormat.format( 090 "Invalid scheme [{0}] it should be '" + HttpFSFileSystem.SCHEME + "' " + 091 "or '" + HttpsFSFileSystem.SCHEME + "'", uri)); 092 } 093 StringBuilder sb = new StringBuilder(); 094 sb.append(realScheme).append("://").append(uri.getAuthority()). 095 append(SERVICE_PATH).append(uri.getPath()); 096 097 String separator = "?"; 098 for (Map.Entry<String, String> entry : params.entrySet()) { 099 sb.append(separator).append(entry.getKey()).append("="). 100 append(URLEncoder.encode(entry.getValue(), "UTF8")); 101 separator = "&"; 102 } 103 if (multiValuedParams != null) { 104 for (Map.Entry<String, List<String>> multiValuedEntry : 105 multiValuedParams.entrySet()) { 106 String name = URLEncoder.encode(multiValuedEntry.getKey(), "UTF8"); 107 List<String> values = multiValuedEntry.getValue(); 108 for (String value : values) { 109 sb.append(separator).append(name).append("="). 110 append(URLEncoder.encode(value, "UTF8")); 111 separator = "&"; 112 } 113 } 114 } 115 return new URL(sb.toString()); 116 } 117 118 /** 119 * Convenience method that JSON Parses the <code>InputStream</code> of a 120 * <code>HttpURLConnection</code>. 121 * 122 * @param conn the <code>HttpURLConnection</code>. 123 * 124 * @return the parsed JSON object. 125 * 126 * @throws IOException thrown if the <code>InputStream</code> could not be 127 * JSON parsed. 128 */ 129 static Object jsonParse(HttpURLConnection conn) throws IOException { 130 try { 131 JSONParser parser = new JSONParser(); 132 return parser.parse(new InputStreamReader(conn.getInputStream())); 133 } catch (ParseException ex) { 134 throw new IOException("JSON parser error, " + ex.getMessage(), ex); 135 } 136 } 137}