made AbstractInvocationHandler that uses safer objects

This commit is contained in:
Adrian Cole 2013-01-05 18:48:22 -08:00
parent 983324670a
commit c43aac2ecc
2 changed files with 124 additions and 0 deletions

View File

@ -0,0 +1,58 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.reflect;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.reflect.Invokable;
/**
* Like {@link com.google.common.reflect.AbstractInvocationHandler}, except you process {@link Invokable} and
* {@link List} as opposed to {@link Method} and arg arrays.
*
* @author Adrian Cole
* @since 1.6
*/
@Beta
public abstract class AbstractInvocationHandler extends com.google.common.reflect.AbstractInvocationHandler {
/**
* @param args
* note that this can contain nulls, as method arguments can be null.
* @see com.google.common.reflect.AbstractInvocationHandler#invoke(Object, Method, Object[])
*/
protected abstract Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable;
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] argv) throws Throwable {
List<Object> args = Arrays.asList(argv);
if (Iterables.all(args, Predicates.notNull()))
args = ImmutableList.copyOf(args);
else
args = Collections.unmodifiableList(args);
return handleInvocation(proxy, Invokable.from(method), args);
}
}

View File

@ -0,0 +1,66 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.jclouds.reflect;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Reflection;
/**
*
* @author Adrian Cole
*/
@Test
public class AbstractInvocationHandlerTest {
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testNullArgsAreAllowedAndUnmodifiable() throws IOException {
Reflection.newProxy(Appendable.class, new AbstractInvocationHandler() {
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
assertNotNull(args);
assertNull(args.get(0));
args.add("foo");
throw new AssertionError("shouldn't be able to mutate the list!");
}
}).append(null);
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testImmutableListWhenArgsAreNotNull() throws IOException {
Reflection.newProxy(Appendable.class, new AbstractInvocationHandler() {
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
assertNotNull(args);
assertTrue(args instanceof ImmutableList);
assertEquals(args.get(0), "foo");
args.add("bar");
throw new AssertionError("shouldn't be able to mutate the list!");
}
}).append("foo");
}
}