Remove FieldExposers, since GAE reflection works normally

Calling setAccessible() cross-package used to fail in
the custom security manager. It never shouldn have failed,
and now it works correctly (not sure when it was fixed) so
remove these trampolines.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=138549703
This commit is contained in:
cgoldfeder 2016-11-08 12:28:29 -08:00 committed by Ben McIlwain
parent 2cbfd6475d
commit 1abd0e1123
5 changed files with 6 additions and 193 deletions

View file

@ -1,35 +0,0 @@
// Copyright 2016 The Nomulus Authors. All Rights Reserved.
//
// Licensed 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 google.registry.model;
import java.lang.reflect.Field;
/**
* A helper that exposes package-private fields in this package for reflective lookup.
*
* <p>By adding a subclass of this to every package in the model, we can write generic code that can
* access fields with package private access. The other alternative is to call
* {@link Field#setAccessible} with {@code true} on any such Field objects, but that does not work
* reliably in Google App Engine cross-package because of its custom security manager
* implementation.
*/
public abstract class AbstractFieldExposer {
public abstract Object getFieldValue(Object instance, Field field) throws IllegalAccessException;
public abstract void setFieldValue(Object instance, Field field, Object value)
throws IllegalAccessException;
public abstract void setAccessible(Field field);
}

View file

@ -11,10 +11,7 @@ java_library(
"*.java",
"*/*.java",
"*/*/*.java",
]) + [
"FieldExposerRegistry.java",
":field_exposers",
],
]),
visibility = ["//visibility:public"],
deps = [
"//java/com/google/common/annotations",
@ -42,57 +39,3 @@ java_library(
"//java/google/registry/xml",
],
)
# Generate FieldExposer classes to work around AppEngine's security limitations.
genrule(
name = "field_exposers",
srcs = ["generate_field_exposer.sh"],
outs = [
"FieldExposer.java",
"billing/FieldExposer.java",
"common/FieldExposer.java",
"contact/FieldExposer.java",
"dns/FieldExposer.java",
"domain/FieldExposer.java",
"domain/allocate/FieldExposer.java",
"domain/fee/FieldExposer.java",
"domain/fee06/FieldExposer.java",
"domain/fee11/FieldExposer.java",
"domain/fee12/FieldExposer.java",
"domain/flags/FieldExposer.java",
"domain/launch/FieldExposer.java",
"domain/rgp/FieldExposer.java",
"domain/secdns/FieldExposer.java",
"eppcommon/FieldExposer.java",
"eppinput/FieldExposer.java",
"eppoutput/FieldExposer.java",
"export/FieldExposer.java",
"host/FieldExposer.java",
"index/FieldExposer.java",
"mark/FieldExposer.java",
"ofy/FieldExposer.java",
"poll/FieldExposer.java",
"rde/FieldExposer.java",
"registrar/FieldExposer.java",
"registry/FieldExposer.java",
"registry/label/FieldExposer.java",
"reporting/FieldExposer.java",
"server/FieldExposer.java",
"smd/FieldExposer.java",
"tmch/FieldExposer.java",
"transfer/FieldExposer.java",
"translators/FieldExposer.java",
],
cmd = "for FILE in $(OUTS); do\n" +
" $(location generate_field_exposer.sh) $$FILE >> $$FILE\n" +
"done",
)
# Generate a registry of FieldExposers.
genrule(
name = "field_exposer_registry",
srcs = [":field_exposers"],
outs = ["FieldExposerRegistry.java"],
cmd = "$(location generate_field_exposer_registry.sh) $(SRCS) >$@",
tools = ["generate_field_exposer_registry.sh"],
)

View file

@ -14,7 +14,6 @@
package google.registry.model;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.isNull;
import static com.google.common.base.Predicates.or;
@ -27,7 +26,6 @@ import static java.util.Arrays.asList;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@ -36,7 +34,6 @@ import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Id;
@ -74,35 +71,17 @@ public class ModelUtils {
}
Map<String, Field> fields = new LinkedHashMap<>();
for (Class<?> hierarchyClass : hierarchy) {
Package pakkage = hierarchyClass.getPackage();
// Don't use hierarchyClass.getFields() because it only picks up public fields.
for (Field field : hierarchyClass.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
if (!Modifier.isStatic(field.getModifiers())) {
field.setAccessible(true);
fields.put(field.getName(), field);
}
// Strictly speaking this shouldn't be necessary since all of these fields
// are already accessible to their FieldExposer, but it is more performant
// to access fields if they are marked accessible this way because it skips
// various security checks.
checkNotNull(
FIELD_EXPOSERS.get(pakkage),
"No FieldExposer registered for %s", pakkage.getName())
.setAccessible(field);
fields.put(field.getName(), field);
}
}
return ImmutableMap.copyOf(fields);
}});
/** Per-package trampolines to expose package-private fields for reflection. */
private static final Map<Package, AbstractFieldExposer> FIELD_EXPOSERS = Maps.uniqueIndex(
FieldExposerRegistry.getFieldExposers(),
new Function<AbstractFieldExposer, Package>() {
@Override
public Package apply(AbstractFieldExposer exposer) {
return exposer.getClass().getPackage();
}});
/** Lists all instance fields on an object, including non-public and inherited fields. */
static Map<String, Field> getAllFields(Class<?> clazz) {
return ALL_FIELDS_CACHE.getUnchecked(clazz);
@ -187,10 +166,7 @@ public class ModelUtils {
/** Retrieves a field value via reflection. */
static Object getFieldValue(Object instance, Field field) {
try {
return Preconditions.checkNotNull(
FIELD_EXPOSERS.get(field.getDeclaringClass().getPackage()),
"No FieldExposer registered for %s", field.getDeclaringClass().getPackage().getName())
.getFieldValue(instance, field);
return field.get(instance);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
@ -199,10 +175,7 @@ public class ModelUtils {
/** Sets a field value via reflection. */
static void setFieldValue(Object instance, Field field, Object value) {
try {
Preconditions.checkNotNull(
FIELD_EXPOSERS.get(field.getDeclaringClass().getPackage()),
"No FieldExposer registered for %s", field.getDeclaringClass().getPackage().getName())
.setFieldValue(instance, field, value);
field.set(instance, value);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}

View file

@ -1,36 +0,0 @@
#!/bin/sh -
# Copyright 2016 The Nomulus Authors. All Rights Reserved.
#
# Licensed 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.
# Generate a FieldExposer for a given package
printf "package google.registry.model"\
`echo $1 | sed -e 's/.*\/model\(.*\).FieldExposer\.java/\1/' -e 's/\//./g'`";\
\n\n\
import google.registry.model.AbstractFieldExposer;\n\n\
import java.lang.reflect.Field;\n\n\
/** A helper that exposes package-private fields in this package for reflective lookup. */\n\
public class FieldExposer extends AbstractFieldExposer {\n\
public Object getFieldValue(Object instance, Field field) throws IllegalAccessException {\n\
return field.get(instance);\n\
}\n\n\
public void setFieldValue(Object instance, Field field, Object value)\n\
throws IllegalAccessException {\n\
field.set(instance, value);\n\
}\n\n\
public void setAccessible(Field field) {\n\
field.setAccessible(true);\n\
}\n\
}\n"

View file

@ -1,32 +0,0 @@
#!/bin/sh -
# Copyright 2016 The Nomulus Authors. All Rights Reserved.
#
# Licensed 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.
# Generate a FieldExposer for a given package
printf "package google.registry.model;\n\n\
import google.registry.model.AbstractFieldExposer;\n\n\
import com.google.common.collect.ImmutableList;\n\n\
/** A registry of all {@link AbstractFieldExposer} impls. */\n\
class FieldExposerRegistry {\n\
static ImmutableList<AbstractFieldExposer> getFieldExposers() {\n\
return new ImmutableList.Builder<AbstractFieldExposer>()\n"
for FILE in $@; do
echo $FILE | sed \
-e 's!^.*/java/\(.*\)\.java$! .add(new \1())!' \
-e 's!/!.!g'
done
printf " .build();\n"
printf " }\n}\n"