killbill-uncached
Changes
.circleci/config.yml 6(+3 -3)
.idea/compiler.xml 38(+19 -19)
catalog/src/main/java/org/killbill/billing/catalog/caching/DefaultOverriddenPlanCache.java 66(+33 -33)
catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseBillingAlignment.java 25(+23 -2)
catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanAlignment.java 25(+23 -2)
catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanPolicy.java 35(+30 -5)
catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java 39(+32 -7)
overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStatesAccount.java 53(+48 -5)
overdue/src/test/java/org/killbill/billing/overdue/caching/TestDefaultOverdueConfigCache.java 8(+6 -2)
payment/src/main/java/org/killbill/billing/payment/caching/DefaultStateMachineConfigCache.java 22(+9 -13)
payment/src/main/java/org/killbill/billing/payment/caching/SerializableStateMachineConfig.java 80(+0 -80)
payment/src/test/java/org/killbill/billing/payment/caching/TestStateMachineConfigCache.java 3(+1 -2)
pom.xml 2(+1 -1)
profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java 10(+5 -5)
profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java 9(+4 -5)
Details
.circleci/config.yml 6(+3 -3)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index fa5db56..df90966 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -43,7 +43,7 @@ jobs:
- checkout
- restore_cache:
key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
- - run: mvn clean install -Ptravis
+ - run: mvn -Djava.security.egd=file:/dev/./urandom clean install -Ptravis
- run:
name: Save test results
command: |
@@ -82,7 +82,7 @@ jobs:
set -e
./bin/db-helper -a create --driver mysql -u root -p root -t yes -h 127.0.0.1
- - run: mvn clean install -Plocaltest-mysql
+ - run: mvn -Djava.security.egd=file:/dev/./urandom clean install -Plocaltest-mysql
- run:
name: Save test results
command: |
@@ -107,7 +107,7 @@ jobs:
- run:
name: Setup latest DDL
command: ./bin/db-helper -a create --driver postgres -u postgres -p postgres -t yes
- - run: mvn clean install -Plocaltest-postgresql
+ - run: mvn -Djava.security.egd=file:/dev/./urandom clean install -Plocaltest-postgresql
- run:
name: Save test results
command: |
.idea/compiler.xml 38(+19 -19)
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index cb68ce5..721e7df 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -36,25 +36,25 @@
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
- <module name="killbill" target="1.6" />
- <module name="killbill-account" target="1.6" />
- <module name="killbill-beatrix" target="1.6" />
- <module name="killbill-catalog" target="1.6" />
- <module name="killbill-currency" target="1.6" />
- <module name="killbill-entitlement" target="1.6" />
- <module name="killbill-internal-api" target="1.6" />
- <module name="killbill-invoice" target="1.6" />
- <module name="killbill-jaxrs" target="1.6" />
- <module name="killbill-junction" target="1.6" />
- <module name="killbill-overdue" target="1.6" />
- <module name="killbill-payment" target="1.6" />
- <module name="killbill-profiles" target="1.6" />
- <module name="killbill-profiles-killbill" target="1.6" />
- <module name="killbill-profiles-killpay" target="1.6" />
- <module name="killbill-subscription" target="1.6" />
- <module name="killbill-tenant" target="1.6" />
- <module name="killbill-usage" target="1.6" />
- <module name="killbill-util" target="1.6" />
+ <module name="killbill" target="1.8" />
+ <module name="killbill-account" target="1.8" />
+ <module name="killbill-beatrix" target="1.8" />
+ <module name="killbill-catalog" target="1.8" />
+ <module name="killbill-currency" target="1.8" />
+ <module name="killbill-entitlement" target="1.8" />
+ <module name="killbill-internal-api" target="1.8" />
+ <module name="killbill-invoice" target="1.8" />
+ <module name="killbill-jaxrs" target="1.8" />
+ <module name="killbill-junction" target="1.8" />
+ <module name="killbill-overdue" target="1.8" />
+ <module name="killbill-payment" target="1.8" />
+ <module name="killbill-profiles" target="1.8" />
+ <module name="killbill-profiles-killbill" target="1.8" />
+ <module name="killbill-profiles-killpay" target="1.8" />
+ <module name="killbill-subscription" target="1.8" />
+ <module name="killbill-tenant" target="1.8" />
+ <module name="killbill-usage" target="1.8" />
+ <module name="killbill-util" target="1.8" />
</bytecodeTargetLevel>
</component>
<component name="JavacSettings">
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index a106408..3e1dd16 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,10 +1,11 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
- <option name="myLocal" value="false" />
+ <inspection_tool class="Anonymous2MethodRef" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CheckTagEmptyBody" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConfusingOctalEscape" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="ControlFlowStatementWithoutBraces" enabled="true" level="WARNING" enabled_by_default="true" />
+ <inspection_tool class="Convert2Lambda" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CyclicClassDependency" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="FieldMayBeFinal" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="HardcodedLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -24,11 +25,13 @@
</inspection_tool>
<inspection_tool class="RedundantTypeArguments" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SizeReplaceableByIsEmpty" enabled="true" level="WARNING" enabled_by_default="true" />
+ <inspection_tool class="TryWithIdenticalCatches" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeMayBeWeakened" enabled="true" level="WARNING" enabled_by_default="true">
<option name="useRighthandTypeAsWeakestTypeInAssignments" value="true" />
<option name="useParameterizedTypeForCollectionMethods" value="true" />
<option name="doNotWeakenToJavaLangObject" value="true" />
<option name="onlyWeakentoInterface" value="true" />
+ <stopClasses>org.killbill.billing.catalog.api.Plan</stopClasses>
</inspection_tool>
<inspection_tool class="UnnecessaryConstantArrayCreationExpression" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UseOfJDBCDriverClass" enabled="true" level="WARNING" enabled_by_default="true" />
diff --git a/account/src/main/java/org/killbill/billing/account/api/DefaultImmutableAccountData.java b/account/src/main/java/org/killbill/billing/account/api/DefaultImmutableAccountData.java
index fdce2f1..0c58a3a 100644
--- a/account/src/main/java/org/killbill/billing/account/api/DefaultImmutableAccountData.java
+++ b/account/src/main/java/org/killbill/billing/account/api/DefaultImmutableAccountData.java
@@ -28,9 +28,6 @@ import org.joda.time.DateTimeZone;
import org.killbill.billing.account.dao.AccountModelDao;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.util.account.AccountDateTimeUtils;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
public class DefaultImmutableAccountData implements ImmutableAccountData, Externalizable {
@@ -157,11 +154,25 @@ public class DefaultImmutableAccountData implements ImmutableAccountData, Extern
@Override
public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ this.id = new UUID(in.readLong(), in.readLong());
+ this.externalKey = in.readUTF();
+ this.currency = in.readBoolean() ? Currency.valueOf(in.readUTF()) : null;
+ this.timeZone = DateTimeZone.forID(in.readUTF());
+ this.fixedOffsetTimeZone = DateTimeZone.forID(in.readUTF());
+ this.referenceTime = new DateTime(in.readUTF());
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeLong(id.getMostSignificantBits());
+ oo.writeLong(id.getLeastSignificantBits());
+ oo.writeUTF(externalKey);
+ oo.writeBoolean(currency != null);
+ if (currency != null) {
+ oo.writeUTF(currency.name());
+ }
+ oo.writeUTF(timeZone.getID());
+ oo.writeUTF(fixedOffsetTimeZone.getID());
+ oo.writeUTF(referenceTime.toString());
}
}
diff --git a/api/src/main/java/org/killbill/billing/callcontext/CallContextBase.java b/api/src/main/java/org/killbill/billing/callcontext/CallContextBase.java
index 2f5b334..0fe2ce0 100644
--- a/api/src/main/java/org/killbill/billing/callcontext/CallContextBase.java
+++ b/api/src/main/java/org/killbill/billing/callcontext/CallContextBase.java
@@ -16,6 +16,10 @@
package org.killbill.billing.callcontext;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -24,19 +28,19 @@ import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.CallOrigin;
import org.killbill.billing.util.callcontext.UserType;
-public abstract class CallContextBase implements CallContext {
+public abstract class CallContextBase implements CallContext, Externalizable {
- protected final UUID accountId;
- protected final UUID tenantId;
- protected final UUID userToken;
- protected final String userName;
- protected final CallOrigin callOrigin;
- protected final UserType userType;
- protected final String reasonCode;
- protected final String comments;
+ protected UUID accountId;
+ protected UUID tenantId;
+ protected UUID userToken;
+ protected String userName;
+ protected CallOrigin callOrigin;
+ protected UserType userType;
+ protected String reasonCode;
+ protected String comments;
- public CallContextBase(@Nullable final UUID accountId, @Nullable final UUID tenantId, final String userName, final CallOrigin callOrigin, final UserType userType) {
- this(accountId, tenantId, userName, callOrigin, userType, null);
+ // For deserialization
+ public CallContextBase() {
}
public CallContextBase(@Nullable final UUID accountId, @Nullable final UUID tenantId, final String userName, final CallOrigin callOrigin, final UserType userType, final UUID userToken) {
@@ -94,4 +98,37 @@ public abstract class CallContextBase implements CallContext {
public UUID getUserToken() {
return userToken;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeLong(accountId == null ? 0 : accountId.getMostSignificantBits());
+ out.writeLong(accountId == null ? 0 : accountId.getLeastSignificantBits());
+ out.writeLong(tenantId == null ? 0 : tenantId.getMostSignificantBits());
+ out.writeLong(tenantId == null ? 0 : tenantId.getLeastSignificantBits());
+ out.writeLong(userToken.getMostSignificantBits());
+ out.writeLong(userToken.getLeastSignificantBits());
+ out.writeUTF(userName);
+ out.writeUTF(callOrigin.name());
+ out.writeUTF(userType.name());
+ out.writeUTF(reasonCode);
+ out.writeUTF(comments);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.accountId = new UUID(in.readLong(), in.readLong());
+ if (this.accountId.getMostSignificantBits() == 0) {
+ this.accountId = null;
+ }
+ this.tenantId = new UUID(in.readLong(), in.readLong());
+ if (this.tenantId.getMostSignificantBits() == 0) {
+ this.tenantId = null;
+ }
+ this.userToken = new UUID(in.readLong(), in.readLong());
+ this.userName = in.readUTF();
+ this.callOrigin = CallOrigin.valueOf(in.readUTF());
+ this.userType = UserType.valueOf(in.readUTF());
+ this.reasonCode = in.readUTF();
+ this.comments = in.readUTF();
+ }
}
diff --git a/api/src/main/java/org/killbill/billing/callcontext/DefaultCallContext.java b/api/src/main/java/org/killbill/billing/callcontext/DefaultCallContext.java
index c12b759..13fb6e7 100644
--- a/api/src/main/java/org/killbill/billing/callcontext/DefaultCallContext.java
+++ b/api/src/main/java/org/killbill/billing/callcontext/DefaultCallContext.java
@@ -16,19 +16,26 @@
package org.killbill.billing.callcontext;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.UUID;
import org.joda.time.DateTime;
-
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.CallOrigin;
import org.killbill.billing.util.callcontext.UserType;
import org.killbill.clock.Clock;
-public class DefaultCallContext extends CallContextBase {
+public class DefaultCallContext extends CallContextBase implements Externalizable {
+
+ private DateTime createdDate;
+ private DateTime updateDate;
- private final DateTime createdDate;
- private final DateTime updateDate;
+ // For deserialization
+ public DefaultCallContext() {
+ }
public DefaultCallContext(final UUID accountId, final UUID tenantId, final String userName, final CallOrigin callOrigin, final UserType userType,
final UUID userToken, final Clock clock) {
@@ -148,4 +155,18 @@ public class DefaultCallContext extends CallContextBase {
result = 31 * result + (createdDate != null ? createdDate.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeUTF(createdDate.toString());
+ out.writeUTF(updateDate.toString());
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.createdDate = new DateTime(in.readUTF());
+ this.updateDate = new DateTime(in.readUTF());
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
index a058104..d883ea4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
@@ -19,8 +19,6 @@ package org.killbill.billing.catalog.api.user;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -65,7 +63,6 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
private final CatalogCache catalogCache;
private final Clock clock;
-
@Inject
public DefaultCatalogUserApi(final CatalogService catalogService,
final TenantUserApi tenantApi,
@@ -116,7 +113,6 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
@Override
public void uploadCatalog(final String catalogXML, final CallContext callContext) throws CatalogApiException {
-
final InternalTenantContext internalTenantContext = createInternalTenantContext(callContext);
try {
@@ -124,7 +120,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
// Validation purpose: Will throw if bad XML or catalog validation fails
final InputStream stream = new ByteArrayInputStream(catalogXML.getBytes());
- final StaticCatalog newCatalogVersion = XMLLoader.getObjectFromStream(new URI("dummy"), stream, StandaloneCatalog.class);
+ final StaticCatalog newCatalogVersion = XMLLoader.getObjectFromStream(stream, StandaloneCatalog.class);
if (versionedCatalog != null) {
@@ -132,7 +128,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
if (versionedCatalog.getCatalogName() != null && !newCatalogVersion.getCatalogName().equals(versionedCatalog.getCatalogName())) {
final ValidationErrors errors = new ValidationErrors();
errors.add(String.format("Catalog name '%s' should match previous catalog name '%s'", newCatalogVersion.getCatalogName(), versionedCatalog.getCatalogName()),
- new URI("dummy"), StandaloneCatalog.class, "");
+ StandaloneCatalog.class, "");
// Bummer ValidationException CTOR is private to package...
//final ValidationException validationException = new ValidationException(errors);
//throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
@@ -144,7 +140,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
if (c.getEffectiveDate().compareTo(newCatalogVersion.getEffectiveDate()) == 0) {
final ValidationErrors errors = new ValidationErrors();
errors.add(String.format("Catalog version for effectiveDate '%s' already exists", newCatalogVersion.getEffectiveDate()),
- new URI("dummy"), StandaloneCatalog.class, "");
+ StandaloneCatalog.class, "");
// Bummer ValidationException CTOR is private to package...
//final ValidationException validationException = new ValidationException(errors);
//throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
@@ -166,17 +162,13 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
throw new IllegalStateException(e);
} catch (final TransformerException e) {
throw new IllegalStateException(e);
- } catch (final URISyntaxException e) {
- throw new IllegalStateException(e);
} catch (final SAXException e) {
throw new IllegalStateException(e);
} catch (final InvalidConfigException e) {
throw new IllegalStateException(e);
}
-
}
-
@Override
public void createDefaultEmptyCatalog(@Nullable final DateTime effectiveDate, final CallContext callContext) throws CatalogApiException {
@@ -224,6 +216,7 @@ public class DefaultCatalogUserApi implements CatalogUserApi {
throw new CatalogApiException(e);
}
}
+
private DateTime getSafeFirstCatalogEffectiveDate(@Nullable final DateTime input, final CallContext callContext) {
// The effectiveDate for the initial version does not matter too much
// Because of #760, we want to make that client passing a approximate date (e.g today.toDateTimeAtStartOfDay()) will find the version
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/caching/OverriddenPlanCache.java b/catalog/src/main/java/org/killbill/billing/catalog/caching/OverriddenPlanCache.java
index f888dc8..21d4e74 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/caching/OverriddenPlanCache.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/caching/OverriddenPlanCache.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -19,13 +19,13 @@ package org.killbill.billing.catalog.caching;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.DefaultPlan;
+import org.killbill.billing.catalog.StandaloneCatalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Plan;
-import org.killbill.billing.catalog.api.StaticCatalog;
public interface OverriddenPlanCache {
- DefaultPlan getOverriddenPlan(final String planName, final StaticCatalog catalog, final InternalTenantContext context) throws CatalogApiException;
+ DefaultPlan getOverriddenPlan(final String planName, final StandaloneCatalog catalog, final InternalTenantContext context) throws CatalogApiException;
void addDryRunPlan(final String planName, final Plan plan);
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java
index d2d2cbd..e797ce4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,6 +17,10 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
@@ -26,7 +30,7 @@ import org.killbill.billing.catalog.api.CatalogEntity;
import com.google.common.collect.Ordering;
-public class CatalogEntityCollection<T extends CatalogEntity> implements Collection<T> {
+public class CatalogEntityCollection<T extends CatalogEntity> implements Collection<T>, Externalizable {
private final Map<String, T> data;
@@ -41,7 +45,6 @@ public class CatalogEntityCollection<T extends CatalogEntity> implements Collect
}
}
-
public CatalogEntityCollection(final Iterable<T> entities) {
this.data = new TreeMap<String, T>(Ordering.<String>natural());
for (final T cur : entities) {
@@ -82,15 +85,18 @@ public class CatalogEntityCollection<T extends CatalogEntity> implements Collect
final Iterator<String> keyIterator = data.keySet().iterator();
final Iterator it = new Iterator() {
private String prevKey = null;
+
@Override
public boolean hasNext() {
return keyIterator.hasNext();
}
+
@Override
public Object next() {
prevKey = keyIterator.next();
return data.get(prevKey);
}
+
@Override
public void remove() {
if (prevKey != null) {
@@ -191,4 +197,13 @@ public class CatalogEntityCollection<T extends CatalogEntity> implements Collect
return data.remove(entry.getName()) != null;
}
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ data.putAll((Map<? extends String, ? extends T>) in.readObject());
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput oo) throws IOException {
+ oo.writeObject(data);
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
index f580cd3..a301784 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2016 Groupon, Inc
- * Copyright 2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,8 +18,6 @@
package org.killbill.billing.catalog;
import java.math.BigDecimal;
-import java.net.URI;
-import java.net.URISyntaxException;
import org.joda.time.DateTime;
import org.killbill.billing.ErrorCode;
@@ -53,17 +51,6 @@ public class CatalogUpdater {
public static String DEFAULT_CATALOG_NAME = "DEFAULT";
- private static URI DEFAULT_URI;
-
- static {
- try {
- DEFAULT_URI = new URI(DEFAULT_CATALOG_NAME);
- } catch (URISyntaxException e) {
- }
- }
-
- ;
-
private final DefaultMutableStaticCatalog catalog;
public CatalogUpdater(final StandaloneCatalog standaloneCatalog) {
@@ -88,7 +75,7 @@ public class CatalogUpdater {
} else {
tmp.setSupportedCurrencies(new Currency[0]);
}
- tmp.initialize(tmp, DEFAULT_URI);
+ tmp.initialize(tmp);
this.catalog = new DefaultMutableStaticCatalog(tmp);
}
@@ -119,12 +106,12 @@ public class CatalogUpdater {
validateNewPlanDescriptor(desc);
- DefaultProduct product = plan != null ? (DefaultProduct) plan.getProduct() : (DefaultProduct) getExistingProduct(desc.getProductName());
+ DefaultProduct product = plan != null ? (DefaultProduct) plan.getProduct() : (DefaultProduct) getExistingProduct(desc.getProductName());
if (product == null) {
product = new DefaultProduct();
product.setName(desc.getProductName());
product.setCatagory(desc.getProductCategory());
- product.initialize(catalog, DEFAULT_URI);
+ product.initialize(catalog);
catalog.addProduct(product);
}
@@ -197,7 +184,7 @@ public class CatalogUpdater {
}
// Reinit catalog
- catalog.initialize(catalog, DEFAULT_URI);
+ catalog.initialize(catalog);
}
private boolean isPriceForCurrencyExists(final InternationalPrice price, final Currency currency) {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultBlock.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultBlock.java
index 8e62c6c..ff42b1f 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultBlock.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultBlock.java
@@ -17,8 +17,11 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.math.BigDecimal;
-import java.net.URI;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -39,7 +42,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultBlock extends ValidatingConfig<StandaloneCatalog> implements Block {
+public class DefaultBlock extends ValidatingConfig<StandaloneCatalog> implements Block, Externalizable {
@XmlAttribute(required = false)
private BlockType type = BlockType.VANILLA;
@@ -97,7 +100,7 @@ public class DefaultBlock extends ValidatingConfig<StandaloneCatalog> implements
if (type == BlockType.TOP_UP && CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(minTopUpCredit)) {
errors.add(new ValidationError(String.format("TOP_UP block needs to define minTopUpCredit for phase %s",
- phase.getName()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.getName()), DefaultUsage.class, ""));
}
return errors;
}
@@ -112,8 +115,8 @@ public class DefaultBlock extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
@@ -189,4 +192,31 @@ public class DefaultBlock extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + (minTopUpCredit != null ? minTopUpCredit.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(type != null);
+ if (type != null) {
+ out.writeUTF(type.name());
+ }
+ out.writeObject(unit);
+ out.writeBoolean(size != null);
+ if (size != null) {
+ out.writeDouble(size);
+ }
+ out.writeObject(prices);
+ out.writeBoolean(minTopUpCredit != null);
+ if (minTopUpCredit != null) {
+ out.writeDouble(minTopUpCredit);
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.type = in.readBoolean() ? BlockType.valueOf(in.readUTF()) : null;
+ this.unit = (DefaultUnit) in.readObject();
+ this.size = in.readBoolean() ? in.readDouble() : null;
+ this.prices = (DefaultInternationalPrice) in.readObject();
+ this.minTopUpCredit = in.readBoolean() ? in.readDouble() : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultDuration.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultDuration.java
index 7af3daa..f53ebee 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultDuration.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultDuration.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -25,7 +30,6 @@ import javax.xml.bind.annotation.XmlElement;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
-
import org.killbill.billing.ErrorCode;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Duration;
@@ -35,7 +39,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> implements Duration {
+public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> implements Duration, Externalizable {
@XmlElement(required = true)
private TimeUnit unit;
@@ -43,22 +47,17 @@ public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> impleme
@XmlElement(required = false)
private Integer number;
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IDuration#getUnit()
- */
@Override
public TimeUnit getUnit() {
return unit;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IDuration#getLength()
- */
@Override
public int getNumber() {
return number;
}
+ // Required for deserialization
public DefaultDuration() {
}
@@ -115,21 +114,20 @@ public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> impleme
//Validation: TimeUnit UNLIMITED if number == -1
if ((unit == TimeUnit.UNLIMITED && !CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_INTEGER_FIELD_VALUE.equals(number))) {
errors.add(new ValidationError("Duration can only have 'UNLIMITED' unit if the number is omitted",
- catalog.getCatalogURI(), DefaultDuration.class, ""));
+ DefaultDuration.class, ""));
} else if ((unit != TimeUnit.UNLIMITED) && CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_INTEGER_FIELD_VALUE.equals(number)) {
errors.add(new ValidationError("Finite Duration must have a well defined length",
- catalog.getCatalogURI(), DefaultDuration.class, ""));
+ DefaultDuration.class, ""));
}
return errors;
}
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
public DefaultDuration setUnit(final TimeUnit unit) {
this.unit = unit;
return this;
@@ -157,7 +155,7 @@ public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> impleme
return new Period().withYears(number);
case UNLIMITED:
default:
- throw new IllegalStateException("Unexpected duration unit " + unit);
+ throw new IllegalStateException("Unexpected duration unit " + unit);
}
}
@@ -188,4 +186,19 @@ public class DefaultDuration extends ValidatingConfig<StandaloneCatalog> impleme
result = 31 * result + (number != null ? number.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(unit != null);
+ if (unit != null) {
+ out.writeUTF(unit.name());
+ }
+ out.writeInt(number);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.unit = in.readBoolean() ? TimeUnit.valueOf(in.readUTF()) : null;
+ this.number = in.readInt();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
index 924fbf5..493505f 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
@@ -1,5 +1,6 @@
/*
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -16,6 +17,10 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.net.URI;
import javax.xml.bind.annotation.XmlAccessType;
@@ -31,7 +36,7 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements Fixed {
+public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements Fixed, Externalizable {
@XmlAttribute(required = false)
private FixedType type;
@@ -49,6 +54,7 @@ public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements
return fixedPrice;
}
+ // Required for deserialization
public DefaultFixed() {
}
@@ -58,11 +64,11 @@ public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (fixedPrice != null) {
- fixedPrice.initialize(root, uri);
+ fixedPrice.initialize(root);
}
}
@@ -112,4 +118,19 @@ public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + (fixedPrice != null ? fixedPrice.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(type != null);
+ if (type != null) {
+ out.writeUTF(type.name());
+ }
+ out.writeObject(fixedPrice);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.type = in.readBoolean() ? FixedType.valueOf(in.readUTF()) : null;
+ this.fixedPrice = (DefaultInternationalPrice) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
index d2b5f7c..663579d 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,8 +18,11 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.math.BigDecimal;
-import java.net.URI;
import java.util.Arrays;
import javax.xml.bind.annotation.XmlAccessType;
@@ -35,21 +40,18 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice {
+public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice, Externalizable {
// No prices is a zero cost plan in all currencies
@XmlElement(name = "price", required = false)
private DefaultPrice[] prices;
-
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.InternationalPrice#getPrices()
- */
@Override
public Price[] getPrices() {
return prices;
}
+ // Required for deserialization
public DefaultInternationalPrice() {}
public DefaultInternationalPrice(final DefaultInternationalPrice in, final PlanPhasePriceOverride override, final boolean fixed) {
@@ -61,7 +63,7 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
this.prices = new DefaultPrice[in.getPrices().length];
// There is a question on whether we keep the other prices that were not overridden or only have one entry for the overridden price on that currency.
for (int i = 0; i < in.getPrices().length; i++) {
- final DefaultPrice curPrice = (DefaultPrice) in.getPrices()[i];
+ final DefaultPrice curPrice = (DefaultPrice) in.getPrices()[i];
if (curPrice.getCurrency().equals(override.getCurrency())) {
prices[i] = new DefaultPrice(fixed ? override.getFixedPrice() : override.getRecurringPrice(), override.getCurrency());
} else {
@@ -74,8 +76,8 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
public DefaultInternationalPrice(final DefaultInternationalPrice in, final BigDecimal overriddenPrice, final Currency currency) {
this.prices = in.getPrices() != null ? new DefaultPrice[in.getPrices().length] : null;
for (int i = 0; i < in.getPrices().length; i++) {
- final DefaultPrice curPrice = (DefaultPrice) in.getPrices()[i];
- if (curPrice.getCurrency().equals(currency)){
+ final DefaultPrice curPrice = (DefaultPrice) in.getPrices()[i];
+ if (curPrice.getCurrency().equals(currency)) {
prices[i] = new DefaultPrice(overriddenPrice, currency);
} else {
prices[i] = curPrice;
@@ -83,9 +85,6 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
}
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IInternationalPrice#getPrice(org.killbill.billing.catalog.api.Currency)
- */
@Override
public BigDecimal getPrice(final Currency currency) throws CatalogApiException {
if (prices.length == 0) {
@@ -105,18 +104,17 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
return this;
}
-
@Override
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
final Currency[] supportedCurrencies = catalog.getCurrentSupportedCurrencies();
for (final Price p : prices) {
final Currency currency = p.getCurrency();
if (!currencyIsSupported(currency, supportedCurrencies)) {
- errors.add("Unsupported currency: " + currency, catalog.getCatalogURI(), this.getClass(), "");
+ errors.add("Unsupported currency: " + currency, this.getClass(), "");
}
try {
if (p.getValue().doubleValue() < 0.0) {
- errors.add("Negative value for price in currency: " + currency, catalog.getCatalogURI(), this.getClass(), "");
+ errors.add("Negative value for price in currency: " + currency, this.getClass(), "");
}
} catch (CurrencyValueNull e) {
// No currency => nothing to check, ignore exception
@@ -134,14 +132,12 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
return false;
}
-
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
@Override
public boolean isZero() {
for (final DefaultPrice price : prices) {
@@ -178,4 +174,14 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
public int hashCode() {
return prices != null ? Arrays.hashCode(prices) : 0;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(prices);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.prices = (DefaultPrice[]) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
index 084b644..e526dc8 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
@@ -1,7 +1,7 @@
/*
- * Copyright 2010-2011 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -31,7 +34,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements Limit {
+public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements Limit, Externalizable {
@XmlElement(required = true)
@XmlIDREF
@@ -43,25 +46,16 @@ public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements
@XmlElement(required = false)
private Double min;
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.Limit#getUnit()
- */
@Override
public DefaultUnit getUnit() {
return unit;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.Limit#getMax()
- */
@Override
public Double getMax() {
return max;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.Limit#getMin()
- */
@Override
public Double getMin() {
return min;
@@ -71,19 +65,18 @@ public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements
public ValidationErrors validate(StandaloneCatalog root, ValidationErrors errors) {
if (!CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(max) &&
!CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(min) &&
- max.doubleValue() < min.doubleValue()) {
- errors.add(new ValidationError("max must be greater than min", root.getCatalogURI(), Limit.class, ""));
+ max.doubleValue() < min.doubleValue()) {
+ errors.add(new ValidationError("max must be greater than min", Limit.class, ""));
}
return errors;
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
@Override
public boolean compliesWith(double value) {
if (!CatalogSafetyInitializer.DEFAULT_NON_REQUIRED_DOUBLE_FIELD_VALUE.equals(max)) {
@@ -145,4 +138,18 @@ public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + min.hashCode();
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(unit);
+ out.writeDouble(max);
+ out.writeDouble(min);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.unit = (DefaultUnit) in.readObject();
+ this.max = in.readDouble();
+ this.min = in.readDouble();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
index c6d9a6c..9d111f6 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultMutableStaticCatalog.java
@@ -50,7 +50,7 @@ public class DefaultMutableStaticCatalog extends StandaloneCatalog implements Mu
.setPlans(input.getCurrentPlans())
.setPlanRules(input.getPlanRules())
.setPriceLists(input.getPriceLists());
- initialize(this, null);
+ initialize(this);
}
@Override
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
index d248450..ad332e6 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
@@ -22,7 +22,6 @@ import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -37,6 +36,7 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
import org.joda.time.DateTime;
import org.killbill.billing.ErrorCode;
@@ -52,15 +52,13 @@ import org.killbill.billing.catalog.api.Product;
import org.killbill.billing.catalog.api.Recurring;
import org.killbill.billing.catalog.api.StaticCatalog;
import org.killbill.billing.catalog.api.TimeUnit;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
import com.google.common.annotations.VisibleForTesting;
+@XmlRootElement(name = "plans")
@XmlAccessorType(XmlAccessType.NONE)
public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements Plan, Externalizable {
@@ -106,7 +104,6 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
// For deserialization
public DefaultPlan() {
- initialPhases = new DefaultPlanPhase[0];
}
public DefaultPlan(final StandaloneCatalog staticCatalog) {
@@ -217,8 +214,8 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (prettyName == null) {
@@ -226,11 +223,11 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
}
if (finalPhase != null) {
finalPhase.setPlan(this);
- finalPhase.initialize(catalog, sourceURI);
+ finalPhase.initialize(catalog);
}
for (final DefaultPlanPhase p : initialPhases) {
p.setPlan(this);
- p.initialize(catalog, sourceURI);
+ p.initialize(catalog);
}
if (recurringBillingMode == null) {
this.recurringBillingMode = catalog.getRecurringBillingMode();
@@ -247,15 +244,15 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
errors.add(new ValidationError(String.format("Price effective date %s is before catalog effective date '%s'",
effectiveDateForExistingSubscriptions,
catalog.getEffectiveDate()),
- catalog.getCatalogURI(), DefaultPlan.class, ""));
+ DefaultPlan.class, ""));
}
if (recurringBillingMode == null) {
- errors.add(new ValidationError(String.format("Invalid reccuring billingMode for plan '%s'", name), catalog.getCatalogURI(), DefaultPlan.class, ""));
+ errors.add(new ValidationError(String.format("Invalid recurring billingMode for plan '%s'", name), DefaultPlan.class, ""));
}
if (product == null) {
- errors.add(new ValidationError(String.format("Invalid product for plan '%s'", name), catalog.getCatalogURI(), DefaultPlan.class, ""));
+ errors.add(new ValidationError(String.format("Invalid product for plan '%s'", name), DefaultPlan.class, ""));
}
for (final DefaultPlanPhase cur : initialPhases) {
@@ -263,7 +260,7 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
if (cur.getPhaseType() == PhaseType.EVERGREEN) {
errors.add(new ValidationError(String.format("Initial Phase %s of plan %s cannot be of type %s",
cur.getName(), name, cur.getPhaseType()),
- catalog.getCatalogURI(), DefaultPlan.class, ""));
+ DefaultPlan.class, ""));
}
}
@@ -272,7 +269,7 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
if (finalPhase.getPhaseType() == PhaseType.TRIAL || finalPhase.getPhaseType() == PhaseType.DISCOUNT) {
errors.add(new ValidationError(String.format("Final Phase %s of plan %s cannot be of type %s",
finalPhase.getName(), name, finalPhase.getPhaseType()),
- catalog.getCatalogURI(), DefaultPlan.class, ""));
+ DefaultPlan.class, ""));
}
// Safety check
if (plansAllowedInBundle == null) {
@@ -413,12 +410,31 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.name = in.readUTF();
+ this.prettyName = in.readUTF();
+ this.effectiveDateForExistingSubscriptions = (Date) in.readObject();
+ this.product = (DefaultProduct) in.readObject();
+ this.recurringBillingMode = in.readBoolean() ? BillingMode.valueOf(in.readUTF()) : null;
+ this.initialPhases = (DefaultPlanPhase[]) in.readObject();
+ this.finalPhase = (DefaultPlanPhase) in.readObject();
+ this.plansAllowedInBundle = in.readInt();
+ this.priceListName = in.readUTF();
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeUTF(name);
+ oo.writeUTF(prettyName);
+ oo.writeObject(effectiveDateForExistingSubscriptions);
+ oo.writeObject(product);
+ oo.writeBoolean(recurringBillingMode != null);
+ if (recurringBillingMode != null) {
+ oo.writeUTF(recurringBillingMode.name());
+ }
+ oo.writeObject(initialPhases);
+ oo.writeObject(finalPhase);
+ oo.writeInt(plansAllowedInBundle);
+ oo.writeUTF(priceListName);
}
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
index 502fa83..9081bbc 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Arrays;
import javax.annotation.Nullable;
@@ -36,6 +39,7 @@ import org.killbill.billing.catalog.api.PhaseType;
import org.killbill.billing.catalog.api.Plan;
import org.killbill.billing.catalog.api.PlanPhase;
import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.Product;
import org.killbill.billing.catalog.api.Recurring;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.catalog.api.UsagePriceOverride;
@@ -47,7 +51,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implements PlanPhase {
+public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implements PlanPhase, Externalizable {
@XmlAttribute(required = false)
private String prettyName;
@@ -69,13 +73,15 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
private DefaultUsage[] usages;
// Not exposed in XML
- private Plan plan;
+ private String planName;
+ private Product product;
+ // Required for deserialization
public DefaultPlanPhase() {
- usages = new DefaultUsage[0];
+ this.usages = new DefaultUsage[0];
}
- public DefaultPlanPhase(final DefaultPlan parentPlan, final DefaultPlanPhase in, @Nullable final PlanPhasePriceOverride override) {
+ public DefaultPlanPhase(final Plan parentPlan, final DefaultPlanPhase in, @Nullable final PlanPhasePriceOverride override) {
this.type = in.getPhaseType();
this.duration = (DefaultDuration) in.getDuration();
this.fixed = override != null && override.getFixedPrice() != null ? new DefaultFixed((DefaultFixed) in.getFixed(), override) : (DefaultFixed) in.getFixed();
@@ -83,20 +89,20 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
this.usages = new DefaultUsage[in.getUsages().length];
for (int i = 0; i < in.getUsages().length; i++) {
final Usage curUsage = in.getUsages()[i];
- if(override != null && override.getUsagePriceOverrides()!= null) {
+ if (override != null && override.getUsagePriceOverrides() != null) {
final UsagePriceOverride usagePriceOverride = Iterables.tryFind(override.getUsagePriceOverrides(), new Predicate<UsagePriceOverride>() {
- @Override
- public boolean apply(final UsagePriceOverride input) {
- return input !=null && input.getName().equals(curUsage.getName());
- }
- }).orNull();
- usages[i] = (usagePriceOverride !=null) ? new DefaultUsage(in.getUsages()[i], usagePriceOverride, override.getCurrency()) : (DefaultUsage)curUsage;
- }
- else {
- usages[i] = (DefaultUsage)curUsage;
+ @Override
+ public boolean apply(final UsagePriceOverride input) {
+ return input != null && input.getName().equals(curUsage.getName());
+ }
+ }).orNull();
+ usages[i] = (usagePriceOverride != null) ? new DefaultUsage(in.getUsages()[i], usagePriceOverride, override.getCurrency()) : (DefaultUsage) curUsage;
+ } else {
+ usages[i] = (DefaultUsage) curUsage;
}
}
- this.plan = parentPlan;
+ this.planName = parentPlan.getName();
+ this.product = parentPlan.getProduct();
}
public static String phaseName(final String planName, final PhaseType phasetype) {
@@ -126,7 +132,7 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
}
}
// Second, check if there are limits defined at the product section.
- return plan.getProduct().compliesWithLimits(unit, value);
+ return product.compliesWithLimits(unit, value);
}
@Override
@@ -146,7 +152,7 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
@Override
public String getName() {
- return phaseName(plan.getName(), this.getPhaseType());
+ return phaseName(planName, this.getPhaseType());
}
@Override
@@ -161,15 +167,14 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
@Override
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
-
- if (plan == null) {
- errors.add(new ValidationError(String.format("Invalid plan for phase '%s'", type), catalog.getCatalogURI(), DefaultPlanPhase.class, ""));
+ if (planName == null) {
+ errors.add(new ValidationError(String.format("Invalid plan for phase '%s'", type), DefaultPlanPhase.class, ""));
}
if (fixed == null && recurring == null && usages.length == 0) {
errors.add(new ValidationError(String.format("Phase %s of plan %s need to define at least either a fixed or recurrring or usage section.",
- type.toString(), plan.getName()),
- catalog.getCatalogURI(), DefaultPlanPhase.class, type.toString()));
+ type.toString(), planName),
+ DefaultPlanPhase.class, type.toString()));
}
if (fixed != null) {
fixed.validate(catalog, errors);
@@ -184,24 +189,23 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
}
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
-
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (fixed != null) {
- fixed.initialize(root, uri);
+ fixed.initialize(root);
}
if (recurring != null) {
- recurring.initialize(root, uri);
- recurring.setPlan(plan);
+ recurring.initialize(root);
+ recurring.setPlan(planName);
recurring.setPhase(this);
}
- for (DefaultUsage usage : usages) {
- usage.initialize(root, uri);
+ for (final DefaultUsage usage : usages) {
+ usage.initialize(root);
usage.setPhase(this);
}
- duration.initialize(root, uri);
+ duration.initialize(root);
}
public DefaultPlanPhase setPrettyName(final String prettyName) {
@@ -235,7 +239,8 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
}
public DefaultPlanPhase setPlan(final Plan plan) {
- this.plan = plan;
+ this.planName = plan.getName();
+ this.product = plan.getProduct();
return this;
}
@@ -289,8 +294,38 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
sb.append(", fixed=").append(fixed);
sb.append(", recurring=").append(recurring);
sb.append(", usages=").append(Arrays.toString(usages));
- sb.append(", plan=").append(plan.getName());
+ sb.append(", plan=").append(planName);
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(prettyName != null);
+ if (prettyName != null) {
+ out.writeUTF(prettyName);
+ }
+ out.writeBoolean(type != null);
+ if (type != null) {
+ out.writeUTF(type.name());
+ }
+ out.writeObject(duration);
+ out.writeObject(fixed);
+ out.writeObject(recurring);
+ out.writeObject(usages);
+ out.writeUTF(planName);
+ out.writeObject(product);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.prettyName = in.readBoolean() ? in.readUTF() : null;
+ this.type = in.readBoolean() ? PhaseType.valueOf(in.readUTF()) : null;
+ this.duration = (DefaultDuration) in.readObject();
+ this.fixed = (DefaultFixed) in.readObject();
+ this.recurring = (DefaultRecurring) in.readObject();
+ this.usages = (DefaultUsage[]) in.readObject();
+ this.planName = in.readUTF();
+ this.product = (Product) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
index 069ccb6..66ac47e 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,11 +18,16 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.math.BigDecimal;
+import java.net.URI;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import java.math.BigDecimal;
-import java.net.URI;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.catalog.api.CurrencyValueNull;
@@ -29,7 +36,8 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements Price {
+public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements Price, Externalizable {
+
@XmlElement(required = true)
private Currency currency;
@@ -46,17 +54,11 @@ public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements
this.currency = currency;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IPrice#getCurrency()
- */
@Override
public Currency getCurrency() {
return currency;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IPrice#getValue()
- */
@Override
public BigDecimal getValue() throws CurrencyValueNull {
if (value == null) {
@@ -81,12 +83,11 @@ public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
@Override
public boolean equals(final Object o) {
if (this == o) {
@@ -114,4 +115,19 @@ public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(currency != null);
+ if (currency != null) {
+ out.writeUTF(currency.name());
+ }
+ out.writeObject(value);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.currency = in.readBoolean() ? Currency.valueOf(in.readUTF()) : null;
+ this.value = (BigDecimal) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
index 7e686b2..68ac129 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,10 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
@@ -37,7 +43,7 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implements PriceList {
+public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implements PriceList, Externalizable {
@XmlAttribute(required = true)
@XmlID
@@ -48,15 +54,15 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
@XmlElementWrapper(name = "plans", required = true)
@XmlIDREF
- @XmlElement(type=DefaultPlan.class, name = "plan", required = false)
+ @XmlElement(type = DefaultPlan.class, name = "plan", required = false)
private CatalogEntityCollection<Plan> plans;
public DefaultPriceList() {
- this.plans = new CatalogEntityCollection();
+ this.plans = new CatalogEntityCollection<Plan>();
}
public DefaultPriceList(final DefaultPlan[] plans, final String name) {
- this.plans = new CatalogEntityCollection(plans);
+ this.plans = new CatalogEntityCollection<Plan>(plans);
this.name = name;
}
@@ -65,13 +71,10 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
return plans;
}
-
public CatalogEntityCollection<Plan> getCatalogEntityCollectionPlan() {
return plans;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IPriceList#getName()
- */
+
@Override
public String getName() {
return name;
@@ -82,9 +85,6 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
return prettyName;
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.IPriceList#findPlan(org.killbill.billing.catalog.api.IProduct, org.killbill.billing.catalog.api.BillingPeriod)
- */
@Override
public Collection<Plan> findPlans(final Product product, final BillingPeriod period) {
final List<Plan> result = new ArrayList<Plan>(plans.size());
@@ -106,10 +106,9 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
return errors;
}
-
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (prettyName == null) {
@@ -159,4 +158,24 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
return "DefaultPriceList{" +
"name='" + name + '}';
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(name != null);
+ if (name != null) {
+ out.writeUTF(name);
+ }
+ out.writeBoolean(prettyName != null);
+ if (prettyName != null) {
+ out.writeUTF(prettyName);
+ }
+ out.writeObject(plans);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.name = in.readBoolean() ? in.readUTF() : null;
+ this.prettyName = in.readBoolean() ? in.readUTF() : null;
+ this.plans = (CatalogEntityCollection<Plan>) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
index 4aaf3cb..6101548 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,16 +18,19 @@
package org.killbill.billing.catalog;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
import org.killbill.billing.ErrorCode;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.CatalogApiException;
@@ -38,17 +43,16 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> implements PriceListSet {
+public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> implements PriceListSet, Externalizable {
+
@XmlElement(required = true, name = "defaultPriceList")
private DefaultPriceList defaultPricelist;
@XmlElement(required = false, name = "childPriceList")
private DefaultPriceList[] childPriceLists;
+ // Required for deserialization
public DefaultPriceListSet() {
- if (childPriceLists == null) {
- childPriceLists = new DefaultPriceList[0];
- }
}
public DefaultPriceListSet(final DefaultPriceList defaultPricelist, final DefaultPriceList[] childPriceLists) {
@@ -66,7 +70,7 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> imp
if (plans.size() == 0) {
plans = defaultPricelist.findPlans(product, period);
}
- switch(plans.size()) {
+ switch (plans.size()) {
case 0:
return null;
case 1:
@@ -99,7 +103,7 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> imp
for (final DefaultPriceList pl : childPriceLists) {
if (pl.getName().equals(PriceListSet.DEFAULT_PRICELIST_NAME)) {
errors.add(new ValidationError("Pricelists cannot use the reserved name '" + PriceListSet.DEFAULT_PRICELIST_NAME + "'",
- catalog.getCatalogURI(), DefaultPriceListSet.class, pl.getName()));
+ DefaultPriceListSet.class, pl.getName()));
}
pl.validate(catalog, errors); // and validate the individual pricelists
}
@@ -107,12 +111,11 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> imp
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
public DefaultPriceList getDefaultPricelist() {
return defaultPricelist;
}
@@ -159,4 +162,15 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> imp
return result;
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(defaultPricelist);
+ out.writeObject(childPriceLists);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.defaultPricelist = (DefaultPriceList) in.readObject();
+ this.childPriceLists = (DefaultPriceList[]) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
index 6a95b24..c9c3fd2 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.Collection;
@@ -36,7 +41,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implements Product {
+public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implements Product, Externalizable {
@XmlAttribute(required = true)
@XmlID
@@ -50,19 +55,19 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
@XmlElementWrapper(name = "included", required = false)
@XmlIDREF
- @XmlElement(type=DefaultProduct.class, name = "addonProduct", required = false)
+ @XmlElement(type = DefaultProduct.class, name = "addonProduct", required = false)
private CatalogEntityCollection<Product> included;
@XmlElementWrapper(name = "available", required = false)
@XmlIDREF
- @XmlElement(type=DefaultProduct.class, name = "addonProduct", required = false)
+ @XmlElement(type = DefaultProduct.class, name = "addonProduct", required = false)
private CatalogEntityCollection<Product> available;
@XmlElementWrapper(name = "limits", required = false)
@XmlElement(name = "limit", required = false)
private DefaultLimit[] limits;
- //Not included in XML
+ // Not included in XML
private String catalogName;
@Override
@@ -85,11 +90,11 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
return available.getEntries();
}
-
public CatalogEntityCollection<Product> getCatalogEntityCollectionAvailable() {
return available;
- };
+ }
+ // Required for deserialization
public DefaultProduct() {
this.included = new CatalogEntityCollection<Product>();
this.available = new CatalogEntityCollection<Product>();
@@ -136,11 +141,10 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
return limits;
}
-
protected Limit findLimit(String unit) {
- for (Limit limit: limits) {
- if(limit.getUnit().getName().equals(unit) ) {
- return limit;
+ for (Limit limit : limits) {
+ if (limit.getUnit().getName().equals(unit)) {
+ return limit;
}
}
return null;
@@ -155,14 +159,12 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
return l.compliesWith(value);
}
-
-
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
- for (DefaultLimit cur : limits) {
- cur.initialize(catalog, sourceURI);
+ for (final DefaultLimit cur : limits) {
+ cur.initialize(catalog);
}
if (prettyName == null) {
this.prettyName = name;
@@ -173,7 +175,7 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
@Override
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
if (catalogName == null || !catalogName.equals(catalog.getCatalogName())) {
- errors.add(new ValidationError(String.format("Invalid catalogName for product '%s'", name), catalog.getCatalogURI(), DefaultProduct.class, ""));
+ errors.add(new ValidationError(String.format("Invalid catalogName for product '%s'", name), DefaultProduct.class, ""));
}
//TODO: MDW validation: inclusion and exclusion lists can only contain addon products
@@ -186,7 +188,7 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
return this;
}
- public DefaultProduct setPrettyName(final String prettyName){
+ public DefaultProduct setPrettyName(final String prettyName) {
this.prettyName = prettyName;
return this;
}
@@ -269,4 +271,38 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
result = 31 * result + (catalogName != null ? catalogName.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(catalogName != null);
+ if (catalogName != null) {
+ out.writeUTF(catalogName);
+ }
+ out.writeBoolean(name != null);
+ if (name != null) {
+ out.writeUTF(name);
+ }
+ out.writeBoolean(prettyName != null);
+ if (prettyName != null) {
+ out.writeUTF(prettyName);
+ }
+ out.writeBoolean(category != null);
+ if (category != null) {
+ out.writeUTF(category.name());
+ }
+ out.writeObject(included);
+ out.writeObject(available);
+ out.writeObject(limits);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.catalogName = in.readBoolean() ? in.readUTF() : null;
+ this.name = in.readBoolean() ? in.readUTF() : null;
+ this.prettyName = in.readBoolean() ? in.readUTF() : null;
+ this.category = in.readBoolean() ? ProductCategory.valueOf(in.readUTF()) : null;
+ this.included = (CatalogEntityCollection<Product>) in.readObject();
+ this.available = (CatalogEntityCollection<Product>) in.readObject();
+ this.limits = (DefaultLimit[]) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
index d4c180b..ffccb7a 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,14 +17,17 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import org.killbill.billing.catalog.api.BillingPeriod;
-import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PhaseType;
import org.killbill.billing.catalog.api.PlanPhase;
import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
import org.killbill.billing.catalog.api.Recurring;
@@ -33,7 +36,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implements Recurring {
+public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implements Recurring, Externalizable {
@XmlElement(required = true)
private BillingPeriod billingPeriod;
@@ -42,10 +45,11 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
private DefaultInternationalPrice recurringPrice;
// Not exposed in xml.
- private Plan plan;
- private PlanPhase phase;
+ private String planName;
+ private PhaseType phaseType;
- public DefaultRecurring() {};
+ // Required for deserialization
+ public DefaultRecurring() {}
public DefaultRecurring(final DefaultRecurring in, final PlanPhasePriceOverride override) {
this.billingPeriod = in.getBillingPeriod();
@@ -63,11 +67,11 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
}
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (recurringPrice != null) {
- recurringPrice.initialize(root, uri);
+ recurringPrice.initialize(root);
}
}
@@ -75,31 +79,30 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
// Validation: check for nulls
- if (plan == null) {
- errors.add(new ValidationError(String.format("Invalid plan for recurring section"), catalog.getCatalogURI(), DefaultRecurring.class, ""));
+ if (planName == null) {
+ errors.add(new ValidationError("Invalid plan for recurring section", DefaultRecurring.class, ""));
}
- if (phase == null) {
- errors.add(new ValidationError(String.format("Invalid phase for recurring section"), catalog.getCatalogURI(), DefaultPlan.class, plan.getName().toString()));
+ if (phaseType == null) {
+ errors.add(new ValidationError("Invalid phase for recurring section", DefaultPlan.class, planName));
}
-
if (billingPeriod == null) {
- errors.add(new ValidationError(String.format("Recurring section of Phase %s of plan %s has a recurring price but no billing period", phase.getPhaseType().toString(), plan.getName()),
- catalog.getCatalogURI(), DefaultPlanPhase.class, phase.getPhaseType().toString()));
+ errors.add(new ValidationError(String.format("Recurring section of Phase %s of plan %s has a recurring price but no billing period", phaseType.toString(), planName),
+ DefaultPlanPhase.class, phaseType.toString()));
}
// Validation: if there is a recurring price there must be a billing period
if ((recurringPrice != null) && (billingPeriod == null || billingPeriod == BillingPeriod.NO_BILLING_PERIOD)) {
- errors.add(new ValidationError(String.format("Recurring section of Phase %s of plan %s has a recurring price but no billing period", phase.getPhaseType().toString(), plan.getName()),
- catalog.getCatalogURI(), DefaultPlanPhase.class, phase.getPhaseType().toString()));
+ errors.add(new ValidationError(String.format("Recurring section of Phase %s of plan %s has a recurring price but no billing period", phaseType.toString(), planName),
+ DefaultPlanPhase.class, phaseType.toString()));
}
// Validation: if there is no recurring price there should be no billing period
if ((recurringPrice == null) && billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
errors.add(new ValidationError(String.format("Recurring section of Phase %s of plan %s has no recurring price but does have a billing period. The billing period should be set to '%s'",
- phase.getPhaseType().toString(), plan.getName(), BillingPeriod.NO_BILLING_PERIOD),
- catalog.getCatalogURI(), DefaultPlanPhase.class, phase.getPhaseType().toString()));
+ phaseType.toString(), planName, BillingPeriod.NO_BILLING_PERIOD),
+ DefaultPlanPhase.class, phaseType.toString()));
}
return errors;
}
@@ -114,13 +117,13 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
return this;
}
- public DefaultRecurring setPlan(final Plan plan) {
- this.plan = plan;
+ public DefaultRecurring setPlan(final String planName) {
+ this.planName = planName;
return this;
}
public DefaultRecurring setPhase(final PlanPhase phase) {
- this.phase = phase;
+ this.phaseType = phase.getPhaseType();
return this;
}
@@ -151,4 +154,26 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
result = 31 * result + (recurringPrice != null ? recurringPrice.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(billingPeriod != null);
+ if (billingPeriod != null) {
+ out.writeUTF(billingPeriod.name());
+ }
+ out.writeObject(recurringPrice);
+ out.writeUTF(planName);
+ out.writeBoolean(phaseType != null);
+ if (phaseType != null) {
+ out.writeUTF(phaseType.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.billingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.recurringPrice = (DefaultInternationalPrice) in.readObject();
+ this.planName = in.readUTF();
+ this.phaseType = in.readBoolean() ? PhaseType.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
index e6c3bf3..aee9962 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,7 +17,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Arrays;
import javax.xml.bind.annotation.XmlAccessType;
@@ -41,10 +44,8 @@ import org.killbill.xmlloader.ValidationErrors;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
-
-
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements Tier {
+public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements Tier, Externalizable {
@XmlElementWrapper(name = "limits", required = false)
@XmlElement(name = "limit", required = false)
@@ -67,17 +68,16 @@ public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements
private UsageType usageType;
private PlanPhase phase;
+ // Required for deserialization
public DefaultTier() {
- limits = new DefaultLimit[0];
- blocks = new DefaultTieredBlock[0];
}
public DefaultTier(Tier in, TierPriceOverride override, Currency currency) {
- this.limits = (DefaultLimit[])in.getLimits();
+ this.limits = (DefaultLimit[]) in.getLimits();
this.blocks = new DefaultTieredBlock[in.getTieredBlocks().length];
for (int i = 0; i < in.getTieredBlocks().length; i++) {
- if(override != null && override.getTieredBlockPriceOverrides() != null) {
+ if (override != null && override.getTieredBlockPriceOverrides() != null) {
final TieredBlock curTieredBlock = in.getTieredBlocks()[i];
final TieredBlockPriceOverride overriddenTierBlock = Iterables.tryFind(override.getTieredBlockPriceOverrides(), new Predicate<TieredBlockPriceOverride>() {
@Override
@@ -89,9 +89,8 @@ public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements
}).orNull();
blocks[i] = (overriddenTierBlock != null) ? new DefaultTieredBlock(in.getTieredBlocks()[i], overriddenTierBlock, currency) :
- (DefaultTieredBlock) in.getTieredBlocks()[i];
- }
- else {
+ (DefaultTieredBlock) in.getTieredBlocks()[i];
+ } else {
blocks[i] = (DefaultTieredBlock) in.getTieredBlocks()[i];
}
}
@@ -154,30 +153,28 @@ public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
if (billingMode == BillingMode.IN_ARREAR && usageType == UsageType.CAPACITY && limits.length == 0) {
errors.add(new ValidationError(String.format("Usage [IN_ARREAR CAPACITY] section of phase %s needs to define some limits",
- phase.getName()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.getName()), DefaultUsage.class, ""));
}
if (billingMode == BillingMode.IN_ARREAR && usageType == UsageType.CONSUMABLE && blocks.length == 0) {
errors.add(new ValidationError(String.format("Usage [IN_ARREAR CONSUMABLE] section of phase %s needs to define some blocks",
- phase.getName()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.getName()), DefaultUsage.class, ""));
}
validateCollection(catalog, errors, limits);
return errors;
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
for (DefaultLimit cur : limits) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (DefaultBlock cur : blocks) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
}
-
-
@Override
public boolean equals(final Object o) {
if (this == o) {
@@ -222,4 +219,20 @@ public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + (recurringPrice != null ? recurringPrice.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(limits);
+ out.writeObject(blocks);
+ out.writeObject(fixedPrice);
+ out.writeObject(recurringPrice);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.limits = (DefaultLimit[]) in.readObject();
+ this.blocks = (DefaultTieredBlock[]) in.readObject();
+ this.fixedPrice = (DefaultInternationalPrice) in.readObject();
+ this.recurringPrice = (DefaultInternationalPrice) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTieredBlock.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTieredBlock.java
index aa661ab..60abfaf 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTieredBlock.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTieredBlock.java
@@ -1,7 +1,8 @@
/*
- * Copyright 2014 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +17,11 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@@ -26,7 +32,7 @@ import org.killbill.billing.catalog.api.TieredBlock;
import org.killbill.billing.catalog.api.TieredBlockPriceOverride;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultTieredBlock extends DefaultBlock implements TieredBlock {
+public class DefaultTieredBlock extends DefaultBlock implements TieredBlock, Externalizable {
@XmlElement(required = true)
private Double max;
@@ -41,11 +47,12 @@ public class DefaultTieredBlock extends DefaultBlock implements TieredBlock {
return this;
}
+ // Required for deserialization
public DefaultTieredBlock() {
}
public DefaultTieredBlock(TieredBlock in, TieredBlockPriceOverride override, Currency currency) {
- super((DefaultUnit)in.getUnit(), in.getSize(),(DefaultInternationalPrice)in.getPrice(), override.getPrice(),currency);
+ super((DefaultUnit) in.getUnit(), in.getSize(), (DefaultInternationalPrice) in.getPrice(), override.getPrice(), currency);
this.max = in.getMax();
}
@@ -87,4 +94,16 @@ public class DefaultTieredBlock extends DefaultBlock implements TieredBlock {
result = 31 * result + (max != null ? max.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeDouble(max);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.max = in.readDouble();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
index b3ad882..6bd7330 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
@@ -1,7 +1,9 @@
/*
- * Copyright 2010-2011 Ning, Inc.
+ * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -28,7 +33,7 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements Unit {
+public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements Unit, Externalizable {
@XmlAttribute(required = true)
@XmlID
@@ -37,9 +42,6 @@ public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements
@XmlAttribute(required = false)
private String prettyName;
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.Unit#getName()
- */
@Override
public String getName() {
return name;
@@ -55,10 +57,13 @@ public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements
return errors;
}
+ // Required for deserialization
+ public DefaultUnit() {
+ }
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (prettyName == null) {
this.prettyName = name;
@@ -97,4 +102,16 @@ public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeUTF(name);
+ out.writeUTF(prettyName);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.name = in.readUTF();
+ this.prettyName = in.readUTF();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
index ce2a92a..86a8376 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,7 +17,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.List;
@@ -36,14 +39,13 @@ import org.killbill.billing.catalog.api.InternationalPrice;
import org.killbill.billing.catalog.api.Limit;
import org.killbill.billing.catalog.api.PlanPhase;
import org.killbill.billing.catalog.api.Tier;
+import org.killbill.billing.catalog.api.TierBlockPolicy;
import org.killbill.billing.catalog.api.TierPriceOverride;
import org.killbill.billing.catalog.api.TieredBlock;
import org.killbill.billing.catalog.api.TieredBlockPriceOverride;
import org.killbill.billing.catalog.api.Usage;
import org.killbill.billing.catalog.api.UsagePriceOverride;
import org.killbill.billing.catalog.api.UsageType;
-import org.killbill.billing.catalog.api.TierBlockPolicy;
-
import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@@ -51,9 +53,8 @@ import org.killbill.xmlloader.ValidationErrors;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
-
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements Usage {
+public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements Usage, Externalizable {
@XmlAttribute(required = true)
@XmlID
@@ -97,54 +98,51 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
// Not exposed in xml.
private PlanPhase phase;
+ // Required for deserialization
public DefaultUsage() {
- limits = new DefaultLimit[0];
- blocks = new DefaultBlock[0];
- tiers = new DefaultTier[0];
}
public DefaultUsage(final Usage in, UsagePriceOverride override, Currency currency) {
- this.name = in.getName();
- this.usageType = in.getUsageType();
- this.tierBlockPolicy = in.getTierBlockPolicy();
- this.billingPeriod = in.getBillingPeriod();
- this.billingMode = in.getBillingMode();
- this.limits = (DefaultLimit[]) in.getLimits();
- this.blocks = (DefaultBlock[]) in.getBlocks();
- this.tiers = new DefaultTier[in.getTiers().length];
-
- for (int i = 0; i < in.getTiers().length; i++) {
- if(override != null && override.getTierPriceOverrides()!=null) {
- final TieredBlock[] curTieredBlocks = in.getTiers()[i].getTieredBlocks();
-
- final TierPriceOverride overriddenTier = Iterables.tryFind(override.getTierPriceOverrides(), new Predicate<TierPriceOverride>() {
- @Override
- public boolean apply(final TierPriceOverride input) {
-
- if(input !=null) {
- final List<TieredBlockPriceOverride> blockPriceOverrides = input.getTieredBlockPriceOverrides();
- for (TieredBlockPriceOverride blockDef : blockPriceOverrides) {
- String unitName = blockDef.getUnitName();
- Double max = blockDef.getMax();
- Double size = blockDef.getSize();
- for (TieredBlock curTieredBlock : curTieredBlocks) {
- if (unitName.equals(curTieredBlock.getUnit().getName()) &&
- Double.compare(size, curTieredBlock.getSize()) == 0 &&
- Double.compare(max, curTieredBlock.getMax()) == 0) {
- return true;
- }
- }
- }
+ this.name = in.getName();
+ this.usageType = in.getUsageType();
+ this.tierBlockPolicy = in.getTierBlockPolicy();
+ this.billingPeriod = in.getBillingPeriod();
+ this.billingMode = in.getBillingMode();
+ this.limits = (DefaultLimit[]) in.getLimits();
+ this.blocks = (DefaultBlock[]) in.getBlocks();
+ this.tiers = new DefaultTier[in.getTiers().length];
+
+ for (int i = 0; i < in.getTiers().length; i++) {
+ if (override != null && override.getTierPriceOverrides() != null) {
+ final TieredBlock[] curTieredBlocks = in.getTiers()[i].getTieredBlocks();
+
+ final TierPriceOverride overriddenTier = Iterables.tryFind(override.getTierPriceOverrides(), new Predicate<TierPriceOverride>() {
+ @Override
+ public boolean apply(final TierPriceOverride input) {
+
+ if (input != null) {
+ final List<TieredBlockPriceOverride> blockPriceOverrides = input.getTieredBlockPriceOverrides();
+ for (TieredBlockPriceOverride blockDef : blockPriceOverrides) {
+ String unitName = blockDef.getUnitName();
+ Double max = blockDef.getMax();
+ Double size = blockDef.getSize();
+ for (TieredBlock curTieredBlock : curTieredBlocks) {
+ if (unitName.equals(curTieredBlock.getUnit().getName()) &&
+ Double.compare(size, curTieredBlock.getSize()) == 0 &&
+ Double.compare(max, curTieredBlock.getMax()) == 0) {
+ return true;
+ }
+ }
}
- return false;
- }
- }).orNull();
- tiers[i] = (overriddenTier != null) ? new DefaultTier(in.getTiers()[i], overriddenTier, currency) : (DefaultTier)in.getTiers()[i] ;
- }
- else {
- tiers[i] = (DefaultTier) in.getTiers()[i];
- }
- }
+ }
+ return false;
+ }
+ }).orNull();
+ tiers[i] = (overriddenTier != null) ? new DefaultTier(in.getTiers()[i], overriddenTier, currency) : (DefaultTier) in.getTiers()[i];
+ } else {
+ tiers[i] = (DefaultTier) in.getTiers()[i];
+ }
+ }
}
@Override
@@ -215,16 +213,16 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
if (billingMode == BillingMode.IN_ADVANCE && usageType == UsageType.CAPACITY && limits.length == 0) {
errors.add(new ValidationError(String.format("Usage [IN_ADVANCE CAPACITY] section of phase %s needs to define some limits",
- phase.toString()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.toString()), DefaultUsage.class, ""));
}
if (billingMode == BillingMode.IN_ADVANCE && usageType == UsageType.CONSUMABLE && blocks.length == 0) {
errors.add(new ValidationError(String.format("Usage [IN_ADVANCE CONSUMABLE] section of phase %s needs to define some blocks",
- phase.toString()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.toString()), DefaultUsage.class, ""));
}
if (billingMode == BillingMode.IN_ARREAR && tiers.length == 0) {
errors.add(new ValidationError(String.format("Usage [IN_ARREAR] section of phase %s needs to define some tiers",
- phase.toString()), catalog.getCatalogURI(), DefaultUsage.class, ""));
+ phase.toString()), DefaultUsage.class, ""));
}
validateCollection(catalog, errors, limits);
validateCollection(catalog, errors, tiers);
@@ -232,8 +230,8 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
}
@Override
- public void initialize(final StandaloneCatalog root, final URI uri) {
- super.initialize(root, uri);
+ public void initialize(final StandaloneCatalog root) {
+ super.initialize(root);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
if (prettyName == null) {
@@ -241,15 +239,15 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
}
for (DefaultLimit limit : limits) {
- limit.initialize(root, uri);
+ limit.initialize(root);
}
for (DefaultBlock block : blocks) {
- block.initialize(root, uri);
+ block.initialize(root);
block.setPhase(phase);
}
for (DefaultTier tier : tiers) {
- tier.initialize(root, uri);
+ tier.initialize(root);
tier.setPhase(phase);
}
}
@@ -380,4 +378,46 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
result = 31 * result + (recurringPrice != null ? recurringPrice.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeUTF(name);
+ out.writeUTF(prettyName);
+ out.writeBoolean(billingMode != null);
+ if (billingMode != null) {
+ out.writeUTF(billingMode.name());
+ }
+ out.writeBoolean(usageType != null);
+ if (usageType != null) {
+ out.writeUTF(usageType.name());
+ }
+ out.writeBoolean(tierBlockPolicy != null);
+ if (tierBlockPolicy != null) {
+ out.writeUTF(tierBlockPolicy.name());
+ }
+ out.writeBoolean(billingPeriod != null);
+ if (billingPeriod != null) {
+ out.writeUTF(billingPeriod.name());
+ }
+ out.writeObject(limits);
+ out.writeObject(blocks);
+ out.writeObject(tiers);
+ out.writeObject(fixedPrice);
+ out.writeObject(recurringPrice);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.name = in.readUTF();
+ this.prettyName = in.readUTF();
+ this.billingMode = in.readBoolean() ? BillingMode.valueOf(in.readUTF()) : null;
+ this.usageType = in.readBoolean() ? UsageType.valueOf(in.readUTF()) : null;
+ this.tierBlockPolicy = in.readBoolean() ? TierBlockPolicy.valueOf(in.readUTF()) : null;
+ this.billingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.limits = (DefaultLimit[]) in.readObject();
+ this.blocks = (DefaultBlock[]) in.readObject();
+ this.tiers = (DefaultTier[]) in.readObject();
+ this.fixedPrice = (DefaultInternationalPrice) in.readObject();
+ this.recurringPrice = (DefaultInternationalPrice) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
index 83e485b..5edf0dc 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultVersionedCatalog.java
@@ -22,7 +22,6 @@ import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -43,7 +42,6 @@ import org.joda.time.DateTime;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.catalog.api.BillingActionPolicy;
import org.killbill.billing.catalog.api.BillingAlignment;
-import org.killbill.billing.catalog.api.Catalog;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.catalog.api.Listing;
@@ -60,9 +58,6 @@ import org.killbill.billing.catalog.api.Product;
import org.killbill.billing.catalog.api.StaticCatalog;
import org.killbill.billing.catalog.api.Unit;
import org.killbill.billing.catalog.api.VersionedCatalog;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
import org.killbill.clock.Clock;
import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationError;
@@ -74,7 +69,7 @@ public class DefaultVersionedCatalog extends ValidatingConfig<DefaultVersionedCa
private static final long serialVersionUID = 3181874902672322725L;
- private final Clock clock;
+ private Clock clock;
@XmlElementWrapper(name = "versions", required = true)
@XmlElement(name = "version", required = true)
@@ -335,13 +330,13 @@ public class DefaultVersionedCatalog extends ValidatingConfig<DefaultVersionedCa
}
@Override
- public void initialize(final DefaultVersionedCatalog catalog, final URI sourceURI) {
+ public void initialize(final DefaultVersionedCatalog catalog) {
//
// Initialization is performed first on each StandaloneCatalog (XMLLoader#initializeAndValidate)
// and then later on the VersionedCatalog, so we only initialize and validate VersionedCatalog
// *without** recursively through each StandaloneCatalog
//
- super.initialize(catalog, sourceURI);
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
@@ -352,13 +347,13 @@ public class DefaultVersionedCatalog extends ValidatingConfig<DefaultVersionedCa
for (final StandaloneCatalog c : versions) {
if (effectiveDates.contains(c.getEffectiveDate())) {
errors.add(new ValidationError(String.format("Catalog effective date '%s' already exists for a previous version", c.getEffectiveDate()),
- c.getCatalogURI(), VersionedCatalog.class, ""));
+ VersionedCatalog.class, ""));
} else {
effectiveDates.add(c.getEffectiveDate());
}
if (!c.getCatalogName().equals(catalogName)) {
errors.add(new ValidationError(String.format("Catalog name '%s' is not consistent across versions ", c.getCatalogName()),
- c.getCatalogURI(), VersionedCatalog.class, ""));
+ VersionedCatalog.class, ""));
}
errors.addAll(c.validate(c, errors));
}
@@ -459,13 +454,48 @@ public class DefaultVersionedCatalog extends ValidatingConfig<DefaultVersionedCa
}
@Override
- public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.catalogName = in.readBoolean() ? in.readUTF() : null;
+ this.versions.addAll((Collection<? extends StandaloneCatalog>) in.readObject());
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeBoolean(catalogName != null);
+ if (catalogName != null) {
+ // Can be null for placeholder XML
+ oo.writeUTF(catalogName);
+ }
+ oo.writeObject(versions);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultVersionedCatalog that = (DefaultVersionedCatalog) o;
+
+ if (versions != null ? !versions.equals(that.versions) : that.versions != null) {
+ return false;
+ }
+ return catalogName != null ? catalogName.equals(that.catalogName) : that.catalogName == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = versions != null ? versions.hashCode() : 0;
+ result = 31 * result + (catalogName != null ? catalogName.hashCode() : 0);
+ return result;
+ }
+
+ public void initialize(final Clock clock, final DefaultVersionedCatalog tenantCatalog) {
+ this.clock = clock;
+ initialize(tenantCatalog);
}
private static class CatalogPlanEntry {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/glue/CatalogModule.java b/catalog/src/main/java/org/killbill/billing/catalog/glue/CatalogModule.java
index f97f26d..b7ec777 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/glue/CatalogModule.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/glue/CatalogModule.java
@@ -26,8 +26,8 @@ import org.killbill.billing.catalog.api.DefaultCatalogInternalApi;
import org.killbill.billing.catalog.api.user.DefaultCatalogUserApi;
import org.killbill.billing.catalog.caching.CatalogCache;
import org.killbill.billing.catalog.caching.CatalogCacheInvalidationCallback;
-import org.killbill.billing.catalog.caching.EhCacheCatalogCache;
-import org.killbill.billing.catalog.caching.EhCacheOverriddenPlanCache;
+import org.killbill.billing.catalog.caching.DefaultCatalogCache;
+import org.killbill.billing.catalog.caching.DefaultOverriddenPlanCache;
import org.killbill.billing.catalog.caching.OverriddenPlanCache;
import org.killbill.billing.catalog.dao.CatalogOverrideDao;
import org.killbill.billing.catalog.dao.DefaultCatalogOverrideDao;
@@ -79,10 +79,10 @@ public class CatalogModule extends KillBillModule {
}
public void installCatalogConfigCache() {
- bind(CatalogCache.class).to(EhCacheCatalogCache.class).asEagerSingleton();
+ bind(CatalogCache.class).to(DefaultCatalogCache.class).asEagerSingleton();
bind(CacheInvalidationCallback.class).annotatedWith(Names.named(CATALOG_INVALIDATION_CALLBACK)).to(CatalogCacheInvalidationCallback.class).asEagerSingleton();
- bind(OverriddenPlanCache.class).to(EhCacheOverriddenPlanCache.class).asEagerSingleton();
+ bind(OverriddenPlanCache.class).to(DefaultOverriddenPlanCache.class).asEagerSingleton();
}
protected void installCatalogPluginApi() {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
index 86085c2..103c45b 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/io/VersionedCatalogLoader.java
@@ -87,7 +87,7 @@ public class VersionedCatalogLoader implements CatalogLoader {
result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride, InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID, internalCallContextFactory));
}
// Perform initialization and validation for VersionedCatalog
- XMLLoader.initializeAndValidate(new URI(uriString), result);
+ XMLLoader.initializeAndValidate(result);
return result;
} catch (final ValidationException e) {
logger.warn("Failed to load default catalog", e);
@@ -121,13 +121,13 @@ public class VersionedCatalogLoader implements CatalogLoader {
uri = new URI("/tenantCatalog");
for (final String cur : catalogXMLs) {
final InputStream curCatalogStream = new ByteArrayInputStream(cur.getBytes());
- final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(uri, curCatalogStream, StandaloneCatalog.class);
+ final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(curCatalogStream, StandaloneCatalog.class);
if (!filterTemplateCatalog || !catalog.isTemplateCatalog()) {
result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride, tenantRecordId, internalCallContextFactory));
}
}
// Perform initialization and validation for VersionedCatalog
- XMLLoader.initializeAndValidate(uri, result);
+ XMLLoader.initializeAndValidate(result);
return result;
} catch (final ValidationException e) {
logger.warn("Failed to load catalog for tenantRecordId='{}'", tenantRecordId, e);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
index 56ae3fb..518bee9 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/override/DefaultPriceOverride.java
@@ -17,8 +17,8 @@
package org.killbill.billing.catalog.override;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
@@ -40,7 +40,6 @@ import org.killbill.billing.catalog.api.Plan;
import org.killbill.billing.catalog.api.PlanPhase;
import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
-import org.killbill.billing.catalog.api.StaticCatalog;
import org.killbill.billing.catalog.api.Tier;
import org.killbill.billing.catalog.api.TierPriceOverride;
import org.killbill.billing.catalog.api.TieredBlock;
@@ -72,7 +71,6 @@ public class DefaultPriceOverride implements PriceOverride {
@Override
public DefaultPlan getOrCreateOverriddenPlan(final StandaloneCatalog standaloneCatalog, final Plan parentPlan, final DateTime catalogEffectiveDate, final List<PlanPhasePriceOverride> overrides, @Nullable final InternalCallContext context) throws CatalogApiException {
-
final PlanPhasePriceOverride[] resolvedOverride = new PlanPhasePriceOverride[parentPlan.getAllPhases().length];
int index = 0;
for (final PlanPhase curPhase : parentPlan.getAllPhases()) {
@@ -92,12 +90,11 @@ public class DefaultPriceOverride implements PriceOverride {
}
}).orNull();
- if(curOverride != null) {
+ if (curOverride != null) {
List<UsagePriceOverride> resolvedUsageOverrides = getResolvedUsageOverrides(curPhase.getUsages(), curOverride.getUsagePriceOverrides());
resolvedOverride[index++] = new DefaultPlanPhasePriceOverride(curPhase.getName(), curOverride.getCurrency(), curOverride.getFixedPrice(),
- curOverride.getRecurringPrice(), resolvedUsageOverrides);
- }
- else {
+ curOverride.getRecurringPrice(), resolvedUsageOverrides);
+ } else {
resolvedOverride[index++] = null;
}
}
@@ -128,14 +125,14 @@ public class DefaultPriceOverride implements PriceOverride {
}
final DefaultPlan result = new DefaultPlan(standaloneCatalog, planName, (DefaultPlan) parentPlan, resolvedOverride);
- result.initialize(standaloneCatalog, standaloneCatalog.getCatalogURI());
+ result.initialize(standaloneCatalog);
if (context == null) {
overriddenPlanCache.addDryRunPlan(planName, result);
}
return result;
}
- public List<UsagePriceOverride> getResolvedUsageOverrides(Usage[] usages, List<UsagePriceOverride> usagePriceOverrides) throws CatalogApiException{
+ public List<UsagePriceOverride> getResolvedUsageOverrides(Usage[] usages, List<UsagePriceOverride> usagePriceOverrides) throws CatalogApiException {
List<UsagePriceOverride> resolvedUsageOverrides = new ArrayList<UsagePriceOverride>();
for (final Usage curUsage : usages) {
@@ -145,18 +142,18 @@ public class DefaultPriceOverride implements PriceOverride {
return input.getName() != null && input.getName().equals(curUsage.getName());
}
}).orNull();
- if(curOverride != null) {
- List<TierPriceOverride> tierPriceOverrides = getResolvedTierOverrides(curUsage.getTiers(), curOverride.getTierPriceOverrides());
- resolvedUsageOverrides.add(new DefaultUsagePriceOverride(curUsage.getName(), curUsage.getUsageType(),tierPriceOverrides));
- } else {
- resolvedUsageOverrides.add(null);
- }
+ if (curOverride != null) {
+ List<TierPriceOverride> tierPriceOverrides = getResolvedTierOverrides(curUsage.getTiers(), curOverride.getTierPriceOverrides());
+ resolvedUsageOverrides.add(new DefaultUsagePriceOverride(curUsage.getName(), curUsage.getUsageType(), tierPriceOverrides));
+ } else {
+ resolvedUsageOverrides.add(null);
+ }
}
return resolvedUsageOverrides;
}
- public List<TierPriceOverride> getResolvedTierOverrides(Tier[] tiers, List<TierPriceOverride> tierPriceOverrides) throws CatalogApiException{
+ public List<TierPriceOverride> getResolvedTierOverrides(Tier[] tiers, List<TierPriceOverride> tierPriceOverrides) throws CatalogApiException {
List<TierPriceOverride> resolvedTierOverrides = new ArrayList<TierPriceOverride>();
for (final Tier curTier : tiers) {
@@ -173,8 +170,8 @@ public class DefaultPriceOverride implements PriceOverride {
for (int i = 0; i < curTier.getTieredBlocks().length; i++) {
TieredBlock curTieredBlock = curTier.getTieredBlocks()[i];
if (unitName.equals(curTieredBlock.getUnit().getName()) &&
- Double.compare(size, curTieredBlock.getSize()) == 0 &&
- Double.compare(max, curTieredBlock.getMax()) == 0) {
+ Double.compare(size, curTieredBlock.getSize()) == 0 &&
+ Double.compare(max, curTieredBlock.getMax()) == 0) {
return true;
}
}
@@ -184,12 +181,11 @@ public class DefaultPriceOverride implements PriceOverride {
}
}).orNull();
- if(curOverride != null) {
+ if (curOverride != null) {
List<TieredBlockPriceOverride> tieredBlockPriceOverrides = getResolvedTieredBlockPriceOverrides(curTier.getTieredBlocks(),
- curOverride.getTieredBlockPriceOverrides());
+ curOverride.getTieredBlockPriceOverrides());
resolvedTierOverrides.add(new DefaultTierPriceOverride(tieredBlockPriceOverrides));
- }
- else {
+ } else {
resolvedTierOverrides.add(null);
}
}
@@ -206,25 +202,23 @@ public class DefaultPriceOverride implements PriceOverride {
@Override
public boolean apply(final TieredBlockPriceOverride input) {
return input.getUnitName() != null && input.getSize() != null && input.getMax() != null &&
- (input.getUnitName().equals(curTieredBlock.getUnit().getName()) &&
- Double.compare(input.getSize(), curTieredBlock.getSize()) == 0 &&
- Double.compare(input.getMax(), curTieredBlock.getMax()) == 0);
+ (input.getUnitName().equals(curTieredBlock.getUnit().getName()) &&
+ Double.compare(input.getSize(), curTieredBlock.getSize()) == 0 &&
+ Double.compare(input.getMax(), curTieredBlock.getMax()) == 0);
}
}).orNull();
- if(curOverride != null) {
- resolvedTieredBlockPriceOverrides.add(new DefaultTieredBlockPriceOverride(curTieredBlock.getUnit().getName(), curOverride.getSize(), curOverride.getPrice(), curOverride.getCurrency(), curOverride.getMax())) ;
- }
- else {
+ if (curOverride != null) {
+ resolvedTieredBlockPriceOverrides.add(new DefaultTieredBlockPriceOverride(curTieredBlock.getUnit().getName(), curOverride.getSize(), curOverride.getPrice(), curOverride.getCurrency(), curOverride.getMax()));
+ } else {
resolvedTieredBlockPriceOverrides.add(null);
}
}
return resolvedTieredBlockPriceOverrides;
}
-
@Override
- public DefaultPlan getOverriddenPlan(final String planName, final StaticCatalog catalog, final InternalTenantContext context) throws CatalogApiException {
+ public DefaultPlan getOverriddenPlan(final String planName, final StandaloneCatalog catalog, final InternalTenantContext context) throws CatalogApiException {
return overriddenPlanCache.getOverriddenPlan(planName, catalog, context);
}
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
index cb81b5b..da47bdc 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/override/PriceOverride.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -24,16 +24,13 @@ import org.killbill.billing.callcontext.InternalCallContext;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.DefaultPlan;
import org.killbill.billing.catalog.StandaloneCatalog;
-import org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Plan;
import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
-import org.killbill.billing.catalog.api.StaticCatalog;
public interface PriceOverride {
DefaultPlan getOrCreateOverriddenPlan(final StandaloneCatalog catalog, final Plan parentPlan, final DateTime catalogEffectiveDate, final List<PlanPhasePriceOverride> overrides, final InternalCallContext context) throws CatalogApiException;
-
- DefaultPlan getOverriddenPlan(final String planName, final StaticCatalog catalog, final InternalTenantContext context) throws CatalogApiException;
+ DefaultPlan getOverriddenPlan(final String planName, final StandaloneCatalog catalog, final InternalTenantContext context) throws CatalogApiException;
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
index e6cedcd..c03ea8e 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
@@ -103,7 +103,7 @@ public class StandaloneCatalogMapper {
this.tmpDefaultPriceListMap = new HashMap<String, DefaultPriceList>();
}
- public StandaloneCatalog toStandaloneCatalog(final StandalonePluginCatalog pluginCatalog, @Nullable URI catalogURI) {
+ public StandaloneCatalog toStandaloneCatalog(final StandalonePluginCatalog pluginCatalog) {
final StandaloneCatalog result = new StandaloneCatalog();
result.setCatalogName(catalogName);
@@ -121,7 +121,7 @@ public class StandaloneCatalogMapper {
((DefaultProduct) target).setIncluded(toFilteredDefaultProduct(cur.getIncluded()));
}
}
- result.initialize(result, catalogURI);
+ result.initialize(result);
return result;
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java b/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
index bdbab8a..dd365d4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/plugin/VersionedCatalogMapper.java
@@ -54,7 +54,7 @@ public class VersionedCatalogMapper {
private StandaloneCatalogWithPriceOverride toStandaloneCatalogWithPriceOverride(final VersionedPluginCatalog pluginCatalog, final StandalonePluginCatalog input, final InternalTenantContext internalTenantContext) {
final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(pluginCatalog.getCatalogName());
- final StandaloneCatalog catalog = mapper.toStandaloneCatalog(input, null);
+ final StandaloneCatalog catalog = mapper.toStandaloneCatalog(input);
final StandaloneCatalogWithPriceOverride result = new StandaloneCatalogWithPriceOverride(catalog, priceOverride, internalTenantContext.getTenantRecordId(), internalCallContextFactory);
return result;
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java b/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
index 08571ef..3005ca4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
@@ -16,8 +16,6 @@
package org.killbill.billing.catalog;
-import java.net.URI;
-
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -40,15 +38,15 @@ public class PriceListDefault extends DefaultPriceList {
super.validate(catalog, errors);
if (!getName().equals(PriceListSet.DEFAULT_PRICELIST_NAME)) {
errors.add(new ValidationError("The name of the default pricelist must be 'DEFAULT'",
- catalog.getCatalogURI(), DefaultPriceList.class, getName()));
+ DefaultPriceList.class, getName()));
}
return errors;
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
@@ -57,5 +55,4 @@ public class PriceListDefault extends DefaultPriceList {
return PriceListSet.DEFAULT_PRICELIST_NAME;
}
-
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
index 99e23d4..933a578 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
@@ -95,8 +95,8 @@ public abstract class DefaultCase<T> extends ValidatingConfig<StandaloneCatalog>
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseBillingAlignment.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseBillingAlignment.java
index 31e56fc..9efc4b9 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseBillingAlignment.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseBillingAlignment.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,13 +18,18 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import org.killbill.billing.catalog.api.BillingAlignment;
import org.killbill.billing.catalog.api.PhaseType;
import org.killbill.billing.catalog.api.rules.CaseBillingAlignment;
-public class DefaultCaseBillingAlignment extends DefaultCasePhase<BillingAlignment> implements CaseBillingAlignment {
+public class DefaultCaseBillingAlignment extends DefaultCasePhase<BillingAlignment> implements CaseBillingAlignment, Externalizable {
@XmlElement(required = true)
private BillingAlignment alignment;
@@ -87,4 +94,18 @@ public class DefaultCaseBillingAlignment extends DefaultCasePhase<BillingAlignme
'}';
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(alignment != null);
+ if (alignment != null) {
+ out.writeUTF(alignment.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.alignment = in.readBoolean() ? BillingAlignment.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCancelPolicy.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCancelPolicy.java
index 2d21e94..23c000f 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCancelPolicy.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCancelPolicy.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,11 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import org.killbill.billing.catalog.StandaloneCatalog;
@@ -25,7 +32,7 @@ import org.killbill.billing.catalog.api.rules.CaseCancelPolicy;
import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
-public class DefaultCaseCancelPolicy extends DefaultCasePhase<BillingActionPolicy> implements CaseCancelPolicy {
+public class DefaultCaseCancelPolicy extends DefaultCasePhase<BillingActionPolicy> implements CaseCancelPolicy, Externalizable {
@XmlElement(required = true)
private BillingActionPolicy policy;
@@ -42,14 +49,13 @@ public class DefaultCaseCancelPolicy extends DefaultCasePhase<BillingActionPolic
@Override
public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
- if (policy == BillingActionPolicy.START_OF_TERM) {
+ if (policy == BillingActionPolicy.START_OF_TERM) {
errors.add(new ValidationError("Default catalog START_OF_TERM has not been implemented, such policy can be used during cancellation by overriding policy",
- catalog.getCatalogURI(), DefaultCaseCancelPolicy.class, ""));
+ DefaultCaseCancelPolicy.class, ""));
}
return errors;
}
-
@Override
public BillingActionPolicy getBillingActionPolicy() {
return policy;
@@ -100,4 +106,18 @@ public class DefaultCaseCancelPolicy extends DefaultCasePhase<BillingActionPolic
'}';
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(policy != null);
+ if (policy != null) {
+ out.writeUTF(policy.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.policy = in.readBoolean() ? BillingActionPolicy.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
index d522bff..99f80a5 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,10 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.net.URI;
import javax.xml.bind.annotation.XmlAccessType;
@@ -42,7 +48,7 @@ import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCatalog> implements CaseChange {
+public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCatalog> implements CaseChange, Externalizable {
@XmlElement(required = false)
protected PhaseType phaseType;
@@ -80,8 +86,6 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
public T getResult(final PlanPhaseSpecifier from,
final PlanSpecifier to, final StaticCatalog catalog) throws CatalogApiException {
-
-
final Product inFromProduct;
final BillingPeriod inFromBillingPeriod;
final ProductCategory inFromProductCategory;
@@ -116,7 +120,6 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
inToPriceList = to.getPriceListName() != null ? catalog.findCurrentPricelist(to.getPriceListName()) : null;
}
-
if (
(phaseType == null || from.getPhaseType() == phaseType) &&
(fromProduct == null || fromProduct.equals(inFromProduct)) &&
@@ -127,7 +130,7 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
(this.toBillingPeriod == null || this.toBillingPeriod.equals(inToBillingPeriod)) &&
(fromPriceList == null || fromPriceList.equals(inFromPriceList)) &&
(toPriceList == null || toPriceList.equals(inToPriceList))
- ) {
+ ) {
return getResult();
}
return null;
@@ -153,8 +156,8 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
@@ -318,4 +321,45 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
", toPriceList=" + toPriceList +
'}';
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(phaseType != null);
+ if (phaseType != null) {
+ out.writeUTF(phaseType.name());
+ }
+ out.writeObject(fromProduct);
+ out.writeBoolean(fromProductCategory != null);
+ if (fromProductCategory != null) {
+ out.writeUTF(fromProductCategory.name());
+ }
+ out.writeBoolean(fromBillingPeriod != null);
+ if (fromBillingPeriod != null) {
+ out.writeUTF(fromBillingPeriod.name());
+ }
+ out.writeObject(fromPriceList);
+ out.writeObject(toProduct);
+ out.writeBoolean(toProductCategory != null);
+ if (toProductCategory != null) {
+ out.writeUTF(toProductCategory.name());
+ }
+ out.writeBoolean(toBillingPeriod != null);
+ if (toBillingPeriod != null) {
+ out.writeUTF(toBillingPeriod.name());
+ }
+ out.writeObject(toPriceList);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.phaseType = in.readBoolean() ? PhaseType.valueOf(in.readUTF()) : null;
+ this.fromProduct = (DefaultProduct) in.readObject();
+ this.fromProductCategory = in.readBoolean() ? ProductCategory.valueOf(in.readUTF()) : null;
+ this.fromBillingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.fromPriceList = (DefaultPriceList) in.readObject();
+ this.toProduct = (DefaultProduct) in.readObject();
+ this.toProductCategory = in.readBoolean() ? ProductCategory.valueOf(in.readUTF()) : null;
+ this.toBillingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.toPriceList = (DefaultPriceList) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanAlignment.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanAlignment.java
index d3a95b6..b482e86 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanAlignment.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanAlignment.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,12 +18,17 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import org.killbill.billing.catalog.api.PlanAlignmentChange;
import org.killbill.billing.catalog.api.rules.CaseChangePlanAlignment;
-public class DefaultCaseChangePlanAlignment extends DefaultCaseChange<PlanAlignmentChange> implements CaseChangePlanAlignment {
+public class DefaultCaseChangePlanAlignment extends DefaultCaseChange<PlanAlignmentChange> implements CaseChangePlanAlignment, Externalizable {
@XmlElement(required = true)
private PlanAlignmentChange alignment;
@@ -85,4 +92,18 @@ public class DefaultCaseChangePlanAlignment extends DefaultCaseChange<PlanAlignm
'}';
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(alignment != null);
+ if (alignment != null) {
+ out.writeUTF(alignment.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.alignment = in.readBoolean() ? PlanAlignmentChange.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanPolicy.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanPolicy.java
index 71f90b5..f1cbf27 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanPolicy.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChangePlanPolicy.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,10 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.net.URI;
import javax.xml.bind.annotation.XmlElement;
@@ -28,11 +34,15 @@ import org.killbill.billing.catalog.api.rules.CaseChangePlanPolicy;
import org.killbill.xmlloader.ValidationErrors;
@XmlSeeAlso(DefaultCaseChange.class)
-public class DefaultCaseChangePlanPolicy extends DefaultCaseChange<BillingActionPolicy> implements CaseChangePlanPolicy {
+public class DefaultCaseChangePlanPolicy extends DefaultCaseChange<BillingActionPolicy> implements CaseChangePlanPolicy, Externalizable {
@XmlElement(required = true)
private BillingActionPolicy policy;
+ // Required for deserialization
+ public DefaultCaseChangePlanPolicy() {
+ }
+
@Override
protected BillingActionPolicy getResult() {
return policy;
@@ -54,8 +64,8 @@ public class DefaultCaseChangePlanPolicy extends DefaultCaseChange<BillingAction
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
@@ -91,7 +101,7 @@ public class DefaultCaseChangePlanPolicy extends DefaultCaseChange<BillingAction
public String toString() {
return "DefaultCaseChangePlanPolicy {" +
"policy=" + policy +
- ", phaseType=" + phaseType +
+ ", phaseType=" + getPhaseType() +
", fromProduct=" + getFromProduct() +
", fromProductCategory=" + getFromProductCategory() +
", fromBillingPeriod=" + getFromBillingPeriod() +
@@ -102,4 +112,19 @@ public class DefaultCaseChangePlanPolicy extends DefaultCaseChange<BillingAction
", toPriceList=" + getToPriceList() +
'}';
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(policy != null);
+ if (policy != null) {
+ out.writeUTF(policy.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.policy = in.readBoolean() ? BillingActionPolicy.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCreateAlignment.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCreateAlignment.java
index 5577db3..27a5db5 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCreateAlignment.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseCreateAlignment.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,12 +18,17 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import org.killbill.billing.catalog.api.PlanAlignmentCreate;
import org.killbill.billing.catalog.api.rules.CaseCreateAlignment;
-public class DefaultCaseCreateAlignment extends DefaultCaseStandardNaming<PlanAlignmentCreate> implements CaseCreateAlignment {
+public class DefaultCaseCreateAlignment extends DefaultCaseStandardNaming<PlanAlignmentCreate> implements CaseCreateAlignment, Externalizable {
@XmlElement(required = true)
private PlanAlignmentCreate alignment;
@@ -80,4 +87,18 @@ public class DefaultCaseCreateAlignment extends DefaultCaseStandardNaming<PlanAl
'}';
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(alignment != null);
+ if (alignment != null) {
+ out.writeUTF(alignment.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.alignment = in.readBoolean() ? PlanAlignmentCreate.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
index ef8773c..1e01885 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,10 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.net.URI;
import javax.xml.bind.annotation.XmlElement;
@@ -29,14 +35,14 @@ import org.killbill.billing.catalog.api.PlanSpecifier;
import org.killbill.billing.catalog.api.StaticCatalog;
import org.killbill.xmlloader.ValidationErrors;
-public abstract class DefaultCasePhase<T> extends DefaultCaseStandardNaming<T> {
+public abstract class DefaultCasePhase<T> extends DefaultCaseStandardNaming<T> implements Externalizable {
@XmlElement(required = false)
protected PhaseType phaseType;
public T getResult(final PlanPhaseSpecifier specifier, final StaticCatalog c) throws CatalogApiException {
if ((phaseType == null || specifier.getPhaseType() == phaseType)
- && satisfiesCase(new PlanSpecifier(specifier), c)) {
+ && satisfiesCase(new PlanSpecifier(specifier), c)) {
return getResult();
}
return null;
@@ -61,12 +67,11 @@ public abstract class DefaultCasePhase<T> extends DefaultCaseStandardNaming<T> {
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
}
-
public DefaultCasePhase<T> setPhaseType(final PhaseType phaseType) {
this.phaseType = phaseType;
return this;
@@ -99,4 +104,19 @@ public abstract class DefaultCasePhase<T> extends DefaultCaseStandardNaming<T> {
result = 31 * result + (phaseType != null ? phaseType.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeBoolean(phaseType != null);
+ if (phaseType != null) {
+ out.writeUTF(phaseType.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.phaseType = in.readBoolean() ? PhaseType.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePriceList.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePriceList.java
index 4b9cf33..ad23086 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePriceList.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePriceList.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,11 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
@@ -26,7 +33,8 @@ import org.killbill.billing.catalog.api.PriceList;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.catalog.api.rules.CasePriceList;
-public class DefaultCasePriceList extends DefaultCaseStandardNaming<DefaultPriceList> implements CasePriceList {
+public class DefaultCasePriceList extends DefaultCaseStandardNaming<DefaultPriceList> implements CasePriceList, Externalizable {
+
@XmlElement(required = false, name = "fromProduct")
@XmlIDREF
private DefaultProduct fromProduct;
@@ -94,7 +102,6 @@ public class DefaultCasePriceList extends DefaultCaseStandardNaming<DefaultPrice
return this;
}
-
public DefaultCasePriceList setToPriceList(final DefaultPriceList toPriceList) {
this.toPriceList = toPriceList;
return this;
@@ -144,7 +151,6 @@ public class DefaultCasePriceList extends DefaultCaseStandardNaming<DefaultPrice
return result;
}
-
@Override
public String toString() {
return "DefaultCasePriceList {" +
@@ -155,4 +161,30 @@ public class DefaultCasePriceList extends DefaultCaseStandardNaming<DefaultPrice
", toPriceList=" + toPriceList +
'}';
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeObject(fromProduct);
+ out.writeBoolean(fromProductCategory != null);
+ if (fromProductCategory != null) {
+ out.writeUTF(fromProductCategory.name());
+ }
+ out.writeBoolean(fromBillingPeriod != null);
+ if (fromBillingPeriod != null) {
+ out.writeUTF(fromBillingPeriod.name());
+ }
+ out.writeObject(fromPriceList);
+ out.writeObject(toPriceList);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.fromProduct = (DefaultProduct) in.readObject();
+ this.fromProductCategory = in.readBoolean() ? ProductCategory.valueOf(in.readUTF()) : null;
+ this.fromBillingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.fromPriceList = (DefaultPriceList) in.readObject();
+ this.toPriceList = (DefaultPriceList) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseStandardNaming.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseStandardNaming.java
index d23c55f..3c97746 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseStandardNaming.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseStandardNaming.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,6 +18,11 @@
package org.killbill.billing.catalog.rules;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
@@ -26,7 +33,8 @@ import org.killbill.billing.catalog.api.Product;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.catalog.api.rules.Case;
-public abstract class DefaultCaseStandardNaming<T> extends DefaultCase<T> implements Case {
+public abstract class DefaultCaseStandardNaming<T> extends DefaultCase<T> implements Case, Externalizable {
+
@XmlElement(required = false, name = "product")
@XmlIDREF
private DefaultProduct product;
@@ -116,4 +124,25 @@ public abstract class DefaultCaseStandardNaming<T> extends DefaultCase<T> implem
return result;
}
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(product);
+ out.writeBoolean(productCategory != null);
+ if (productCategory != null) {
+ out.writeUTF(productCategory.name());
+ }
+ out.writeBoolean(billingPeriod != null);
+ if (billingPeriod != null) {
+ out.writeUTF(billingPeriod.name());
+ }
+ out.writeObject(priceList);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.product = (DefaultProduct) in.readObject();
+ this.productCategory = in.readBoolean() ? ProductCategory.valueOf(in.readUTF()) : null;
+ this.billingPeriod = in.readBoolean() ? BillingPeriod.valueOf(in.readUTF()) : null;
+ this.priceList = (DefaultPriceList) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
index 6085476..0a18078 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
@@ -18,7 +18,10 @@
package org.killbill.billing.catalog.rules;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.Arrays;
import java.util.HashSet;
@@ -54,7 +57,7 @@ import org.killbill.xmlloader.ValidationErrors;
import com.google.common.collect.ImmutableList;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implements PlanRules {
+public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implements PlanRules, Externalizable {
@XmlElementWrapper(name = "changePolicy")
@XmlElement(name = "changePolicyCase", required = false)
@@ -80,6 +83,10 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
@XmlElement(name = "priceListCase", required = false)
private DefaultCasePriceList[] priceListCase;
+ // Required for deserialization
+ public DefaultPlanRules() {
+ }
+
@Override
public Iterable<CaseChangePlanPolicy> getCaseChangePlanPolicy() {
return ImmutableList.<CaseChangePlanPolicy>copyOf(changeCase);
@@ -137,7 +144,6 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
new PlanSpecifier(to.getProductName(), to.getBillingPeriod(), toPriceList.getName()) :
to;
-
final BillingActionPolicy policy = getPlanChangePolicy(from, toWithPriceList, catalog);
if (policy == BillingActionPolicy.ILLEGAL) {
throw new IllegalPlanChange(from, toWithPriceList);
@@ -178,7 +184,7 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
boolean foundDefaultCase = false;
for (final DefaultCaseChangePlanPolicy cur : changeCase) {
if (caseChangePlanPoliciesSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for change plan %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for change plan %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
caseChangePlanPoliciesSet.add(cur);
}
@@ -196,14 +202,14 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
cur.validate(catalog, errors);
}
if (!foundDefaultCase) {
- errors.add(new ValidationError("Missing default rule case for plan change", catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError("Missing default rule case for plan change", DefaultPlanRules.class, ""));
}
final HashSet<DefaultCaseCancelPolicy> defaultCaseCancelPoliciesSet = new HashSet<DefaultCaseCancelPolicy>();
foundDefaultCase = false;
for (final DefaultCaseCancelPolicy cur : cancelCase) {
if (defaultCaseCancelPoliciesSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for plan cancellation %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for plan cancellation %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
defaultCaseCancelPoliciesSet.add(cur);
}
@@ -217,14 +223,13 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
cur.validate(catalog, errors);
}
if (!foundDefaultCase) {
- errors.add(new ValidationError("Missing default rule case for plan cancellation", catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError("Missing default rule case for plan cancellation", DefaultPlanRules.class, ""));
}
-
final HashSet<DefaultCaseChangePlanAlignment> caseChangePlanAlignmentsSet = new HashSet<DefaultCaseChangePlanAlignment>();
for (final DefaultCaseChangePlanAlignment cur : changeAlignmentCase) {
if (caseChangePlanAlignmentsSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for plan change alignment %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for plan change alignment %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
caseChangePlanAlignmentsSet.add(cur);
}
@@ -234,7 +239,7 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
final HashSet<DefaultCaseCreateAlignment> caseCreateAlignmentsSet = new HashSet<DefaultCaseCreateAlignment>();
for (final DefaultCaseCreateAlignment cur : createAlignmentCase) {
if (caseCreateAlignmentsSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for create plan alignment %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for create plan alignment %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
caseCreateAlignmentsSet.add(cur);
}
@@ -244,7 +249,7 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
final HashSet<DefaultCaseBillingAlignment> caseBillingAlignmentsSet = new HashSet<DefaultCaseBillingAlignment>();
for (final DefaultCaseBillingAlignment cur : billingAlignmentCase) {
if (caseBillingAlignmentsSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for billing alignment %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for billing alignment %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
caseBillingAlignmentsSet.add(cur);
}
@@ -254,7 +259,7 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
final HashSet<DefaultCasePriceList> casePriceListsSet = new HashSet<DefaultCasePriceList>();
for (final DefaultCasePriceList cur : priceListCase) {
if (casePriceListsSet.contains(cur)) {
- errors.add(new ValidationError(String.format("Duplicate rule for price list transition %s", cur.toString()), catalog.getCatalogURI(), DefaultPlanRules.class, ""));
+ errors.add(new ValidationError(String.format("Duplicate rule for price list transition %s", cur.toString()), DefaultPlanRules.class, ""));
} else {
casePriceListsSet.add(cur);
}
@@ -263,33 +268,31 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
return errors;
}
-
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
for (final DefaultCaseChangePlanPolicy cur : changeCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final DefaultCaseChangePlanAlignment cur : changeAlignmentCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final DefaultCaseCancelPolicy cur : cancelCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final DefaultCaseCreateAlignment cur : createAlignmentCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final DefaultCaseBillingAlignment cur : billingAlignmentCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final DefaultCasePriceList cur : priceListCase) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
}
-
/////////////////////////////////////////////////////////////////////////////////////
// Setters for testing
/////////////////////////////////////////////////////////////////////////////////////
@@ -369,4 +372,24 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
result = 31 * result + (priceListCase != null ? Arrays.hashCode(priceListCase) : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(changeCase);
+ out.writeObject(changeAlignmentCase);
+ out.writeObject(cancelCase);
+ out.writeObject(createAlignmentCase);
+ out.writeObject(billingAlignmentCase);
+ out.writeObject(priceListCase);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.changeCase = (DefaultCaseChangePlanPolicy[]) in.readObject();
+ this.changeAlignmentCase = (DefaultCaseChangePlanAlignment[]) in.readObject();
+ this.cancelCase = (DefaultCaseCancelPolicy[]) in.readObject();
+ this.createAlignmentCase = (DefaultCaseCreateAlignment[]) in.readObject();
+ this.billingAlignmentCase = (DefaultCaseBillingAlignment[]) in.readObject();
+ this.priceListCase = (DefaultCasePriceList[]) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
index 9d454b0..ed078fb 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
@@ -18,7 +18,10 @@
package org.killbill.billing.catalog;
-import java.net.URI;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -58,7 +61,7 @@ import org.killbill.xmlloader.ValidationErrors;
@XmlRootElement(name = "catalog")
@XmlAccessorType(XmlAccessType.NONE)
-public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements StaticCatalog {
+public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements StaticCatalog, Externalizable {
@XmlElement(required = true)
private Date effectiveDate;
@@ -91,8 +94,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
@XmlElement(name = "priceLists", required = true)
private DefaultPriceListSet priceLists;
- private URI catalogURI;
-
public StandaloneCatalog() {
this.plans = new CatalogEntityCollection<Plan>();
this.products = new CatalogEntityCollection<Product>();
@@ -156,10 +157,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
(supportedCurrencies == null || supportedCurrencies.length == 0);
}
- public URI getCatalogURI() {
- return catalogURI;
- }
-
public DefaultPlanRules getPlanRules() {
return planRules;
}
@@ -294,22 +291,20 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
}
@Override
- public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
-
- super.initialize(catalog, sourceURI);
+ public void initialize(final StandaloneCatalog catalog) {
+ super.initialize(catalog);
CatalogSafetyInitializer.initializeNonRequiredNullFieldsWithDefaultValue(this);
- catalogURI = sourceURI;
- planRules.initialize(catalog, sourceURI);
- priceLists.initialize(catalog, sourceURI);
+ planRules.initialize(catalog);
+ priceLists.initialize(catalog);
for (final DefaultUnit cur : units) {
- cur.initialize(catalog, sourceURI);
+ cur.initialize(catalog);
}
for (final Product p : products.getEntries()) {
- ((DefaultProduct) p).initialize(catalog, sourceURI);
+ ((DefaultProduct) p).initialize(catalog);
}
for (final Plan p : plans.getEntries()) {
- ((DefaultPlan) p).initialize(catalog, sourceURI);
+ ((DefaultPlan) p).initialize(catalog);
}
}
@@ -401,9 +396,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
if (catalogName != null ? !catalogName.equals(that.catalogName) : that.catalogName != null) {
return false;
}
- if (catalogURI != null ? !catalogURI.equals(that.catalogURI) : that.catalogURI != null) {
- return false;
- }
if (effectiveDate != null ? !effectiveDate.equals(that.effectiveDate) : that.effectiveDate != null) {
return false;
}
@@ -442,7 +434,35 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
result = 31 * result + (planRules != null ? planRules.hashCode() : 0);
result = 31 * result + (plans != null ? plans.hashCode() : 0);
result = 31 * result + (priceLists != null ? priceLists.hashCode() : 0);
- result = 31 * result + (catalogURI != null ? catalogURI.hashCode() : 0);
return result;
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(effectiveDate);
+ out.writeUTF(catalogName);
+ out.writeBoolean(recurringBillingMode != null);
+ if (recurringBillingMode != null) {
+ out.writeUTF(recurringBillingMode.name());
+ }
+ out.writeObject(supportedCurrencies);
+ out.writeObject(units);
+ out.writeObject(products);
+ out.writeObject(planRules);
+ out.writeObject(plans);
+ out.writeObject(priceLists);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.effectiveDate = (Date) in.readObject();
+ this.catalogName = in.readUTF();
+ this.recurringBillingMode = in.readBoolean() ? BillingMode.valueOf(in.readUTF()) : null;
+ this.supportedCurrencies = (Currency[]) in.readObject();
+ this.units = (DefaultUnit[]) in.readObject();
+ this.products = (CatalogEntityCollection<Product>) in.readObject();
+ this.planRules = (DefaultPlanRules) in.readObject();
+ this.plans = (CatalogEntityCollection<Plan>) in.readObject();
+ this.priceLists = (DefaultPriceListSet) in.readObject();
+ }
}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
index 4729e6d..88b547f 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalogWithPriceOverride.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,6 +17,10 @@
package org.killbill.billing.catalog;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.util.regex.Matcher;
import org.killbill.billing.ErrorCode;
@@ -25,7 +29,6 @@ import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.catalog.api.CatalogApiException;
import org.killbill.billing.catalog.api.Plan;
import org.killbill.billing.catalog.api.PlanPhase;
-import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
import org.killbill.billing.catalog.api.PlanPhasePriceOverridesWithCallContext;
import org.killbill.billing.catalog.api.PlanSpecifier;
import org.killbill.billing.catalog.api.Product;
@@ -36,15 +39,19 @@ import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import com.fasterxml.jackson.annotation.JsonIgnore;
-public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implements StaticCatalog {
+public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implements StaticCatalog, Externalizable {
- private final Long tenantRecordId;
+ private Long tenantRecordId;
/* Since we offer endpoints that attempt to serialize catalog objects, we need to explicitly tell Jackson to ignore those fields */
@JsonIgnore
- private final InternalCallContextFactory internalCallContextFactory;
+ private InternalCallContextFactory internalCallContextFactory;
@JsonIgnore
- private final PriceOverride priceOverride;
+ private PriceOverride priceOverride;
+
+ // Required for deserialization
+ public StandaloneCatalogWithPriceOverride() {
+ }
public StandaloneCatalogWithPriceOverride(final StandaloneCatalog catalog, final PriceOverride priceOverride, final Long tenantRecordId, final InternalCallContextFactory internalCallContextFactory) {
// Initialize from input catalog
@@ -133,4 +140,22 @@ public class StandaloneCatalogWithPriceOverride extends StandaloneCatalog implem
private InternalTenantContext createInternalTenantContext() {
return internalCallContextFactory.createInternalTenantContext(tenantRecordId, null);
}
+
+ public void initialize(final StandaloneCatalog catalog, final PriceOverride priceOverride, final InternalCallContextFactory internalCallContextFactory) {
+ super.initialize(catalog);
+ this.priceOverride = priceOverride;
+ this.internalCallContextFactory = internalCallContextFactory;
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ super.writeExternal(out);
+ out.writeLong(tenantRecordId);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ super.readExternal(in);
+ this.tenantRecordId = in.readLong();
+ }
}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java b/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
index de3d3da..87627b9 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/io/TestXMLWriter.java
@@ -71,7 +71,7 @@ public class TestXMLWriter extends CatalogTestSuiteNoDB {
final String oldCatalogStr = XMLWriter.writeXML(catalog, StandaloneCatalog.class);
//System.err.println(oldCatalogStr);
- final StandaloneCatalog oldCatalog = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(oldCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
+ final StandaloneCatalog oldCatalog = XMLLoader.getObjectFromStream(new ByteArrayInputStream(oldCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
final String oldCatalogStr2 = XMLWriter.writeXML(oldCatalog, StandaloneCatalog.class);
assertEquals(oldCatalogStr2, oldCatalogStr);
}
@@ -85,7 +85,7 @@ public class TestXMLWriter extends CatalogTestSuiteNoDB {
final DefaultProduct newProduct = new DefaultProduct();
newProduct.setName("Dynamic");
newProduct.setCatagory(ProductCategory.BASE);
- newProduct.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
+ newProduct.initialize((StandaloneCatalog) mutableCatalog);
mutableCatalog.addProduct(newProduct);
@@ -108,10 +108,10 @@ public class TestXMLWriter extends CatalogTestSuiteNoDB {
newPlan.setRecurringBillingMode(BillingMode.IN_ADVANCE);
// TODO Ordering breaks
mutableCatalog.addPlan(newPlan);
- newPlan.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
+ newPlan.initialize((StandaloneCatalog) mutableCatalog);
final String newCatalogStr = XMLWriter.writeXML((StandaloneCatalog) mutableCatalog, StandaloneCatalog.class);
- final StandaloneCatalog newCatalog = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
+ final StandaloneCatalog newCatalog = XMLLoader.getObjectFromStream(new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
assertEquals(newCatalog.getCurrentPlans().size(), catalog.getCurrentPlans().size() + 1);
final Plan plan = newCatalog.findCurrentPlan("dynamic-monthly");
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
index ed37579..2fb5c63 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
@@ -48,7 +48,7 @@ public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
final StandaloneCatalogMapper mapper = new StandaloneCatalogMapper(inputCatalog.getCatalogName());
- final StandaloneCatalog output = mapper.toStandaloneCatalog(pluginCatalog, inputCatalog.getCatalogURI());
+ final StandaloneCatalog output = mapper.toStandaloneCatalog(pluginCatalog);
output.setRecurringBillingMode(inputCatalog.getRecurringBillingMode());
Assert.assertEquals(output, inputCatalog);
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
index 448942f..5ac2eb0 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
@@ -60,7 +60,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
final CatalogUpdater catalogUpdater = new CatalogUpdater(now, null);
final String catalogXML = catalogUpdater.getCatalogXML();
- final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(catalogXML.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
+ final StandaloneCatalog catalog = XMLLoader.getObjectFromStream(new ByteArrayInputStream(catalogXML.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
assertEquals(catalog.getCurrentPlans().size(), 0);
}
@@ -294,7 +294,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
final DefaultProduct newProduct = new DefaultProduct();
newProduct.setName("Something");
newProduct.setCatagory(ProductCategory.BASE);
- newProduct.initialize((StandaloneCatalog) mutableCatalog, null);
+ newProduct.initialize((StandaloneCatalog) mutableCatalog);
mutableCatalog.addProduct(newProduct);
final DefaultPlanPhase trialPhase = new DefaultPlanPhase();
@@ -320,10 +320,10 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
newPlan.setInitialPhases(new DefaultPlanPhase[]{trialPhase, fixedTermPhase});
newPlan.setFinalPhase(fixedTermPhase);
mutableCatalog.addPlan(newPlan);
- newPlan.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
+ newPlan.initialize((StandaloneCatalog) mutableCatalog);
final String newCatalogStr = XMLWriter.writeXML((StandaloneCatalog) mutableCatalog, StandaloneCatalog.class);
- final StandaloneCatalog newCatalog = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
+ final StandaloneCatalog newCatalog = XMLLoader.getObjectFromStream(new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
final DefaultPlan targetPlan = newCatalog.findCurrentPlan("something-with-fixed-term");
Assert.assertEquals(targetPlan.getInitialPhases().length, 2);
@@ -588,7 +588,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
final DefaultProduct newProduct1 = new DefaultProduct();
newProduct1.setName("Dynamic");
newProduct1.setCatagory(ProductCategory.BASE);
- newProduct1.initialize((StandaloneCatalog) mutableCatalog, null);
+ newProduct1.initialize((StandaloneCatalog) mutableCatalog);
mutableCatalog.addProduct(newProduct1);
final DefaultPlanPhase discountPhase1 = new DefaultPlanPhase();
@@ -609,12 +609,12 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
newPlan1.setInitialPhases(new DefaultPlanPhase[]{discountPhase1});
newPlan1.setFinalPhase(evergreenPhase1);
mutableCatalog.addPlan(newPlan1);
- newPlan1.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
+ newPlan1.initialize((StandaloneCatalog) mutableCatalog);
final DefaultProduct newProduct2 = new DefaultProduct();
newProduct2.setName("SuperDynamic");
newProduct2.setCatagory(ProductCategory.BASE);
- newProduct2.initialize((StandaloneCatalog) mutableCatalog, null);
+ newProduct2.initialize((StandaloneCatalog) mutableCatalog);
mutableCatalog.addProduct(newProduct2);
// Add a Plan with a FIXEDTERM phase
@@ -629,10 +629,10 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
newPlan2.setProduct(newProduct2);
newPlan2.setFinalPhase(fixedterm2);
mutableCatalog.addPlan(newPlan2);
- newPlan2.initialize((StandaloneCatalog) mutableCatalog, new URI("dummy"));
+ newPlan2.initialize((StandaloneCatalog) mutableCatalog);
final String newCatalogStr = XMLWriter.writeXML((StandaloneCatalog) mutableCatalog, StandaloneCatalog.class);
- return XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
+ return XMLLoader.getObjectFromStream(new ByteArrayInputStream(newCatalogStr.getBytes(Charset.forName("UTF-8"))), StandaloneCatalog.class);
}
private void addBadSimplePlanDescriptor(final CatalogUpdater catalogUpdater, final SimplePlanDescriptor desc) {
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java b/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
index 46ba4da..273df5d 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
@@ -52,7 +52,7 @@ public class TestDefaultPriceOverride extends CatalogTestSuiteWithEmbeddedDB {
public void testBasic() throws Exception {
final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class);
- catalog.initialize(catalog, null);
+ catalog.initialize(catalog);
final Plan plan = catalog.findCurrentPlan("discount-standard-monthly");
final List<PlanPhasePriceOverride> overrides = new ArrayList<PlanPhasePriceOverride>();
@@ -106,7 +106,7 @@ public class TestDefaultPriceOverride extends CatalogTestSuiteWithEmbeddedDB {
public void testWithInvalidPriceOverride() throws Exception {
final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class);
- catalog.initialize(catalog, null);
+ catalog.initialize(catalog);
final Plan plan = catalog.findCurrentPlan("discount-standard-monthly");
@@ -122,7 +122,7 @@ public class TestDefaultPriceOverride extends CatalogTestSuiteWithEmbeddedDB {
public void testGetOverriddenPlan() throws Exception {
final StandaloneCatalog catalog = XMLLoader.getObjectFromString(Resources.getResource("SpyCarAdvanced.xml").toExternalForm(), StandaloneCatalog.class);
- catalog.initialize(catalog, null);
+ catalog.initialize(catalog);
final Plan plan = catalog.findCurrentPlan("discount-standard-monthly");
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestInternationalPrice.java b/catalog/src/test/java/org/killbill/billing/catalog/TestInternationalPrice.java
index 103777a..1f848c0 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestInternationalPrice.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestInternationalPrice.java
@@ -35,7 +35,7 @@ public class TestInternationalPrice extends CatalogTestSuiteNoDB {
c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
final DefaultInternationalPrice p0 = new MockInternationalPrice();
p0.setPrices(new DefaultPrice[0]);
- p0.initialize(c, new URI("foo:bar"));
+ p0.initialize(c);
final DefaultInternationalPrice p1 = new MockInternationalPrice();
p1.setPrices(new DefaultPrice[]{
new DefaultPrice().setCurrency(Currency.GBP).setValue(new BigDecimal(1)),
@@ -44,7 +44,7 @@ public class TestInternationalPrice extends CatalogTestSuiteNoDB {
new DefaultPrice().setCurrency(Currency.BRL).setValue(new BigDecimal(1)),
new DefaultPrice().setCurrency(Currency.MXN).setValue(new BigDecimal(1)),
});
- p1.initialize(c, new URI("foo:bar"));
+ p1.initialize(c);
Assert.assertEquals(p0.getPrice(Currency.GBP), new BigDecimal(0));
Assert.assertEquals(p0.getPrice(Currency.EUR), new BigDecimal(0));
@@ -65,7 +65,7 @@ public class TestInternationalPrice extends CatalogTestSuiteNoDB {
c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
((DefaultInternationalPrice) c.getCurrentPlans().iterator().next().getFinalPhase().getRecurring().getRecurringPrice()).setPrices(new DefaultPrice[0]);
c.setUnits(new DefaultUnit[0]);
- c.initialize(c, new URI("foo://bar"));
+ c.initialize(c);
Assert.assertEquals(c.getCurrentPlans().iterator().next().getFinalPhase().getRecurring().getRecurringPrice().getPrice(Currency.GBP), new BigDecimal(0));
}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestPlanPhase.java b/catalog/src/test/java/org/killbill/billing/catalog/TestPlanPhase.java
index df1663c..046fed0 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestPlanPhase.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestPlanPhase.java
@@ -33,14 +33,14 @@ public class TestPlanPhase extends CatalogTestSuiteNoDB {
final MockCatalog catalog = new MockCatalog();
DefaultPlanPhase pp = MockPlanPhase.createUSDMonthlyEvergreen(null, "1.00").setPlan(MockPlan.createBicycleNoTrialEvergreen1USD());
- pp.initialize(catalog, null);
+ pp.initialize(catalog);
ValidationErrors errors = pp.validate(catalog, new ValidationErrors());
errors.log(log);
Assert.assertEquals(errors.size(), 1);
pp = MockPlanPhase.createUSDMonthlyEvergreen("1.00", null).setRecurring(new MockRecurring(BillingPeriod.NO_BILLING_PERIOD, MockInternationalPrice.createUSD("1.00")).setPhase(pp)).setPlan(MockPlan.createBicycleNoTrialEvergreen1USD());
- pp.initialize(catalog, null);
+ pp.initialize(catalog);
errors = pp.validate(catalog, new ValidationErrors());
errors.log(log);
Assert.assertEquals(errors.size(), 1);
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/OverdueResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/OverdueResource.java
index 6b6009a..426f23d 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/OverdueResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/OverdueResource.java
@@ -142,7 +142,7 @@ public class OverdueResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final UriInfo uriInfo) throws Exception {
// Validation purpose: Will throw if bad XML or catalog validation fails
final InputStream stream = new ByteArrayInputStream(overdueXML.getBytes());
- XMLLoader.getObjectFromStream(new URI(JaxrsResource.OVERDUE_PATH), stream, DefaultOverdueConfig.class);
+ XMLLoader.getObjectFromStream(stream, DefaultOverdueConfig.class);
final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request);
overdueApi.uploadOverdueConfig(overdueXML, callContext);
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultDuration.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultDuration.java
index 3ae374c..242d86a 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultDuration.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultDuration.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,6 +18,11 @@
package org.killbill.billing.overdue.config;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
@@ -25,14 +30,14 @@ import javax.xml.bind.annotation.XmlElement;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
-
import org.killbill.billing.catalog.api.Duration;
import org.killbill.billing.catalog.api.TimeUnit;
import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> implements Duration {
+public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> implements Duration, Externalizable {
+
@XmlElement(required = true)
private TimeUnit unit;
@@ -66,7 +71,7 @@ public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> impl
return dateTime.plusYears(number);
case UNLIMITED:
default:
- throw new IllegalStateException("Unexpected duration unit " + unit);
+ throw new IllegalStateException("Unexpected duration unit " + unit);
}
}
@@ -87,9 +92,10 @@ public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> impl
return localDate.plusYears(number);
case UNLIMITED:
default:
- throw new IllegalStateException("Unexpected duration unit " + unit);
+ throw new IllegalStateException("Unexpected duration unit " + unit);
}
}
+
@Override
public Period toJodaPeriod() {
if ((number == null) && (unit != TimeUnit.UNLIMITED)) {
@@ -107,7 +113,7 @@ public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> impl
return new Period().withYears(number);
case UNLIMITED:
default:
- throw new IllegalStateException("Unexpected duration unit " + unit);
+ throw new IllegalStateException("Unexpected duration unit " + unit);
}
}
@@ -128,6 +134,30 @@ public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> impl
}
@Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultDuration that = (DefaultDuration) o;
+
+ if (unit != that.unit) {
+ return false;
+ }
+ return number != null ? number.equals(that.number) : that.number == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = unit != null ? unit.hashCode() : 0;
+ result = 31 * result + (number != null ? number.hashCode() : 0);
+ return result;
+ }
+
+ @Override
public String toString() {
final StringBuilder sb = new StringBuilder("DefaultDuration{");
sb.append("unit=").append(unit);
@@ -135,4 +165,22 @@ public class DefaultDuration extends ValidatingConfig<DefaultOverdueConfig> impl
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(unit != null);
+ if (unit != null) {
+ out.writeUTF(unit.name());
+ }
+ out.writeBoolean(number != null);
+ if (number != null) {
+ out.writeInt(number);
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.unit = in.readBoolean() ? TimeUnit.valueOf(in.readUTF()) : null;
+ this.number = in.readBoolean() ? in.readInt() : null;
+ }
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
index a4e4b51..4a810b0 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueCondition.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,6 +18,10 @@
package org.killbill.billing.overdue.config;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Arrays;
@@ -28,21 +32,20 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import org.joda.time.LocalDate;
-
import org.killbill.billing.catalog.api.Duration;
import org.killbill.billing.catalog.api.TimeUnit;
import org.killbill.billing.overdue.ConditionEvaluation;
import org.killbill.billing.overdue.api.OverdueCondition;
import org.killbill.billing.overdue.config.api.BillingState;
import org.killbill.billing.payment.api.PaymentResponse;
-import org.killbill.xmlloader.ValidatingConfig;
-import org.killbill.xmlloader.ValidationErrors;
import org.killbill.billing.util.tag.ControlTagType;
import org.killbill.billing.util.tag.Tag;
+import org.killbill.xmlloader.ValidatingConfig;
+import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConfig> implements ConditionEvaluation, OverdueCondition {
+public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConfig> implements ConditionEvaluation, OverdueCondition, Externalizable {
@XmlElement(required = false, name = "numberOfUnpaidInvoicesEqualsOrExceeds")
private Integer numberOfUnpaidInvoicesEqualsOrExceeds;
@@ -115,19 +118,6 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
}
@Override
- public void initialize(final DefaultOverdueConfig root, final URI uri) {
- }
-
- public Duration getTimeOffset() {
- if (timeSinceEarliestUnpaidInvoiceEqualsOrExceeds != null) {
- return timeSinceEarliestUnpaidInvoiceEqualsOrExceeds;
- } else {
- return new DefaultDuration().setUnit(TimeUnit.DAYS).setNumber(0); // zero time
- }
-
- }
-
- @Override
public Integer getNumberOfUnpaidInvoicesEqualsOrExceeds() {
return numberOfUnpaidInvoicesEqualsOrExceeds;
}
@@ -143,7 +133,7 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
}
@Override
- public PaymentResponse [] getResponseForLastFailedPaymentIn() {
+ public PaymentResponse[] getResponseForLastFailedPaymentIn() {
return responseForLastFailedPayment;
}
@@ -182,6 +172,47 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
}
@Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultOverdueCondition that = (DefaultOverdueCondition) o;
+
+ if (numberOfUnpaidInvoicesEqualsOrExceeds != null ? !numberOfUnpaidInvoicesEqualsOrExceeds.equals(that.numberOfUnpaidInvoicesEqualsOrExceeds) : that.numberOfUnpaidInvoicesEqualsOrExceeds != null) {
+ return false;
+ }
+ if (totalUnpaidInvoiceBalanceEqualsOrExceeds != null ? !totalUnpaidInvoiceBalanceEqualsOrExceeds.equals(that.totalUnpaidInvoiceBalanceEqualsOrExceeds) : that.totalUnpaidInvoiceBalanceEqualsOrExceeds != null) {
+ return false;
+ }
+ if (timeSinceEarliestUnpaidInvoiceEqualsOrExceeds != null ? !timeSinceEarliestUnpaidInvoiceEqualsOrExceeds.equals(that.timeSinceEarliestUnpaidInvoiceEqualsOrExceeds) : that.timeSinceEarliestUnpaidInvoiceEqualsOrExceeds != null) {
+ return false;
+ }
+ // Probably incorrect - comparing Object[] arrays with Arrays.equals
+ if (!Arrays.equals(responseForLastFailedPayment, that.responseForLastFailedPayment)) {
+ return false;
+ }
+ if (controlTagInclusion != that.controlTagInclusion) {
+ return false;
+ }
+ return controlTagExclusion == that.controlTagExclusion;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = numberOfUnpaidInvoicesEqualsOrExceeds != null ? numberOfUnpaidInvoicesEqualsOrExceeds.hashCode() : 0;
+ result = 31 * result + (totalUnpaidInvoiceBalanceEqualsOrExceeds != null ? totalUnpaidInvoiceBalanceEqualsOrExceeds.hashCode() : 0);
+ result = 31 * result + (timeSinceEarliestUnpaidInvoiceEqualsOrExceeds != null ? timeSinceEarliestUnpaidInvoiceEqualsOrExceeds.hashCode() : 0);
+ result = 31 * result + Arrays.hashCode(responseForLastFailedPayment);
+ result = 31 * result + (controlTagInclusion != null ? controlTagInclusion.hashCode() : 0);
+ result = 31 * result + (controlTagExclusion != null ? controlTagExclusion.hashCode() : 0);
+ return result;
+ }
+
+ @Override
public String toString() {
final StringBuilder sb = new StringBuilder("DefaultOverdueCondition{");
sb.append("numberOfUnpaidInvoicesEqualsOrExceeds=").append(numberOfUnpaidInvoicesEqualsOrExceeds);
@@ -193,4 +224,33 @@ public class DefaultOverdueCondition extends ValidatingConfig<DefaultOverdueConf
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeBoolean(numberOfUnpaidInvoicesEqualsOrExceeds != null);
+ if (numberOfUnpaidInvoicesEqualsOrExceeds != null) {
+ out.writeInt(numberOfUnpaidInvoicesEqualsOrExceeds);
+ }
+ out.writeObject(totalUnpaidInvoiceBalanceEqualsOrExceeds);
+ out.writeObject(timeSinceEarliestUnpaidInvoiceEqualsOrExceeds);
+ out.writeObject(responseForLastFailedPayment);
+ out.writeBoolean(controlTagInclusion != null);
+ if (controlTagInclusion != null) {
+ out.writeUTF(controlTagInclusion.name());
+ }
+ out.writeBoolean(controlTagExclusion != null);
+ if (controlTagExclusion != null) {
+ out.writeUTF(controlTagExclusion.name());
+ }
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.numberOfUnpaidInvoicesEqualsOrExceeds = in.readBoolean() ? in.readInt() : null;
+ this.totalUnpaidInvoiceBalanceEqualsOrExceeds = (BigDecimal) in.readObject();
+ this.timeSinceEarliestUnpaidInvoiceEqualsOrExceeds = (DefaultDuration) in.readObject();
+ this.responseForLastFailedPayment = (PaymentResponse[]) in.readObject();
+ this.controlTagInclusion = in.readBoolean() ? ControlTagType.valueOf(in.readUTF()) : null;
+ this.controlTagExclusion = in.readBoolean() ? ControlTagType.valueOf(in.readUTF()) : null;
+ }
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueConfig.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueConfig.java
index 0aec675..599d8d9 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueConfig.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueConfig.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -22,7 +22,6 @@ import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.net.URI;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -30,9 +29,6 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.killbill.billing.overdue.api.OverdueConfig;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
import org.killbill.xmlloader.ValidatingConfig;
import org.killbill.xmlloader.ValidationErrors;
@@ -63,17 +59,32 @@ public class DefaultOverdueConfig extends ValidatingConfig<DefaultOverdueConfig>
return this;
}
- public URI getURI() {
- return null;
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultOverdueConfig that = (DefaultOverdueConfig) o;
+
+ return accountOverdueStates != null ? accountOverdueStates.equals(that.accountOverdueStates) : that.accountOverdueStates == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return accountOverdueStates != null ? accountOverdueStates.hashCode() : 0;
}
@Override
- public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.accountOverdueStates = (DefaultOverdueStatesAccount) in.readObject();
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeObject(accountOverdueStates);
}
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueState.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueState.java
index 233a0ca..ca74058 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueState.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueState.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -18,21 +18,21 @@
package org.killbill.billing.overdue.config;
-import java.util.List;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlID;
-import org.joda.time.Period;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.catalog.api.Duration;
import org.killbill.billing.catalog.api.TimeUnit;
import org.killbill.billing.overdue.ConditionEvaluation;
-import org.killbill.billing.overdue.api.EmailNotification;
import org.killbill.billing.overdue.api.OverdueApiException;
import org.killbill.billing.overdue.api.OverdueCancellationPolicy;
import org.killbill.billing.overdue.api.OverdueCondition;
@@ -42,7 +42,7 @@ import org.killbill.xmlloader.ValidationError;
import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
-public class DefaultOverdueState extends ValidatingConfig<DefaultOverdueConfig> implements OverdueState {
+public class DefaultOverdueState extends ValidatingConfig<DefaultOverdueConfig> implements OverdueState, Externalizable {
private static final int MAX_NAME_LENGTH = 50;
@@ -168,16 +168,66 @@ public class DefaultOverdueState extends ValidatingConfig<DefaultOverdueConfig>
return isClearState;
}
-
@Override
public ValidationErrors validate(final DefaultOverdueConfig root,
final ValidationErrors errors) {
if (name.length() > MAX_NAME_LENGTH) {
- errors.add(new ValidationError(String.format("Name of state '%s' exceeds the maximum length of %d", name, MAX_NAME_LENGTH), root.getURI(), DefaultOverdueState.class, name));
+ errors.add(new ValidationError(String.format("Name of state '%s' exceeds the maximum length of %d", name, MAX_NAME_LENGTH), DefaultOverdueState.class, name));
}
return errors;
}
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultOverdueState that = (DefaultOverdueState) o;
+
+ if (condition != null ? !condition.equals(that.condition) : that.condition != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+ if (externalMessage != null ? !externalMessage.equals(that.externalMessage) : that.externalMessage != null) {
+ return false;
+ }
+ if (blockChanges != null ? !blockChanges.equals(that.blockChanges) : that.blockChanges != null) {
+ return false;
+ }
+ if (disableEntitlement != null ? !disableEntitlement.equals(that.disableEntitlement) : that.disableEntitlement != null) {
+ return false;
+ }
+ if (subscriptionCancellationPolicy != that.subscriptionCancellationPolicy) {
+ return false;
+ }
+ if (isClearState != null ? !isClearState.equals(that.isClearState) : that.isClearState != null) {
+ return false;
+ }
+ if (autoReevaluationInterval != null ? !autoReevaluationInterval.equals(that.autoReevaluationInterval) : that.autoReevaluationInterval != null) {
+ return false;
+ }
+ return enterStateEmailNotification != null ? enterStateEmailNotification.equals(that.enterStateEmailNotification) : that.enterStateEmailNotification == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = condition != null ? condition.hashCode() : 0;
+ result = 31 * result + (name != null ? name.hashCode() : 0);
+ result = 31 * result + (externalMessage != null ? externalMessage.hashCode() : 0);
+ result = 31 * result + (blockChanges != null ? blockChanges.hashCode() : 0);
+ result = 31 * result + (disableEntitlement != null ? disableEntitlement.hashCode() : 0);
+ result = 31 * result + (subscriptionCancellationPolicy != null ? subscriptionCancellationPolicy.hashCode() : 0);
+ result = 31 * result + (isClearState != null ? isClearState.hashCode() : 0);
+ result = 31 * result + (autoReevaluationInterval != null ? autoReevaluationInterval.hashCode() : 0);
+ result = 31 * result + (enterStateEmailNotification != null ? enterStateEmailNotification.hashCode() : 0);
+ return result;
+ }
@Override
public String toString() {
@@ -193,4 +243,31 @@ public class DefaultOverdueState extends ValidatingConfig<DefaultOverdueConfig>
sb.append('}');
return sb.toString();
}
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(condition);
+ out.writeUTF(name);
+ out.writeUTF(externalMessage);
+ out.writeBoolean(blockChanges);
+ out.writeBoolean(disableEntitlement);
+ out.writeBoolean(subscriptionCancellationPolicy != null);
+ if (subscriptionCancellationPolicy != null) {
+ out.writeUTF(subscriptionCancellationPolicy.name());
+ }
+ out.writeBoolean(isClearState);
+ out.writeObject(autoReevaluationInterval);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.condition = (DefaultOverdueCondition) in.readObject();
+ this.name = in.readUTF();
+ this.externalMessage = in.readUTF();
+ this.blockChanges = in.readBoolean();
+ this.disableEntitlement = in.readBoolean();
+ this.subscriptionCancellationPolicy = in.readBoolean() ? OverdueCancellationPolicy.valueOf(in.readUTF()) : null;
+ this.isClearState = in.readBoolean();
+ this.autoReevaluationInterval = (DefaultDuration) in.readObject();
+ }
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStatesAccount.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStatesAccount.java
index c384444..e8e118e 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStatesAccount.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStatesAccount.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -16,17 +18,19 @@
package org.killbill.billing.overdue.config;
-import java.util.List;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Arrays;
-import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import org.joda.time.Period;
-
import org.killbill.billing.catalog.api.TimeUnit;
import org.killbill.billing.overdue.api.OverdueStatesAccount;
-public class DefaultOverdueStatesAccount extends DefaultOverdueStateSet implements OverdueStatesAccount {
+public class DefaultOverdueStatesAccount extends DefaultOverdueStateSet implements OverdueStatesAccount, Externalizable {
@XmlElement(required = false, name = "initialReevaluationInterval")
private DefaultDuration initialReevaluationInterval;
@@ -35,6 +39,9 @@ public class DefaultOverdueStatesAccount extends DefaultOverdueStateSet implemen
@XmlElement(required = true, name = "state")
private DefaultOverdueState[] accountOverdueStates = new DefaultOverdueState[0];
+ // Required for deserialization
+ public DefaultOverdueStatesAccount() {
+ }
@Override
public DefaultOverdueState[] getStates() {
@@ -58,4 +65,40 @@ public class DefaultOverdueStatesAccount extends DefaultOverdueStateSet implemen
this.initialReevaluationInterval = initialReevaluationInterval;
return this;
}
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultOverdueStatesAccount that = (DefaultOverdueStatesAccount) o;
+
+ if (initialReevaluationInterval != null ? !initialReevaluationInterval.equals(that.initialReevaluationInterval) : that.initialReevaluationInterval != null) {
+ return false;
+ }
+ return Arrays.equals(accountOverdueStates, that.accountOverdueStates);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = initialReevaluationInterval != null ? initialReevaluationInterval.hashCode() : 0;
+ result = 31 * result + Arrays.hashCode(accountOverdueStates);
+ return result;
+ }
+
+ @Override
+ public void writeExternal(final ObjectOutput out) throws IOException {
+ out.writeObject(initialReevaluationInterval);
+ out.writeObject(accountOverdueStates);
+ }
+
+ @Override
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.initialReevaluationInterval = (DefaultDuration) in.readObject();
+ this.accountOverdueStates = (DefaultOverdueState[]) in.readObject();
+ }
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStateSet.java b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStateSet.java
index af4a0cd..bfeff4c 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStateSet.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/config/DefaultOverdueStateSet.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -20,7 +22,6 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import org.joda.time.LocalDate;
-import org.joda.time.Period;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.overdue.api.OverdueApiException;
import org.killbill.billing.overdue.api.OverdueState;
@@ -33,7 +34,6 @@ import org.killbill.xmlloader.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
public abstract class DefaultOverdueStateSet extends ValidatingConfig<DefaultOverdueConfig> implements OverdueStateSet {
- private static final Period ZERO_PERIOD = new Period();
private final DefaultOverdueState clearState = new DefaultOverdueState().setName(OverdueWrapper.CLEAR_STATE_NAME).setClearState(true);
public abstract DefaultOverdueState[] getStates();
@@ -51,9 +51,6 @@ public abstract class DefaultOverdueStateSet extends ValidatingConfig<DefaultOve
throw new OverdueApiException(ErrorCode.CAT_NO_SUCH_OVERDUE_STATE, stateName);
}
- /* (non-Javadoc)
- * @see org.killbill.billing.catalog.overdue.OverdueBillingState#findClearState()
- */
@Override
public DefaultOverdueState getClearState() throws OverdueApiException {
return clearState;
@@ -80,7 +77,7 @@ public abstract class DefaultOverdueStateSet extends ValidatingConfig<DefaultOve
} catch (OverdueApiException e) {
if (e.getCode() == ErrorCode.CAT_MISSING_CLEAR_STATE.getCode()) {
errors.add("Overdue state set is missing a clear state.",
- root.getURI(), this.getClass(), "");
+ this.getClass(), "");
}
}
diff --git a/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java b/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
index 9a00618..3b509aa 100644
--- a/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
+++ b/overdue/src/main/java/org/killbill/billing/overdue/glue/DefaultOverdueModule.java
@@ -23,7 +23,7 @@ import org.killbill.billing.overdue.OverdueProperties;
import org.killbill.billing.overdue.OverdueService;
import org.killbill.billing.overdue.api.DefaultOverdueApi;
import org.killbill.billing.overdue.api.OverdueApi;
-import org.killbill.billing.overdue.caching.EhCacheOverdueConfigCache;
+import org.killbill.billing.overdue.caching.DefaultOverdueConfigCache;
import org.killbill.billing.overdue.caching.OverdueCacheInvalidationCallback;
import org.killbill.billing.overdue.caching.OverdueConfigCache;
import org.killbill.billing.overdue.listener.OverdueListener;
@@ -88,7 +88,7 @@ public class DefaultOverdueModule extends KillBillModule implements OverdueModul
}
public void installOverdueConfigCache() {
- bind(OverdueConfigCache.class).to(EhCacheOverdueConfigCache.class).asEagerSingleton();
+ bind(OverdueConfigCache.class).to(DefaultOverdueConfigCache.class).asEagerSingleton();
bind(CacheInvalidationCallback.class).annotatedWith(Names.named(OVERDUE_INVALIDATION_CALLBACK)).to(OverdueCacheInvalidationCallback.class).asEagerSingleton();
}
}
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/caching/MockOverdueConfigCache.java b/overdue/src/test/java/org/killbill/billing/overdue/caching/MockOverdueConfigCache.java
index 7d88488..26b6d03 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/caching/MockOverdueConfigCache.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/caching/MockOverdueConfigCache.java
@@ -24,7 +24,7 @@ import org.killbill.billing.overdue.api.OverdueApiException;
import org.killbill.billing.overdue.api.OverdueConfig;
import org.killbill.billing.util.cache.CacheControllerDispatcher;
-public class MockOverdueConfigCache extends EhCacheOverdueConfigCache implements OverdueConfigCache
+public class MockOverdueConfigCache extends DefaultOverdueConfigCache implements OverdueConfigCache
{
private OverdueConfig overwriteDefaultOverdueConfig;
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/config/io/TestConfig.java b/overdue/src/test/java/org/killbill/billing/overdue/config/io/TestConfig.java
index 1e16a8d..41ceda1 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/config/io/TestConfig.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/config/io/TestConfig.java
@@ -43,7 +43,7 @@ public class TestConfig extends OverdueTestSuiteNoDB {
final String overdueConfigStr = XMLWriter.writeXML(overdueConfig, DefaultOverdueConfig.class);
//System.err.println(overdueConfigStr);
- final DefaultOverdueConfig overdueConfig2 = XMLLoader.getObjectFromStream(new URI("dummy"), new ByteArrayInputStream(overdueConfigStr.getBytes(Charset.forName("UTF-8"))), DefaultOverdueConfig.class);
+ final DefaultOverdueConfig overdueConfig2 = XMLLoader.getObjectFromStream(new ByteArrayInputStream(overdueConfigStr.getBytes(Charset.forName("UTF-8"))), DefaultOverdueConfig.class);
final String overdueConfigStr2 = XMLWriter.writeXML(overdueConfig2, DefaultOverdueConfig.class);
Assert.assertEquals(overdueConfigStr, overdueConfigStr2);
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java b/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
index d9d06b0..52d8c9d 100644
--- a/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
+++ b/payment/src/main/java/org/killbill/billing/payment/glue/PaymentModule.java
@@ -23,7 +23,6 @@ import javax.inject.Provider;
import org.killbill.automaton.DefaultStateMachineConfig;
import org.killbill.automaton.StateMachineConfig;
import org.killbill.billing.control.plugin.api.PaymentControlPluginApi;
-import org.killbill.billing.invoice.api.InvoiceInternalApi;
import org.killbill.billing.osgi.api.OSGIServiceRegistration;
import org.killbill.billing.payment.api.AdminPaymentApi;
import org.killbill.billing.payment.api.DefaultAdminPaymentApi;
@@ -38,7 +37,7 @@ import org.killbill.billing.payment.api.PaymentService;
import org.killbill.billing.payment.api.svcs.DefaultInvoicePaymentInternalApi;
import org.killbill.billing.payment.bus.PaymentBusEventHandler;
import org.killbill.billing.payment.config.MultiTenantPaymentConfig;
-import org.killbill.billing.payment.caching.EhCacheStateMachineConfigCache;
+import org.killbill.billing.payment.caching.DefaultStateMachineConfigCache;
import org.killbill.billing.payment.caching.StateMachineConfigCache;
import org.killbill.billing.payment.caching.StateMachineConfigCacheInvalidationCallback;
import org.killbill.billing.payment.core.PaymentExecutors;
@@ -122,7 +121,7 @@ public class PaymentModule extends KillBillModule {
bind(PaymentControlStateMachineHelper.class).asEagerSingleton();
- bind(StateMachineConfigCache.class).to(EhCacheStateMachineConfigCache.class).asEagerSingleton();
+ bind(StateMachineConfigCache.class).to(DefaultStateMachineConfigCache.class).asEagerSingleton();
bind(CacheInvalidationCallback.class).annotatedWith(Names.named(STATE_MACHINE_CONFIG_INVALIDATION_CALLBACK)).to(StateMachineConfigCacheInvalidationCallback.class).asEagerSingleton();
bind(PaymentStateMachineHelper.class).asEagerSingleton();
diff --git a/payment/src/test/java/org/killbill/billing/payment/caching/TestStateMachineConfigCache.java b/payment/src/test/java/org/killbill/billing/payment/caching/TestStateMachineConfigCache.java
index db29761..ea2689c 100644
--- a/payment/src/test/java/org/killbill/billing/payment/caching/TestStateMachineConfigCache.java
+++ b/payment/src/test/java/org/killbill/billing/payment/caching/TestStateMachineConfigCache.java
@@ -97,7 +97,7 @@ public class TestStateMachineConfigCache extends PaymentTestSuiteNoDB {
}
});
- // Verify the lookup for a non-cached tenant. No system config is set yet but EhCacheStateMachineConfigCache returns a default empty one
+ // Verify the lookup for a non-cached tenant. No system config is set yet but DefaultStateMachineConfigCache returns a default empty one
final StateMachineConfig defaultStateMachineConfig = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, differentMultiTenantContext);
Assert.assertNotNull(defaultStateMachineConfig);
@@ -114,7 +114,6 @@ public class TestStateMachineConfigCache extends PaymentTestSuiteNoDB {
Assert.assertEquals(stateMachineConfigCache.getPaymentStateMachineConfig(UUID.randomUUID().toString(), multiTenantContext), defaultStateMachineConfig);
final StateMachineConfig result = stateMachineConfigCache.getPaymentStateMachineConfig(pluginName, multiTenantContext);
Assert.assertNotNull(result);
- Assert.assertNotEquals(result, defaultStateMachineConfig);
Assert.assertEquals(result.getStateMachines().length, 8);
// Verify the lookup for another tenant
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 334f2f2..02d1b7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
<parent>
<artifactId>killbill-oss-parent</artifactId>
<groupId>org.kill-bill.billing</groupId>
- <version>0.142.4</version>
+ <version>0.142.6</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.20.3-SNAPSHOT</version>
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
index d7ce566..5c9437f 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/modules/KillBillShiroWebModule.java
@@ -32,21 +32,21 @@ import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.guice.web.ShiroWebModuleWith435;
import org.apache.shiro.realm.Realm;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.util.WebUtils;
import org.killbill.billing.jaxrs.resources.JaxrsResource;
import org.killbill.billing.server.security.FirstSuccessfulStrategyWith540;
-import org.killbill.billing.server.security.KillBillWebSessionManager;
import org.killbill.billing.server.security.KillbillJdbcTenantRealm;
import org.killbill.billing.util.config.definition.RbacConfig;
import org.killbill.billing.util.glue.EhcacheShiroManagerProvider;
-import org.killbill.billing.util.glue.JDBCSessionDaoProvider;
import org.killbill.billing.util.glue.KillBillShiroModule;
import org.killbill.billing.util.glue.RealmsFromShiroIniProvider;
-import org.killbill.billing.util.security.shiro.dao.JDBCSessionDao;
+import org.killbill.billing.util.glue.SessionDAOProvider;
import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillOktaRealm;
@@ -118,10 +118,10 @@ public class KillBillShiroWebModule extends ShiroWebModuleWith435 {
protected void bindSessionManager(final AnnotatedBindingBuilder<SessionManager> bind) {
// Bypass the servlet container completely for session management and delegate it to Shiro.
// The default session timeout is 30 minutes.
- bind.to(KillBillWebSessionManager.class).asEagerSingleton();
+ bind.to(DefaultSessionManager.class).asEagerSingleton();
// Magic provider to configure the session DAO
- bind(JDBCSessionDao.class).toProvider(JDBCSessionDaoProvider.class).asEagerSingleton();
+ bind(SessionDAO.class).toProvider(SessionDAOProvider.class).asEagerSingleton();
}
public static final class CorsBasicHttpAuthenticationFilter extends BasicHttpAuthenticationFilter {
diff --git a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
index 7faf4f6..01c8960 100644
--- a/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
+++ b/profiles/killbill/src/main/java/org/killbill/billing/server/security/KillbillJdbcTenantRealm.java
@@ -33,9 +33,6 @@ import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.util.ByteSource;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
import org.killbill.billing.util.config.definition.SecurityConfig;
import org.killbill.billing.util.security.shiro.KillbillCredentialsMatcher;
@@ -133,12 +130,14 @@ public class KillbillJdbcTenantRealm extends JdbcRealm {
@Override
public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ this.bytes = new byte[in.readInt()];
+ in.read(this.bytes);
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeInt(bytes.length);
+ oo.write(bytes);
}
}
}
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/CallbackServlet.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/CallbackServlet.java
index bf0535d..d95ec8d 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/CallbackServlet.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/CallbackServlet.java
@@ -98,6 +98,28 @@ public class CallbackServlet extends HttpServlet {
}
}
+ public void flakyAssertListenerStatus() {
+ // Bail early
+ if (isListenerFailed) {
+ log.error(listenerFailedMsg);
+ Assert.fail(listenerFailedMsg);
+ }
+
+ try {
+ isCompleted(DELAY);
+ } catch (final Exception e) {
+ log.warn("flakyAssertListenerStatus didn't complete", e);
+ }
+
+ // Ignore missed events
+ nextExpectedEvent.clear();
+
+ if (isListenerFailed) {
+ log.error(listenerFailedMsg);
+ Assert.fail(listenerFailedMsg);
+ }
+ }
+
public synchronized void reset() {
receivedCalls.set(0);
forceToFail.set(false);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
index 4adf0a7..ec17e3c 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCache.java
@@ -88,6 +88,10 @@ public class TestCache extends TestJaxrsBase {
assertTrue(accountImmutableCache.isKeyInCache(accountRecordId));
assertTrue(accountBcdCache.isKeyInCache(input.getAccountId()));
+ // Make sure all events have been fully processed
+ clock.addDays(1);
+ callbackServlet.assertListenerStatus();
+
// invalidate caches per account level by accountId
adminApi.invalidatesCacheByAccount(input.getAccountId(), requestOptions);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
index 763036a..07448a0 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
@@ -322,7 +322,11 @@ public class TestJaxrsBase extends KillbillClient {
// Register tenant for callback
final String callback = callbackServer.getServletEndpoint();
tenantApi.registerPushNotificationCallback(callback, requestOptions);
- callbackServlet.assertListenerStatus();
+
+ // Use the flaky version... In the non-happy path, the catalog event sent during tenant creation is received
+ // before we had the chance to register our servlet. In this case, instead of 2 events, we will only see one
+ // and the flakyAssertListenerStatus will timeout but not fail the test
+ callbackServlet.flakyAssertListenerStatus();
createdTenant.setApiSecret(apiSecret);
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenant.java b/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenant.java
index dbda74f..e9acf05 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenant.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/DefaultTenant.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -27,9 +29,6 @@ import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.killbill.billing.tenant.dao.TenantModelDao;
import org.killbill.billing.util.UUIDs;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
public class DefaultTenant implements Tenant, Externalizable {
@@ -137,10 +136,10 @@ public class DefaultTenant implements Tenant, Externalizable {
if (id != null ? !id.equals(that.id) : that.id != null) {
return false;
}
- if (createdDate != null ? !createdDate.equals(that.createdDate) : that.createdDate != null) {
+ if (createdDate != null ? createdDate.compareTo(that.createdDate) != 0 : that.createdDate != null) {
return false;
}
- if (updatedDate != null ? !updatedDate.equals(that.updatedDate) : that.updatedDate != null) {
+ if (updatedDate != null ? updatedDate.compareTo(that.updatedDate) != 0 : that.updatedDate != null) {
return false;
}
if (externalKey != null ? !externalKey.equals(that.externalKey) : that.externalKey != null) {
@@ -165,11 +164,23 @@ public class DefaultTenant implements Tenant, Externalizable {
@Override
public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ this.id = new UUID(in.readLong(), in.readLong());
+ this.createdDate = new DateTime(in.readUTF());
+ this.updatedDate = new DateTime(in.readUTF());
+ this.externalKey = in.readBoolean() ? in.readUTF() : null;
+ this.apiKey = in.readUTF();
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeLong(id.getMostSignificantBits());
+ oo.writeLong(id.getLeastSignificantBits());
+ oo.writeUTF(createdDate.toString());
+ oo.writeUTF(updatedDate.toString());
+ oo.writeBoolean(externalKey != null);
+ if (externalKey != null) {
+ oo.writeUTF(externalKey);
+ }
+ oo.writeUTF(apiKey);
}
}
diff --git a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantConfigChangeInternalEvent.java b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantConfigChangeInternalEvent.java
index f62e80d..9c03bf7 100644
--- a/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantConfigChangeInternalEvent.java
+++ b/tenant/src/main/java/org/killbill/billing/tenant/api/user/DefaultTenantConfigChangeInternalEvent.java
@@ -57,4 +57,41 @@ public class DefaultTenantConfigChangeInternalEvent extends BusEventBase impleme
public BusInternalEventType getBusEventType() {
return BusInternalEventType.TENANT_CONFIG_CHANGE;
}
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("DefaultTenantConfigChangeInternalEvent{");
+ sb.append("id=").append(id);
+ sb.append(", key='").append(key).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ final DefaultTenantConfigChangeInternalEvent that = (DefaultTenantConfigChangeInternalEvent) o;
+
+ if (id != null ? !id.equals(that.id) : that.id != null) {
+ return false;
+ }
+ return key != null ? key.equals(that.key) : that.key == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (id != null ? id.hashCode() : 0);
+ result = 31 * result + (key != null ? key.hashCode() : 0);
+ return result;
+ }
}
diff --git a/util/src/main/java/org/killbill/billing/util/audit/dao/AuditLogModelDao.java b/util/src/main/java/org/killbill/billing/util/audit/dao/AuditLogModelDao.java
index 0c67fb0..b8be85f 100644
--- a/util/src/main/java/org/killbill/billing/util/audit/dao/AuditLogModelDao.java
+++ b/util/src/main/java/org/killbill/billing/util/audit/dao/AuditLogModelDao.java
@@ -25,11 +25,9 @@ import java.io.ObjectOutput;
import java.util.UUID;
import org.joda.time.DateTime;
+import org.killbill.billing.callcontext.DefaultCallContext;
import org.killbill.billing.util.audit.AuditLog;
import org.killbill.billing.util.audit.ChangeType;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.dao.EntityAudit;
import org.killbill.billing.util.dao.TableName;
@@ -43,7 +41,7 @@ public class AuditLogModelDao implements EntityModelDao<AuditLog>, Externalizabl
private TableName tableName;
private Long targetRecordId;
private ChangeType changeType;
- private CallContext callContext;
+ private DefaultCallContext callContext;
private Long recordId;
private Long accountRecordId;
@@ -52,7 +50,7 @@ public class AuditLogModelDao implements EntityModelDao<AuditLog>, Externalizabl
// For deserialization
public AuditLogModelDao() {}
- public AuditLogModelDao(final EntityAudit entityAudit, final CallContext callContext) {
+ public AuditLogModelDao(final EntityAudit entityAudit, final DefaultCallContext callContext) {
this.id = entityAudit.getId();
this.tableName = entityAudit.getTableName();
this.targetRecordId = entityAudit.getTargetRecordId();
@@ -188,12 +186,33 @@ public class AuditLogModelDao implements EntityModelDao<AuditLog>, Externalizabl
}
@Override
- public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ this.id = new UUID(in.readLong(), in.read());
+ this.createdDate = new DateTime(in.readUTF());
+ this.updatedDate = new DateTime(in.readUTF());
+ this.tableName = TableName.valueOf(in.readUTF());
+ this.targetRecordId = in.readLong();
+ this.changeType = ChangeType.valueOf(in.readUTF());
+ this.callContext = (DefaultCallContext) in.readObject();
+ this.recordId = in.readLong();
+ this.accountRecordId = in.readLong();
+ this.tenantRecordId = in.readLong();
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeLong(id.getMostSignificantBits());
+ oo.writeLong(id.getLeastSignificantBits());
+ oo.writeUTF(createdDate.toString());
+ oo.writeUTF(updatedDate.toString());
+ oo.writeUTF(tableName.name());
+ oo.writeLong(targetRecordId);
+ oo.writeUTF(changeType.name());
+
+ oo.writeObject(callContext);
+
+ oo.writeLong(recordId);
+ oo.writeLong(accountRecordId);
+ oo.writeLong(tenantRecordId);
}
}
diff --git a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
index 2ce2b6f..ce32de0 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
@@ -61,7 +61,7 @@ public class CacheControllerDispatcherProvider implements Provider<CacheControll
}
Preconditions.checkState(!cache.isClosed(), "Cache '%s' should not be closed", cacheType.getCacheName());
- final CacheController<Object, Object> ehCacheBasedCacheController = new EhCacheBasedCacheController<Object, Object>(cache, cacheLoader);
+ final CacheController<Object, Object> ehCacheBasedCacheController = new KillBillCacheController<Object, Object>(cache, cacheLoader);
cacheControllers.put(cacheType, ehCacheBasedCacheController);
}
diff --git a/util/src/main/java/org/killbill/billing/util/config/tenant/PerTenantConfig.java b/util/src/main/java/org/killbill/billing/util/config/tenant/PerTenantConfig.java
index 25a3f34..1dae3c9 100644
--- a/util/src/main/java/org/killbill/billing/util/config/tenant/PerTenantConfig.java
+++ b/util/src/main/java/org/killbill/billing/util/config/tenant/PerTenantConfig.java
@@ -23,10 +23,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
-import org.killbill.billing.util.cache.ExternalizableInput;
-import org.killbill.billing.util.cache.ExternalizableOutput;
-import org.killbill.billing.util.cache.MapperHolder;
-
public class PerTenantConfig extends HashMap<String, String> implements Externalizable {
private static final long serialVersionUID = 3887971108446630172L;
@@ -35,12 +31,21 @@ public class PerTenantConfig extends HashMap<String, String> implements External
}
@Override
- public void readExternal(final ObjectInput in) throws IOException {
- MapperHolder.mapper().readerForUpdating(this).readValue(new ExternalizableInput(in));
+ public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ final Object key = in.readObject();
+ final Object value = in.readObject();
+ put(String.valueOf(key), value == null ? null : String.valueOf(value));
+ }
}
@Override
public void writeExternal(final ObjectOutput oo) throws IOException {
- MapperHolder.mapper().writeValue(new ExternalizableOutput(oo), this);
+ oo.writeInt(size());
+ for (final String key : keySet()) {
+ oo.writeObject(key);
+ oo.writeObject(get(key));
+ }
}
}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
index cb7c571..40b55b5 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/CacheModule.java
@@ -45,6 +45,8 @@ import org.killbill.billing.util.config.definition.EhCacheConfig;
import org.skife.config.ConfigurationObjectFactory;
import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
+import com.google.inject.util.Providers;
public class CacheModule extends KillBillModule {
@@ -54,8 +56,8 @@ public class CacheModule extends KillBillModule {
@Override
protected void configure() {
- final EhCacheConfig config = new ConfigurationObjectFactory(skifeConfigSource).build(EhCacheConfig.class);
- bind(EhCacheConfig.class).toInstance(config);
+ final EhCacheConfig ehCacheConfig = new ConfigurationObjectFactory(skifeConfigSource).build(EhCacheConfig.class);
+ bind(EhCacheConfig.class).toInstance(ehCacheConfig);
// EhCache specifics
bind(CacheManager.class).toProvider(Eh107CacheManagerProvider.class).asEagerSingleton();
diff --git a/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java b/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
index 222dc7f..ceb312c 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
@@ -17,16 +17,9 @@
package org.killbill.billing.util.glue;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
import javax.cache.Cache;
import javax.cache.CacheManager;
-import javax.cache.configuration.MutableConfiguration;
-
-import org.killbill.billing.util.config.definition.EhCacheConfig;
-import org.killbill.xmlloader.UriAccessor;
+import javax.cache.configuration.Configuration;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricFilter;
@@ -40,28 +33,15 @@ abstract class CacheProviderBase {
private final MetricRegistry metricRegistry;
- final URL xmlConfigurationURL;
-
- CacheProviderBase(final MetricRegistry metricRegistry, final EhCacheConfig cacheConfig) {
+ CacheProviderBase(final MetricRegistry metricRegistry) {
this.metricRegistry = metricRegistry;
-
- try {
- xmlConfigurationURL = UriAccessor.toURL(cacheConfig.getCacheConfigLocation());
- } catch (final IOException e) {
- throw new RuntimeException(e);
- } catch (final URISyntaxException e) {
- throw new RuntimeException(e);
- }
}
- <K, V> Cache<K, V> createCache(final CacheManager cacheManager, final String cacheName, final Class<K> keyType, final Class<V> valueType) {
+ <C extends Configuration> void createCache(final CacheManager cacheManager, final String cacheName, final C configuration) {
// Make sure we start from a clean state - this is mainly useful for tests
cacheManager.destroyCache(cacheName);
- // All other configuration options come from the ehcache.xml
- final MutableConfiguration<K, V> configuration = new MutableConfiguration<K, V>().setTypes(keyType, valueType)
- .setStoreByValue(false); // Store by reference to avoid copying large objects (e.g. catalog)
- final Cache<K, V> cache = cacheManager.createCache(cacheName, configuration);
+ final Cache cache = cacheManager.createCache(cacheName, configuration);
Preconditions.checkState(!cache.isClosed(), "Cache '%s' should not be closed", cacheName);
// Re-create the metrics to support dynamically created caches (e.g. for Shiro)
@@ -72,7 +52,5 @@ abstract class CacheProviderBase {
}
});
metricRegistry.register(PROP_METRIC_REG_JCACHE_STATISTICS, new JCacheGaugeSet());
-
- return cache;
}
}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java b/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
index d5de5cc..49bf278 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
@@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
// EhCache specific provider
-public class Eh107CacheManagerProvider extends CacheProviderBase implements Provider<CacheManager> {
+public class Eh107CacheManagerProvider extends EhCacheProviderBase implements Provider<CacheManager> {
private static final Logger logger = LoggerFactory.getLogger(Eh107CacheManagerProvider.class);
private static final EhcacheLoggingListener ehcacheLoggingListener = new EhcacheLoggingListener();
@@ -54,7 +54,7 @@ public class Eh107CacheManagerProvider extends CacheProviderBase implements Prov
@Override
public CacheManager get() {
// JSR-107 registration, required for JMX integration
- final CachingProvider cachingProvider = Caching.getCachingProvider();
+ final CachingProvider cachingProvider = Caching.getCachingProvider("org.ehcache.jsr107.EhcacheCachingProvider");
CacheManager cacheManager;
try {
diff --git a/util/src/main/java/org/killbill/billing/util/glue/EhCacheProviderBase.java b/util/src/main/java/org/killbill/billing/util/glue/EhCacheProviderBase.java
new file mode 100644
index 0000000..924e766
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/EhCacheProviderBase.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2014-2017 Groupon, Inc
+ * Copyright 2014-2017 The Billing Project, LLC
+ *
+ * The Billing Project 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.killbill.billing.util.glue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.cache.CacheManager;
+import javax.cache.configuration.Configuration;
+import javax.cache.configuration.MutableConfiguration;
+
+import org.killbill.billing.util.config.definition.EhCacheConfig;
+import org.killbill.xmlloader.UriAccessor;
+
+import com.codahale.metrics.MetricRegistry;
+
+abstract class EhCacheProviderBase extends CacheProviderBase {
+
+ final URL xmlConfigurationURL;
+
+ EhCacheProviderBase(final MetricRegistry metricRegistry, final EhCacheConfig cacheConfig) {
+ super(metricRegistry);
+
+ try {
+ xmlConfigurationURL = UriAccessor.toURL(cacheConfig.getCacheConfigLocation());
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ } catch (final URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ <K, V> void createCache(final CacheManager cacheManager, final String cacheName, final Class<K> keyType, final Class<V> valueType) {
+ // All other configuration options come from the ehcache.xml
+ final Configuration configuration = new MutableConfiguration<K, V>().setTypes(keyType, valueType)
+ .setStoreByValue(false); // Store by reference to avoid copying large objects (e.g. catalog)
+ super.createCache(cacheManager, cacheName, configuration);
+ }
+}
diff --git a/util/src/main/java/org/killbill/billing/util/glue/EhcacheShiroManagerProvider.java b/util/src/main/java/org/killbill/billing/util/glue/EhcacheShiroManagerProvider.java
index 943450c..361fb8d 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/EhcacheShiroManagerProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/EhcacheShiroManagerProvider.java
@@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
import com.codahale.metrics.MetricRegistry;
-public class EhcacheShiroManagerProvider extends CacheProviderBase implements Provider<EhcacheShiroManager> {
+public class EhcacheShiroManagerProvider extends EhCacheProviderBase implements Provider<EhcacheShiroManager> {
private final SecurityManager securityManager;
private final CacheManager eh107CacheManager;
diff --git a/util/src/main/java/org/killbill/billing/util/glue/GlobalLockerModule.java b/util/src/main/java/org/killbill/billing/util/glue/GlobalLockerModule.java
index 6abfb5d..830b0dd 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/GlobalLockerModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/GlobalLockerModule.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2011 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
*
* The Billing Project 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
diff --git a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
index 154bc1d..07a9613 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/KillBillShiroModule.java
@@ -21,14 +21,12 @@ package org.killbill.billing.util.glue;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.guice.ShiroModule;
import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.util.config.definition.RbacConfig;
-import org.killbill.billing.util.config.definition.SecurityConfig;
-import org.killbill.billing.util.security.shiro.dao.JDBCSessionDao;
import org.killbill.billing.util.security.shiro.realm.KillBillJdbcRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillJndiLdapRealm;
import org.killbill.billing.util.security.shiro.realm.KillBillOktaRealm;
@@ -123,6 +121,6 @@ public class KillBillShiroModule extends ShiroModule {
bind.to(DefaultSessionManager.class).asEagerSingleton();
// Magic provider to configure the session DAO
- bind(JDBCSessionDao.class).toProvider(JDBCSessionDaoProvider.class).asEagerSingleton();
+ bind(SessionDAO.class).toProvider(SessionDAOProvider.class).asEagerSingleton();
}
}
diff --git a/util/src/test/java/org/killbill/billing/util/cache/TestKillBillCacheController.java b/util/src/test/java/org/killbill/billing/util/cache/TestKillBillCacheController.java
new file mode 100644
index 0000000..23d4f35
--- /dev/null
+++ b/util/src/test/java/org/killbill/billing/util/cache/TestKillBillCacheController.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
+ *
+ * The Billing Project 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.killbill.billing.util.cache;
+
+import javax.cache.Cache;
+import javax.cache.CacheException;
+
+import org.killbill.billing.util.UtilTestSuiteNoDB;
+import org.killbill.billing.util.cache.Cachable.CacheType;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestKillBillCacheController extends UtilTestSuiteNoDB {
+
+ @Test(groups = "fast")
+ public void testWithBrokenCache() {
+ final Cache cache = Mockito.mock(Cache.class, new Answer() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ // e.g. Redis connection broken
+ throw new CacheException("Exception for testing");
+ }
+ });
+
+ final BaseCacheLoader<String, Long> baseCacheLoader = new BaseCacheLoader<String, Long>() {
+ @Override
+ public CacheType getCacheType() {
+ return CacheType.RECORD_ID;
+ }
+
+ @Override
+ public Long compute(final String key, final CacheLoaderArgument cacheLoaderArgument) {
+ return Long.valueOf(key);
+ }
+ };
+
+ final KillBillCacheController<String, Long> killBillCacheController = new KillBillCacheController<String, Long>(cache, baseCacheLoader);
+
+ try {
+ killBillCacheController.getKeys();
+ Assert.fail();
+ } catch (final CacheException e) {
+ // Nothing we can do
+ }
+
+ // This will go back to the cache loader
+ Assert.assertEquals(killBillCacheController.get("12", null), new Long(12));
+ }
+}