Details
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java b/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
index 65f339f..79a0a45 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/config/MultiTenantInvoiceConfig.java
@@ -17,14 +17,13 @@
package org.killbill.billing.invoice.config;
-import java.lang.reflect.Method;
-
import javax.inject.Inject;
import javax.inject.Named;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.glue.InvoiceModule;
import org.killbill.billing.util.config.definition.InvoiceConfig;
+import org.killbill.billing.util.config.definition.KillbillConfig;
import org.killbill.billing.util.config.tenant.CacheConfig;
import org.killbill.billing.util.config.tenant.MultiTenantConfigBase;
import org.skife.config.TimeSpan;
@@ -46,8 +45,7 @@ public class MultiTenantInvoiceConfig extends MultiTenantConfigBase implements I
@Override
public int getNumberOfMonthsInFuture(final InternalTenantContext tenantContext) {
- final Method method = new Object(){}.getClass().getEnclosingMethod();
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getNumberOfMonthsInFuture", tenantContext);
if (result != null) {
return Integer.parseInt(result);
}
@@ -61,8 +59,7 @@ public class MultiTenantInvoiceConfig extends MultiTenantConfigBase implements I
@Override
public TimeSpan getDryRunNotificationSchedule(final InternalTenantContext tenantContext) {
- final Method method = new Object(){}.getClass().getEnclosingMethod();
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getDryRunNotificationSchedule", tenantContext);
if (result != null) {
return new TimeSpan(result);
}
@@ -76,8 +73,7 @@ public class MultiTenantInvoiceConfig extends MultiTenantConfigBase implements I
@Override
public int getMaxRawUsagePreviousPeriod(final InternalTenantContext tenantContext) {
- final Method method = new Object(){}.getClass().getEnclosingMethod();
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getMaxRawUsagePreviousPeriod", tenantContext);
if (result != null) {
return Integer.parseInt(result);
}
@@ -95,11 +91,7 @@ public class MultiTenantInvoiceConfig extends MultiTenantConfigBase implements I
}
@Override
- protected Method getConfigStaticMethod(final String methodName) {
- try {
- return InvoiceConfig.class.getMethod(methodName, InternalTenantContext.class);
- } catch (final NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
+ protected Class<? extends KillbillConfig> getConfigClass() {
+ return InvoiceConfig.class;
}
}
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
index 7a6b6aa..ee09c1a 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/util/JaxrsUriBuilder.java
@@ -17,6 +17,7 @@
package org.killbill.billing.jaxrs.util;
import java.net.URI;
+import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
@@ -33,6 +34,10 @@ import org.killbill.billing.util.config.definition.JaxrsConfig;
public class JaxrsUriBuilder {
private final JaxrsConfig jaxrsConfig;
+ private final Map<Class, UriBuilder> classToUriBuilder = new HashMap<Class, UriBuilder>();
+ private final Map<String, UriBuilder> classAndMethodToUriBuilder = new HashMap<String, UriBuilder>();
+ private final Map<String, UriBuilder> pathAndClassToUriBuilder = new HashMap<String, UriBuilder>();
+ private final Map<String, UriBuilder> pathClassAndMethodToUriBuilder = new HashMap<String, UriBuilder>();
@Inject
public JaxrsUriBuilder(JaxrsConfig jaxrsConfig) {
@@ -53,8 +58,8 @@ public class JaxrsUriBuilder {
if (jaxrsConfig.isJaxrsLocationFullUrl()) {
uriBuilder.scheme(uriInfo.getAbsolutePath().getScheme())
- .host(uriInfo.getAbsolutePath().getHost())
- .port(uriInfo.getAbsolutePath().getPort());
+ .host(uriInfo.getAbsolutePath().getHost())
+ .port(uriInfo.getAbsolutePath().getPort());
}
return objectId != null ? uriBuilder.build(objectId) : uriBuilder.build();
}
@@ -92,15 +97,74 @@ public class JaxrsUriBuilder {
private UriBuilder getUriBuilder(final String path, final Class<? extends JaxrsResource> theClassMaybeEnhanced, @Nullable final String getMethodName) {
final Class theClass = getNonEnhancedClass(theClassMaybeEnhanced);
- return getMethodName != null ? UriBuilder.fromPath(path.equals("/") ? path.substring(1) : path).path(theClass).path(theClass, getMethodName) :
- UriBuilder.fromPath(path).path(theClass);
+ return getMethodName != null ? fromPath(path.equals("/") ? path.substring(1) : path, theClass, getMethodName) : fromPath(path, theClass);
+ }
+
+ private UriBuilder fromPath(final String path, final Class theClass, final String getMethodName) {
+ final String key = path + theClass.getName() + getMethodName;
+
+ UriBuilder uriBuilder = pathClassAndMethodToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ synchronized (pathClassAndMethodToUriBuilder) {
+ uriBuilder = pathClassAndMethodToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ uriBuilder = fromPath(path, theClass).path(theClass, getMethodName);
+ pathClassAndMethodToUriBuilder.put(key, uriBuilder);
+ }
+ }
+ }
+ return uriBuilder.clone();
+ }
+
+ private UriBuilder fromPath(final String path, final Class theClass) {
+ final String key = path + theClass.getName();
+
+ UriBuilder uriBuilder = pathAndClassToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ synchronized (pathAndClassToUriBuilder) {
+ uriBuilder = pathAndClassToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ uriBuilder = UriBuilder.fromPath(path).path(theClass);
+ pathAndClassToUriBuilder.put(key, uriBuilder);
+ }
+ }
+ }
+ return uriBuilder.clone();
}
private UriBuilder getUriBuilder(final Class<? extends JaxrsResource> theClassMaybeEnhanced, @Nullable final String getMethodName) {
final Class theClass = getNonEnhancedClass(theClassMaybeEnhanced);
- return getMethodName != null ? UriBuilder.fromResource(theClass).path(theClass, getMethodName) :
- UriBuilder.fromResource(theClass);
+ return getMethodName != null ? fromResource(theClass, getMethodName) : fromResource(theClass);
+ }
+ private UriBuilder fromResource(final Class theClass, final String getMethodName) {
+ final String key = theClass.getName() + getMethodName;
+
+ UriBuilder uriBuilder = classAndMethodToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ synchronized (classAndMethodToUriBuilder) {
+ uriBuilder = classAndMethodToUriBuilder.get(key);
+ if (uriBuilder == null) {
+ uriBuilder = fromResource(theClass).path(theClass, getMethodName);
+ classAndMethodToUriBuilder.put(key, uriBuilder);
+ }
+ }
+ }
+ return uriBuilder.clone();
+ }
+
+ private UriBuilder fromResource(final Class theClass) {
+ UriBuilder uriBuilder = classToUriBuilder.get(theClass);
+ if (uriBuilder == null) {
+ synchronized (classToUriBuilder) {
+ uriBuilder = classToUriBuilder.get(theClass);
+ if (uriBuilder == null) {
+ uriBuilder = UriBuilder.fromResource(theClass);
+ classToUriBuilder.put(theClass, uriBuilder);
+ }
+ }
+ }
+ return uriBuilder.clone();
}
private Class getNonEnhancedClass(final Class<? extends JaxrsResource> theClassMaybeEnhanced) {
diff --git a/payment/src/main/java/org/killbill/billing/payment/config/MultiTenantPaymentConfig.java b/payment/src/main/java/org/killbill/billing/payment/config/MultiTenantPaymentConfig.java
index bbf365f..6e56c52 100644
--- a/payment/src/main/java/org/killbill/billing/payment/config/MultiTenantPaymentConfig.java
+++ b/payment/src/main/java/org/killbill/billing/payment/config/MultiTenantPaymentConfig.java
@@ -17,7 +17,6 @@
package org.killbill.billing.payment.config;
-import java.lang.reflect.Method;
import java.util.List;
import javax.inject.Inject;
@@ -25,6 +24,7 @@ import javax.inject.Named;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.payment.glue.PaymentModule;
+import org.killbill.billing.util.config.definition.KillbillConfig;
import org.killbill.billing.util.config.definition.PaymentConfig;
import org.killbill.billing.util.config.tenant.CacheConfig;
import org.killbill.billing.util.config.tenant.MultiTenantConfigBase;
@@ -48,11 +48,9 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public List<Integer> getPaymentFailureRetryDays(@Param("dummy") final InternalTenantContext tenantContext) {
- // There is no good way to achieve that in java; this solution is expensive (we could consider hardcoding the method name each time instead)
- final Method method = new Object() {}.getClass().getEnclosingMethod();
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPaymentFailureRetryDays", tenantContext);
if (result != null) {
- return convertToListInteger(result, method.getName());
+ return convertToListInteger(result, "getPaymentFailureRetryDays");
}
return getPaymentFailureRetryDays();
}
@@ -64,8 +62,7 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public int getPluginFailureInitialRetryInSec(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPluginFailureInitialRetryInSec", tenantContext);
if (result != null) {
return Integer.parseInt(result);
}
@@ -79,9 +76,7 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public int getPluginFailureRetryMultiplier(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
-
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPluginFailureRetryMultiplier", tenantContext);
if (result != null) {
return Integer.parseInt(result);
}
@@ -95,11 +90,9 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public List<TimeSpan> getIncompleteTransactionsRetries(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
-
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getIncompleteTransactionsRetries", tenantContext);
if (result != null) {
- return convertToListTimeSpan(result, method.getName());
+ return convertToListTimeSpan(result, "getIncompleteTransactionsRetries");
}
return getIncompleteTransactionsRetries();
}
@@ -111,9 +104,7 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public int getPluginFailureRetryMaxAttempts(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
-
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPluginFailureRetryMaxAttempts", tenantContext);
if (result != null) {
return Integer.parseInt(result);
}
@@ -127,11 +118,9 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
@Override
public List<String> getPaymentControlPluginNames(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
-
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPaymentControlPluginNames", tenantContext);
if (result != null) {
- return convertToListString(result, method.getName());
+ return convertToListString(result, "getPaymentControlPluginNames");
}
return getPaymentControlPluginNames();
}
@@ -167,11 +156,7 @@ public class MultiTenantPaymentConfig extends MultiTenantConfigBase implements P
}
@Override
- protected Method getConfigStaticMethod(final String methodName) {
- try {
- return PaymentConfig.class.getMethod(methodName, InternalTenantContext.class);
- } catch (final NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
+ protected Class<? extends KillbillConfig> getConfigClass() {
+ return PaymentConfig.class;
}
}
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java b/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java
index cfea29b..08ffd8a 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/config/MultiTenantNotificationConfig.java
@@ -18,10 +18,13 @@
package org.killbill.billing.server.config;
import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.payment.glue.PaymentModule;
+import org.killbill.billing.util.config.definition.KillbillConfig;
import org.killbill.billing.util.config.definition.NotificationConfig;
import org.killbill.billing.util.config.tenant.CacheConfig;
import org.killbill.billing.util.config.tenant.MultiTenantConfigBase;
@@ -33,6 +36,7 @@ import com.google.inject.name.Named;
public class MultiTenantNotificationConfig extends MultiTenantConfigBase implements NotificationConfig {
+ private final Map<String, Method> methodsCache = new HashMap<String, Method>();
private final NotificationConfig staticConfig;
@Inject
@@ -42,27 +46,21 @@ public class MultiTenantNotificationConfig extends MultiTenantConfigBase impleme
}
@Override
- protected Method getConfigStaticMethod(final String methodName) {
- try {
- return NotificationConfig.class.getMethod(methodName, InternalTenantContext.class);
- } catch (final NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
public List<TimeSpan> getPushNotificationsRetries() {
return staticConfig.getPushNotificationsRetries();
}
@Override
public List<TimeSpan> getPushNotificationsRetries(@Param("dummy") final InternalTenantContext tenantContext) {
- final Method method = new Object() {}.getClass().getEnclosingMethod();
-
- final String result = getStringTenantConfig(method.getName(), tenantContext);
+ final String result = getStringTenantConfig("getPushNotificationsRetries", tenantContext);
if (result != null) {
- return convertToListTimeSpan(result, method.getName());
+ return convertToListTimeSpan(result, "getPushNotificationsRetries");
}
return getPushNotificationsRetries();
}
+
+ @Override
+ protected Class<? extends KillbillConfig> getConfigClass() {
+ return NotificationConfig.class;
+ }
}
diff --git a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
index 87f0b0a..39562ee 100644
--- a/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
+++ b/util/src/main/java/org/killbill/billing/util/config/tenant/MultiTenantConfigBase.java
@@ -18,9 +18,12 @@
package org.killbill.billing.util.config.tenant;
import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.killbill.billing.callcontext.InternalTenantContext;
+import org.killbill.billing.util.config.definition.KillbillConfig;
import org.skife.config.Config;
import org.skife.config.Separator;
import org.skife.config.TimeSpan;
@@ -31,6 +34,7 @@ import com.google.common.collect.Iterables;
public abstract class MultiTenantConfigBase {
+ private final Map<String, Method> methodsCache = new HashMap<String, Method>();
protected final CacheConfig cacheConfig;
private final static Function<String, Integer> INT_CONVERTER = new Function<String, Integer>() {
@@ -107,5 +111,23 @@ public abstract class MultiTenantConfigBase {
return ImmutableList.copyOf(value.split(separator == null ? Separator.DEFAULT : separator.value()));
}
- protected abstract Method getConfigStaticMethod(final String methodName);
+ protected Method getConfigStaticMethod(final String methodName) {
+ Method method = methodsCache.get(methodName);
+ if (method == null) {
+ synchronized (methodsCache) {
+ method = methodsCache.get(methodName);
+ if (method == null) {
+ try {
+ method = getConfigClass().getMethod(methodName, InternalTenantContext.class);
+ methodsCache.put(methodName, method);
+ } catch (final NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ return method;
+ }
+
+ protected abstract Class<? extends KillbillConfig> getConfigClass();
}
diff --git a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
index 3973932..7ae7360 100644
--- a/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
+++ b/util/src/main/java/org/killbill/billing/util/security/AnnotationHierarchicalResolver.java
@@ -18,6 +18,7 @@ package org.killbill.billing.util.security;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
+import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
@@ -26,13 +27,26 @@ import org.apache.shiro.aop.MethodInvocation;
public class AnnotationHierarchicalResolver implements AnnotationResolver {
+ private final Map<String, Annotation> methodToAnnotation = new HashMap<String, Annotation>();
+
@Override
public Annotation getAnnotation(final MethodInvocation mi, final Class<? extends Annotation> clazz) {
return getAnnotationFromMethod(mi.getMethod(), clazz);
}
public Annotation getAnnotationFromMethod(final Method method, final Class<? extends Annotation> clazz) {
- return findAnnotation(method, clazz);
+ final String key = method.toString();
+ Annotation annotation = methodToAnnotation.get(key);
+ if (annotation == null) {
+ synchronized (methodToAnnotation) {
+ annotation = methodToAnnotation.get(key);
+ if (annotation == null) {
+ annotation = findAnnotation(method, clazz);
+ methodToAnnotation.put(key, annotation);
+ }
+ }
+ }
+ return annotation;
}
// The following comes from spring-core (AnnotationUtils) to handle annotations on interfaces