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 */ 018 019 package org.apache.hadoop.lib.wsrs; 020 021 import com.sun.jersey.api.core.HttpContext; 022 import com.sun.jersey.core.spi.component.ComponentContext; 023 import com.sun.jersey.core.spi.component.ComponentScope; 024 import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable; 025 import com.sun.jersey.spi.inject.Injectable; 026 import com.sun.jersey.spi.inject.InjectableProvider; 027 import org.apache.hadoop.classification.InterfaceAudience; 028 029 import javax.ws.rs.core.Context; 030 import javax.ws.rs.core.MultivaluedMap; 031 import java.lang.reflect.Type; 032 import java.text.MessageFormat; 033 import java.util.HashMap; 034 import java.util.Map; 035 036 /** 037 * Jersey provider that parses the request parameters based on the 038 * given parameter definition. 039 */ 040 @InterfaceAudience.Private 041 public class ParametersProvider 042 extends AbstractHttpContextInjectable<Parameters> 043 implements InjectableProvider<Context, Type> { 044 045 private String driverParam; 046 private Class<? extends Enum> enumClass; 047 private Map<Enum, Class<Param<?>>[]> paramsDef; 048 049 public ParametersProvider(String driverParam, Class<? extends Enum> enumClass, 050 Map<Enum, Class<Param<?>>[]> paramsDef) { 051 this.driverParam = driverParam; 052 this.enumClass = enumClass; 053 this.paramsDef = paramsDef; 054 } 055 056 @Override 057 @SuppressWarnings("unchecked") 058 public Parameters getValue(HttpContext httpContext) { 059 Map<String, Param<?>> map = new HashMap<String, Param<?>>(); 060 MultivaluedMap<String, String> queryString = 061 httpContext.getRequest().getQueryParameters(); 062 String str = queryString.getFirst(driverParam); 063 if (str == null) { 064 throw new IllegalArgumentException( 065 MessageFormat.format("Missing Operation parameter [{0}]", 066 driverParam)); 067 } 068 Enum op; 069 try { 070 op = Enum.valueOf(enumClass, str.toUpperCase()); 071 } catch (IllegalArgumentException ex) { 072 throw new IllegalArgumentException( 073 MessageFormat.format("Invalid Operation [{0}]", str)); 074 } 075 if (!paramsDef.containsKey(op)) { 076 throw new IllegalArgumentException( 077 MessageFormat.format("Unsupported Operation [{0}]", op)); 078 } 079 for (Class<Param<?>> paramClass : paramsDef.get(op)) { 080 Param<?> param; 081 try { 082 param = paramClass.newInstance(); 083 } catch (Exception ex) { 084 throw new UnsupportedOperationException( 085 MessageFormat.format( 086 "Param class [{0}] does not have default constructor", 087 paramClass.getName())); 088 } 089 try { 090 param.parseParam(queryString.getFirst(param.getName())); 091 } 092 catch (Exception ex) { 093 throw new IllegalArgumentException(ex.toString(), ex); 094 } 095 map.put(param.getName(), param); 096 } 097 return new Parameters(map); 098 } 099 100 @Override 101 public ComponentScope getScope() { 102 return ComponentScope.PerRequest; 103 } 104 105 @Override 106 public Injectable getInjectable(ComponentContext componentContext, Context context, Type type) { 107 return (type.equals(Parameters.class)) ? this : null; 108 } 109 }