You are viewing a plain text version of this content. The canonical link for it is here.
Posted to yarn-commits@hadoop.apache.org by zj...@apache.org on 2014/08/13 22:29:24 UTC
svn commit: r1617832 - in /hadoop/common/trunk/hadoop-yarn-project: ./
hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/
hadoop-yarn/hadoop-yarn-server/hadoop-yarn-s...
Author: zjshen
Date: Wed Aug 13 20:29:23 2014
New Revision: 1617832
URL: http://svn.apache.org/r1617832
Log:
YARN-2277. Added cross-origin support for the timeline server web services. Contributed by Jonathan Eagles.
Added:
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilter.java
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilterInitializer.java
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilter.java
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilterInitializer.java
Modified:
hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt
Modified: hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt?rev=1617832&r1=1617831&r2=1617832&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-yarn-project/CHANGES.txt Wed Aug 13 20:29:23 2014
@@ -41,6 +41,9 @@ Release 2.6.0 - UNRELEASED
YARN-1337. Recover containers upon nodemanager restart. (Jason Lowe via
junping_du)
+ YARN-2277. Added cross-origin support for the timeline server web services.
+ (Jonathan Eagles via zjshen)
+
IMPROVEMENTS
YARN-2242. Improve exception information on AM launch crashes. (Li Lu
Added: hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilter.java?rev=1617832&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilter.java (added)
+++ hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilter.java Wed Aug 13 20:29:23 2014
@@ -0,0 +1,220 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.timeline.webapp;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class CrossOriginFilter implements Filter {
+
+ private static final Log LOG = LogFactory.getLog(CrossOriginFilter.class);
+
+ // HTTP CORS Request Headers
+ static final String ORIGIN = "Origin";
+ static final String ACCESS_CONTROL_REQUEST_METHOD =
+ "Access-Control-Request-Method";
+ static final String ACCESS_CONTROL_REQUEST_HEADERS =
+ "Access-Control-Request-Headers";
+
+ // HTTP CORS Response Headers
+ static final String ACCESS_CONTROL_ALLOW_ORIGIN =
+ "Access-Control-Allow-Origin";
+ static final String ACCESS_CONTROL_ALLOW_CREDENTIALS =
+ "Access-Control-Allow-Credentials";
+ static final String ACCESS_CONTROL_ALLOW_METHODS =
+ "Access-Control-Allow-Methods";
+ static final String ACCESS_CONTROL_ALLOW_HEADERS =
+ "Access-Control-Allow-Headers";
+ static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age";
+
+ // Filter configuration
+ public static final String ALLOWED_ORIGINS = "allowed-origins";
+ public static final String ALLOWED_ORIGINS_DEFAULT = "*";
+ public static final String ALLOWED_METHODS = "allowed-methods";
+ public static final String ALLOWED_METHODS_DEFAULT = "GET,POST,HEAD";
+ public static final String ALLOWED_HEADERS = "allowed-headers";
+ public static final String ALLOWED_HEADERS_DEFAULT =
+ "X-Requested-With,Content-Type,Accept,Origin";
+ public static final String MAX_AGE = "max-age";
+ public static final String MAX_AGE_DEFAULT = "1800";
+
+ private List<String> allowedMethods = new ArrayList<String>();
+ private List<String> allowedHeaders = new ArrayList<String>();
+ private List<String> allowedOrigins = new ArrayList<String>();
+ private String maxAge;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ initializeAllowedMethods(filterConfig);
+ initializeAllowedHeaders(filterConfig);
+ initializeAllowedOrigins(filterConfig);
+ initializeMaxAge(filterConfig);
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res,
+ FilterChain chain)
+ throws IOException, ServletException {
+ doCrossFilter((HttpServletRequest) req, (HttpServletResponse) res);
+ chain.doFilter(req, res);
+ }
+
+ @Override
+ public void destroy() {
+ allowedMethods.clear();
+ allowedHeaders.clear();
+ allowedOrigins.clear();
+ }
+
+ private void doCrossFilter(HttpServletRequest req, HttpServletResponse res) {
+
+ String origin = encodeHeader(req.getHeader(ORIGIN));
+ if (!isCrossOrigin(origin)) {
+ return;
+ }
+
+ if (!isOriginAllowed(origin)) {
+ return;
+ }
+
+ String accessControlRequestMethod =
+ req.getHeader(ACCESS_CONTROL_REQUEST_METHOD);
+ if (!isMethodAllowed(accessControlRequestMethod)) {
+ return;
+ }
+
+ String accessControlRequestHeaders =
+ req.getHeader(ACCESS_CONTROL_REQUEST_HEADERS);
+ if (!areHeadersAllowed(accessControlRequestHeaders)) {
+ return;
+ }
+
+ res.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
+ res.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, Boolean.TRUE.toString());
+ res.setHeader(ACCESS_CONTROL_ALLOW_METHODS, getAllowedMethodsHeader());
+ res.setHeader(ACCESS_CONTROL_ALLOW_HEADERS, getAllowedHeadersHeader());
+ res.setHeader(ACCESS_CONTROL_MAX_AGE, maxAge);
+ }
+
+ @VisibleForTesting
+ String getAllowedHeadersHeader() {
+ return StringUtils.join(allowedHeaders, ',');
+ }
+
+ @VisibleForTesting
+ String getAllowedMethodsHeader() {
+ return StringUtils.join(allowedMethods, ',');
+ }
+
+ private void initializeAllowedMethods(FilterConfig filterConfig) {
+ String allowedMethodsConfig =
+ filterConfig.getInitParameter(ALLOWED_METHODS);
+ if (allowedMethodsConfig == null) {
+ allowedMethodsConfig = ALLOWED_METHODS_DEFAULT;
+ }
+ allowedMethods =
+ Arrays.asList(allowedMethodsConfig.trim().split("\\s*,\\s*"));
+ LOG.info("Allowed Methods: " + getAllowedMethodsHeader());
+ }
+
+ private void initializeAllowedHeaders(FilterConfig filterConfig) {
+ String allowedHeadersConfig =
+ filterConfig.getInitParameter(ALLOWED_HEADERS);
+ if (allowedHeadersConfig == null) {
+ allowedHeadersConfig = ALLOWED_HEADERS_DEFAULT;
+ }
+ allowedHeaders =
+ Arrays.asList(allowedHeadersConfig.trim().split("\\s*,\\s*"));
+ LOG.info("Allowed Headers: " + getAllowedHeadersHeader());
+ }
+
+ private void initializeAllowedOrigins(FilterConfig filterConfig) {
+ String allowedOriginsConfig =
+ filterConfig.getInitParameter(ALLOWED_ORIGINS);
+ if (allowedOriginsConfig == null) {
+ allowedOriginsConfig = ALLOWED_ORIGINS_DEFAULT;
+ }
+ allowedOrigins =
+ Arrays.asList(allowedOriginsConfig.trim().split("\\s*,\\s*"));
+ LOG.info("Allowed Origins: " + StringUtils.join(allowedOrigins, ','));
+ }
+
+ private void initializeMaxAge(FilterConfig filterConfig) {
+ maxAge = filterConfig.getInitParameter(MAX_AGE);
+ if (maxAge == null) {
+ maxAge = MAX_AGE_DEFAULT;
+ }
+ LOG.info("Max Age: " + maxAge);
+ }
+
+ static String encodeHeader(final String header) {
+ if (header == null) {
+ return null;
+ }
+ try {
+ // Protect against HTTP response splitting vulnerability
+ // since value is written as part of the response header
+ return URLEncoder.encode(header, "ASCII");
+ } catch (UnsupportedEncodingException e) {
+ return null;
+ }
+ }
+
+ static boolean isCrossOrigin(String origin) {
+ return origin != null;
+ }
+
+ private boolean isOriginAllowed(String origin) {
+ return allowedOrigins.contains(origin);
+ }
+
+ private boolean areHeadersAllowed(String accessControlRequestHeaders) {
+ if (accessControlRequestHeaders == null) {
+ return true;
+ }
+ String headers[] = accessControlRequestHeaders.trim().split("\\s*,\\s*");
+ return allowedHeaders.containsAll(Arrays.asList(headers));
+ }
+
+ private boolean isMethodAllowed(String accessControlRequestMethod) {
+ if (accessControlRequestMethod == null) {
+ return false;
+ }
+ return allowedMethods.contains(accessControlRequestMethod);
+ }
+}
Added: hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilterInitializer.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilterInitializer.java?rev=1617832&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilterInitializer.java (added)
+++ hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/main/java/org/apache/hadoop/yarn/server/timeline/webapp/CrossOriginFilterInitializer.java Wed Aug 13 20:29:23 2014
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.timeline.webapp;
+
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.http.FilterContainer;
+import org.apache.hadoop.http.FilterInitializer;
+
+public class CrossOriginFilterInitializer extends FilterInitializer {
+
+ public static final String PREFIX =
+ "yarn.timeline-service.http-cross-origin.";
+
+ @Override
+ public void initFilter(FilterContainer container, Configuration conf) {
+
+ container.addGlobalFilter("Cross Origin Filter",
+ CrossOriginFilter.class.getName(), getFilterParameters(conf));
+ }
+
+ static Map<String, String> getFilterParameters(Configuration conf) {
+ return conf.getValByRegex(PREFIX);
+ }
+}
Added: hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilter.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilter.java?rev=1617832&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilter.java (added)
+++ hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilter.java Wed Aug 13 20:29:23 2014
@@ -0,0 +1,214 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.timeline.webapp;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class TestCrossOriginFilter {
+
+ @Test
+ public void testSameOrigin() throws ServletException, IOException {
+
+ // Setup the configuration settings of the server
+ Map<String, String> conf = new HashMap<String, String>();
+ conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "");
+ FilterConfig filterConfig = new FilterConfigTest(conf);
+
+ // Origin is not specified for same origin requests
+ HttpServletRequest mockReq = mock(HttpServletRequest.class);
+ when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn(null);
+
+ // Objects to verify interactions based on request
+ HttpServletResponse mockRes = mock(HttpServletResponse.class);
+ FilterChain mockChain = mock(FilterChain.class);
+
+ // Object under test
+ CrossOriginFilter filter = new CrossOriginFilter();
+ filter.init(filterConfig);
+ filter.doFilter(mockReq, mockRes, mockChain);
+
+ verifyZeroInteractions(mockRes);
+ verify(mockChain).doFilter(mockReq, mockRes);
+ }
+
+ @Test
+ public void testDisallowedOrigin() throws ServletException, IOException {
+
+ // Setup the configuration settings of the server
+ Map<String, String> conf = new HashMap<String, String>();
+ conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "example.com");
+ FilterConfig filterConfig = new FilterConfigTest(conf);
+
+ // Origin is not specified for same origin requests
+ HttpServletRequest mockReq = mock(HttpServletRequest.class);
+ when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.org");
+
+ // Objects to verify interactions based on request
+ HttpServletResponse mockRes = mock(HttpServletResponse.class);
+ FilterChain mockChain = mock(FilterChain.class);
+
+ // Object under test
+ CrossOriginFilter filter = new CrossOriginFilter();
+ filter.init(filterConfig);
+ filter.doFilter(mockReq, mockRes, mockChain);
+
+ verifyZeroInteractions(mockRes);
+ verify(mockChain).doFilter(mockReq, mockRes);
+ }
+
+ @Test
+ public void testDisallowedMethod() throws ServletException, IOException {
+
+ // Setup the configuration settings of the server
+ Map<String, String> conf = new HashMap<String, String>();
+ conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "example.com");
+ FilterConfig filterConfig = new FilterConfigTest(conf);
+
+ // Origin is not specified for same origin requests
+ HttpServletRequest mockReq = mock(HttpServletRequest.class);
+ when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
+ when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
+ .thenReturn("DISALLOWED_METHOD");
+
+ // Objects to verify interactions based on request
+ HttpServletResponse mockRes = mock(HttpServletResponse.class);
+ FilterChain mockChain = mock(FilterChain.class);
+
+ // Object under test
+ CrossOriginFilter filter = new CrossOriginFilter();
+ filter.init(filterConfig);
+ filter.doFilter(mockReq, mockRes, mockChain);
+
+ verifyZeroInteractions(mockRes);
+ verify(mockChain).doFilter(mockReq, mockRes);
+ }
+
+ @Test
+ public void testDisallowedHeader() throws ServletException, IOException {
+
+ // Setup the configuration settings of the server
+ Map<String, String> conf = new HashMap<String, String>();
+ conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "example.com");
+ FilterConfig filterConfig = new FilterConfigTest(conf);
+
+ // Origin is not specified for same origin requests
+ HttpServletRequest mockReq = mock(HttpServletRequest.class);
+ when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
+ when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
+ .thenReturn("GET");
+ when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
+ .thenReturn("Disallowed-Header");
+
+ // Objects to verify interactions based on request
+ HttpServletResponse mockRes = mock(HttpServletResponse.class);
+ FilterChain mockChain = mock(FilterChain.class);
+
+ // Object under test
+ CrossOriginFilter filter = new CrossOriginFilter();
+ filter.init(filterConfig);
+ filter.doFilter(mockReq, mockRes, mockChain);
+
+ verifyZeroInteractions(mockRes);
+ verify(mockChain).doFilter(mockReq, mockRes);
+ }
+
+ @Test
+ public void testCrossOriginFilter() throws ServletException, IOException {
+
+ // Setup the configuration settings of the server
+ Map<String, String> conf = new HashMap<String, String>();
+ conf.put(CrossOriginFilter.ALLOWED_ORIGINS, "example.com");
+ FilterConfig filterConfig = new FilterConfigTest(conf);
+
+ // Origin is not specified for same origin requests
+ HttpServletRequest mockReq = mock(HttpServletRequest.class);
+ when(mockReq.getHeader(CrossOriginFilter.ORIGIN)).thenReturn("example.com");
+ when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD))
+ .thenReturn("GET");
+ when(mockReq.getHeader(CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS))
+ .thenReturn("X-Requested-With");
+
+ // Objects to verify interactions based on request
+ HttpServletResponse mockRes = mock(HttpServletResponse.class);
+ FilterChain mockChain = mock(FilterChain.class);
+
+ // Object under test
+ CrossOriginFilter filter = new CrossOriginFilter();
+ filter.init(filterConfig);
+ filter.doFilter(mockReq, mockRes, mockChain);
+
+ verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN,
+ "example.com");
+ verify(mockRes).setHeader(
+ CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS,
+ Boolean.TRUE.toString());
+ verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_METHODS,
+ filter.getAllowedMethodsHeader());
+ verify(mockRes).setHeader(CrossOriginFilter.ACCESS_CONTROL_ALLOW_HEADERS,
+ filter.getAllowedHeadersHeader());
+ verify(mockChain).doFilter(mockReq, mockRes);
+ }
+
+ private static class FilterConfigTest implements FilterConfig {
+
+ final Map<String, String> map;
+
+ FilterConfigTest(Map<String, String> map) {
+ this.map = map;
+ }
+
+ @Override
+ public String getFilterName() {
+ return "test-filter";
+ }
+
+ @Override
+ public String getInitParameter(String key) {
+ return map.get(key);
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return Collections.enumeration(map.keySet());
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return null;
+ }
+ }
+}
Added: hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilterInitializer.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilterInitializer.java?rev=1617832&view=auto
==============================================================================
--- hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilterInitializer.java (added)
+++ hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/webapp/TestCrossOriginFilterInitializer.java Wed Aug 13 20:29:23 2014
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.yarn.server.timeline.webapp;
+
+import java.util.Map;
+
+import org.apache.hadoop.conf.Configuration;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCrossOriginFilterInitializer {
+
+ @Test
+ public void testGetFilterParameters() {
+
+ // Initialize configuration object
+ Configuration conf = new Configuration();
+ conf.set(CrossOriginFilterInitializer.PREFIX + "rootparam", "rootvalue");
+ conf.set(CrossOriginFilterInitializer.PREFIX + "nested.param",
+ "nestedvalue");
+ conf.set("outofscopeparam", "outofscopevalue");
+
+ // call function under test
+ Map<String, String> filterParameters =
+ CrossOriginFilterInitializer.getFilterParameters(conf);
+
+ // retrieve values
+ String rootvalue =
+ filterParameters.get(CrossOriginFilterInitializer.PREFIX + "rootparam");
+ String nestedvalue =
+ filterParameters.get(CrossOriginFilterInitializer.PREFIX
+ + "nested.param");
+ String outofscopeparam = filterParameters.get("outofscopeparam");
+
+ // verify expected values are in place
+ Assert.assertEquals("Could not find filter parameter", "rootvalue",
+ rootvalue);
+ Assert.assertEquals("Could not find filter parameter", "nestedvalue",
+ nestedvalue);
+ Assert.assertNull("Found unexpected value in filter parameters",
+ outofscopeparam);
+ }
+}