Repository: ambari Updated Branches: refs/heads/trunk 51620c6e2 -> 16bcc80e0
http://git-wip-us.apache.org/repos/asf/ambari/blob/16bcc80e/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobLDAPServiceTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobLDAPServiceTest.java b/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobLDAPServiceTest.java new file mode 100644 index 0000000..7be8bc9 --- /dev/null +++ b/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobLDAPServiceTest.java @@ -0,0 +1,158 @@ +/** + * 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.ambari.view.hive.resources.jobs; + +import org.apache.ambari.view.hive.BaseHiveTest; +import org.apache.ambari.view.hive.ServiceTestUtils; +import org.apache.ambari.view.hive.client.Connection; +import org.apache.ambari.view.hive.client.HiveAuthRequiredException; +import org.apache.ambari.view.hive.resources.jobs.viewJobs.JobImpl; +import org.apache.ambari.view.hive.utils.HdfsApiMock; +import org.apache.ambari.view.utils.UserLocal; +import org.apache.ambari.view.utils.hdfs.HdfsApi; +import org.apache.ambari.view.utils.hdfs.HdfsApiException; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.json.simple.JSONObject; +import org.junit.*; +import org.junit.rules.ExpectedException; + +import javax.ws.rs.WebApplicationException; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.*; + +public class JobLDAPServiceTest extends BaseHiveTest { + private JobService jobService; + @Rule public ExpectedException thrown = ExpectedException.none(); + + @BeforeClass + public static void startUp() throws Exception { + BaseHiveTest.startUp(); // super + } + + @AfterClass + public static void shutDown() throws Exception { + BaseHiveTest.shutDown(); // super + } + + @Override + @After + public void tearDown() throws Exception { + jobService.getSharedObjectsFactory().clear(HdfsApi.class); + } + + @Override + protected void setupProperties(Map<String, String> properties, File baseDir) throws Exception { + super.setupProperties(properties, baseDir); + properties.put("hive.host", "nonexistent.host.com"); + properties.put("hive.port", "10000"); + + properties.put("scripts.dir", "/tmp/.hiveQueries"); + properties.put("jobs.dir", "/tmp/.hiveJobs"); + } + + private HdfsApiMock setupHdfsApiMock() throws IOException, InterruptedException, HdfsApiException { + HdfsApiMock hdfsApiMock = new HdfsApiMock("select * from Z"); + HdfsApi hdfsApi = hdfsApiMock.getHdfsApi(); + jobService.getSharedObjectsFactory().setInstance(HdfsApi.class, hdfsApi); + replay(hdfsApi); + return hdfsApiMock; + } + + @Test + public void createJobNoPasswordProvided() throws Exception { + UserLocal.dropAllConnections(Connection.class); + Map<String, String> properties = new HashMap<String, String>(); + properties.put("hive.auth", "auth=NONE;password=${ask_password}"); + context = makeContext(properties, "ambari-qa-1", "MyHive"); + replay(context); + jobService = getService(JobService.class, handler, context); + setupHdfsApiMock(); + + JobService.JobRequest request = new JobService.JobRequest(); + request.job = new JobImpl(); + request.job.setForcedContent("Hello world"); + + thrown.expect(HiveAuthRequiredException.class); + jobService.create(request, + ServiceTestUtils.getResponseWithLocation(), ServiceTestUtils.getDefaultUriInfo()); + } + + @Test + public void createJobNoPasswordRequired() throws Exception { + Map<String, String> properties = new HashMap<String, String>(); + properties.put("hive.auth", "auth=NONE"); + context = makeContext(properties, "ambari-qa-2", "MyHive"); + replay(context); + jobService = getService(JobService.class, handler, context); + setupHdfsApiMock(); + + JobService.JobRequest request = new JobService.JobRequest(); + request.job = new JobImpl(); + request.job.setForcedContent("Hello world"); + + thrown.expect(new ExpectedJSONErrorMessage("Connection refused")); + jobService.create(request, + ServiceTestUtils.getResponseWithLocation(), ServiceTestUtils.getDefaultUriInfo()); + } + + @Test + public void createJobPasswordProvided() throws Exception { + Map<String, String> properties = new HashMap<String, String>(); + properties.put("hive.auth", "auth=NONE;password=${ask_password}"); + context = makeContext(properties, "ambari-qa-3", "MyHive"); + replay(context); + jobService = getService(JobService.class, handler, context); + setupHdfsApiMock(); + + JobService.JobRequest request = new JobService.JobRequest(); + request.job = new JobImpl(); + request.job.setForcedContent("Hello world"); + + JobService.AuthRequest authRequest = new JobService.AuthRequest(); + authRequest.password = "ok"; + + thrown.expect(new ExpectedJSONErrorMessage("Connection refused")); + jobService.setupPassword(authRequest); + } + + private static class ExpectedJSONErrorMessage extends BaseMatcher<WebApplicationException> { + private String expectedMessage; + + public ExpectedJSONErrorMessage(String message) { + this.expectedMessage = message; + } + + @Override + public void describeTo(Description description) { + description.appendText(this.expectedMessage); + } + + @Override + public boolean matches(Object o) { + JSONObject response = (JSONObject) ((WebApplicationException) o).getResponse().getEntity(); + String message = (String) response.get("message"); + return message.contains(expectedMessage); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16bcc80e/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobServiceTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobServiceTest.java b/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobServiceTest.java index 897d951..55c62e7 100644 --- a/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobServiceTest.java +++ b/contrib/views/hive/src/test/java/org/apache/ambari/view/hive/resources/jobs/JobServiceTest.java @@ -20,6 +20,7 @@ package org.apache.ambari.view.hive.resources.jobs; import org.apache.ambari.view.hive.ServiceTestUtils; import org.apache.ambari.view.hive.BaseHiveTest; +import org.apache.ambari.view.hive.client.UserLocalConnection; import org.apache.ambari.view.hive.resources.jobs.viewJobs.JobImpl; import org.apache.ambari.view.hive.utils.HdfsApiMock; import org.apache.ambari.view.hive.client.Connection; @@ -71,7 +72,7 @@ public class JobServiceTest extends BaseHiveTest { Connection hiveConnection = configureHiveConnectionMock(); - jobService.getSharedObjectsFactory().setInstance(Connection.class, hiveConnection); + new UserLocalConnection().set(hiveConnection, context); jobService.setAggregator( new Aggregator( jobService.getResourceManager(), http://git-wip-us.apache.org/repos/asf/ambari/blob/16bcc80e/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocal.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocal.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocal.java new file mode 100644 index 0000000..4d36de0 --- /dev/null +++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocal.java @@ -0,0 +1,129 @@ +/** + * 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.ambari.view.utils; + +import org.apache.ambari.view.ViewContext; + +import java.util.HashMap; +import java.util.Map; + +/** + * Manages end user specific objects. + * Ensures that the instance of specific class is exists only in one instance for + * specific user of specific instance. + * @param <T> user-local class + */ +public class UserLocal<T> { + private static Map<Class, Map<String, Object>> viewSingletonObjects = new HashMap<Class, Map<String, Object>>(); + private final Class<? extends T> tClass; + + public UserLocal(Class<? extends T> tClass) { + this.tClass =tClass; + } + + /** + * Initial value of user-local class. Value can be set either by initialValue() on first get() call, + * or directly by calling set() method. Default initial value is null, it can be changed by overriding + * this method. + * @param context initial value usually based on user properties provided by View Context + * @return initial value of user-local variable + */ + protected synchronized T initialValue(ViewContext context) { + return null; + } + + /** + * Returns user-local instance. + * If instance of class is not present yet for user, calls initialValue to create it. + * @param context View context that provides instance and user names. + * @return instance + */ + public T get(ViewContext context) { + if (!viewSingletonObjects.containsKey(tClass)) { + viewSingletonObjects.put(tClass, new HashMap<String, Object>()); + } + + Map<String, Object> instances = viewSingletonObjects.get(tClass); + + if (!instances.containsKey(getTagName(context))) { + instances.put(getTagName(context), initialValue(context)); + } + return (T) instances.get(getTagName(context)); + } + + /** + * Method for directly setting user-local singleton instances. + * @param obj new variable value for current user + * @param context ViewContext that provides username and instance name + */ + public void set(T obj, ViewContext context) { + if (!viewSingletonObjects.containsKey(tClass)) { + viewSingletonObjects.put(tClass, new HashMap<String, Object>()); + } + + Map<String, Object> instances = viewSingletonObjects.get(tClass); + instances.put(getTagName(context), obj); + } + + /** + * Remove instance if it's already exists. + * @param context ViewContext that provides username and instance name + */ + public void remove(ViewContext context) { + if (viewSingletonObjects.containsKey(tClass)) { + Map<String, Object> instances = viewSingletonObjects.get(tClass); + if (instances.containsKey(getTagName(context))) { + instances.remove(getTagName(context)); + } + } + } + + /** + * Returns unique key for Map to store a user-local variable. + * @param context ViewContext + * @return Unique identifier of pair instance-user. + */ + private String getTagName(ViewContext context) { + if (context == null) { + return "<null>"; + } + return String.format("%s:%s", context.getInstanceName(), context.getUsername()); + } + + /** + * Method for testing purposes, intended to clear the cached user-local instances. + * Method should not normally be called from production code. + * @param tClass classname instances of which should be dropped + */ + public static void dropAllConnections(Class tClass) { + Map<String, Object> instances = viewSingletonObjects.get(tClass); + if (instances != null) { + viewSingletonObjects.get(tClass).clear(); + } + } + + /** + * Method for testing purposes, intended to clear the cached user-local instances. + * Drops all classes of user-local variables. + * Method should not normally be called from production code. + */ + public static void dropAllConnections() { + viewSingletonObjects.clear(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16bcc80e/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocalFactory.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocalFactory.java b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocalFactory.java new file mode 100644 index 0000000..33c6a6d --- /dev/null +++ b/contrib/views/utils/src/main/java/org/apache/ambari/view/utils/UserLocalFactory.java @@ -0,0 +1,27 @@ +/** + * 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.ambari.view.utils; + +/** + * + * @param <T> + */ +public interface UserLocalFactory <T>{ + T create(); +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16bcc80e/contrib/views/utils/src/test/java/org/apache/ambari/view/utils/ViewUserLocalTest.java ---------------------------------------------------------------------- diff --git a/contrib/views/utils/src/test/java/org/apache/ambari/view/utils/ViewUserLocalTest.java b/contrib/views/utils/src/test/java/org/apache/ambari/view/utils/ViewUserLocalTest.java index c82df62..293de9d 100644 --- a/contrib/views/utils/src/test/java/org/apache/ambari/view/utils/ViewUserLocalTest.java +++ b/contrib/views/utils/src/test/java/org/apache/ambari/view/utils/ViewUserLocalTest.java @@ -38,7 +38,7 @@ public class ViewUserLocalTest { expect(viewContext2.getUsername()).andReturn("leia").anyTimes(); replay(viewContext, viewContext2); - ViewUserLocal<Object> test = new ViewUserLocal<Object>(Object.class) { + UserLocal<Object> test = new UserLocal<Object>(Object.class) { @Override protected synchronized Object initialValue(ViewContext context) { return new Object(); @@ -61,7 +61,7 @@ public class ViewUserLocalTest { expect(viewContext2.getUsername()).andReturn("luke").anyTimes(); replay(viewContext, viewContext2); - ViewUserLocal<Object> test = new ViewUserLocal<Object>(Object.class) { + UserLocal<Object> test = new UserLocal<Object>(Object.class) { @Override protected synchronized Object initialValue(ViewContext context) { return new Object(); @@ -84,7 +84,7 @@ public class ViewUserLocalTest { expect(viewContext2.getUsername()).andReturn("luke").anyTimes(); replay(viewContext, viewContext2); - ViewUserLocal<Object> test = new ViewUserLocal<Object>(Object.class) { + UserLocal<Object> test = new UserLocal<Object>(Object.class) { @Override protected synchronized Object initialValue(ViewContext context) { return new Object();
