Search in sources :

Example 1 with VersionedCatalog

use of org.killbill.billing.catalog.VersionedCatalog in project killbill by killbill.

the class VersionedCatalogLoader method loadDefaultCatalog.

@Override
public VersionedCatalog loadDefaultCatalog(final String uriString) throws CatalogApiException {
    try {
        final List<URI> xmlURIs;
        if (uriString.endsWith(XML_EXTENSION)) {
            // Assume its an xml file
            xmlURIs = new ArrayList<URI>();
            xmlURIs.add(new URI(uriString));
        } else {
            // Assume its a directory
            final URL url = getURLFromString(uriString);
            final String directoryContents = UriAccessor.accessUriAsString(uriString);
            xmlURIs = findXmlReferences(directoryContents, url);
        }
        final VersionedCatalog result = new VersionedCatalog(clock);
        for (final URI u : xmlURIs) {
            final StandaloneCatalog catalog = XMLLoader.getObjectFromUri(u, StandaloneCatalog.class);
            result.add(new StandaloneCatalogWithPriceOverride(catalog, priceOverride, InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID, internalCallContextFactory));
        }
        // Perform initialization and validation for VersionedCatalog
        XMLLoader.initializeAndValidate(new URI(uriString), result);
        return result;
    } catch (final ValidationException e) {
        logger.warn("Failed to load default catalog", e);
        throw new CatalogApiException(e, ErrorCode.CAT_INVALID_DEFAULT, uriString);
    } catch (final JAXBException e) {
        logger.warn("Failed to load default catalog", e);
        throw new CatalogApiException(e, ErrorCode.CAT_INVALID_DEFAULT, uriString);
    } catch (IllegalArgumentException e) {
        logger.warn("Failed to load default catalog", e);
        throw new CatalogApiException(e, ErrorCode.CAT_INVALID_DEFAULT, uriString);
    } catch (Exception e) {
        logger.warn("Failed to load default catalog", e);
        throw new IllegalStateException(e);
    }
}
Also used : StandaloneCatalogWithPriceOverride(org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride) ValidationException(org.killbill.xmlloader.ValidationException) JAXBException(javax.xml.bind.JAXBException) URI(java.net.URI) URL(java.net.URL) TransformerException(javax.xml.transform.TransformerException) InvalidConfigException(org.killbill.billing.catalog.api.InvalidConfigException) URISyntaxException(java.net.URISyntaxException) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) JAXBException(javax.xml.bind.JAXBException) SAXException(org.xml.sax.SAXException) ValidationException(org.killbill.xmlloader.ValidationException) VersionedCatalog(org.killbill.billing.catalog.VersionedCatalog) StandaloneCatalog(org.killbill.billing.catalog.StandaloneCatalog) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) PriceOverride(org.killbill.billing.catalog.override.PriceOverride) StandaloneCatalogWithPriceOverride(org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride)

Example 2 with VersionedCatalog

use of org.killbill.billing.catalog.VersionedCatalog in project killbill by killbill.

the class TestEhCacheCatalogCache method testExistingTenantCatalog.

//
// Verify CatalogCache returns per tenant catalog:
// 1. We first mock TenantInternalApi to return a different catalog than the default one
// 2. We then mock TenantInternalApi to throw RuntimeException which means catalog was cached and there was no additional call
//    to the TenantInternalApi api (otherwise test would fail with RuntimeException)
//
@Test(groups = "fast")
public void testExistingTenantCatalog() throws CatalogApiException, URISyntaxException, IOException {
    final InternalCallContext differentMultiTenantContext = Mockito.mock(InternalCallContext.class);
    Mockito.when(differentMultiTenantContext.getTenantRecordId()).thenReturn(55667788L);
    final AtomicBoolean shouldThrow = new AtomicBoolean(false);
    final Long multiTenantRecordId = multiTenantContext.getTenantRecordId();
    final Long otherMultiTenantRecordId = otherMultiTenantContext.getTenantRecordId();
    final InputStream tenantInputCatalog = UriAccessor.accessUri(new URI(Resources.getResource("SpyCarAdvanced.xml").toExternalForm()));
    final String tenantCatalogXML = CharStreams.toString(new InputStreamReader(tenantInputCatalog, "UTF-8"));
    final InputStream otherTenantInputCatalog = UriAccessor.accessUri(new URI(Resources.getResource("SpyCarBasic.xml").toExternalForm()));
    final String otherTenantCatalogXML = CharStreams.toString(new InputStreamReader(otherTenantInputCatalog, "UTF-8"));
    Mockito.when(tenantInternalApi.getTenantCatalogs(Mockito.any(InternalTenantContext.class))).thenAnswer(new Answer<List<String>>() {

        @Override
        public List<String> answer(final InvocationOnMock invocation) throws Throwable {
            if (shouldThrow.get()) {
                throw new RuntimeException();
            }
            final InternalTenantContext internalContext = (InternalTenantContext) invocation.getArguments()[0];
            if (multiTenantRecordId.equals(internalContext.getTenantRecordId())) {
                return ImmutableList.<String>of(tenantCatalogXML);
            } else if (otherMultiTenantRecordId.equals(internalContext.getTenantRecordId())) {
                return ImmutableList.<String>of(otherTenantCatalogXML);
            } else {
                return ImmutableList.<String>of();
            }
        }
    });
    // Verify the lookup for a non-cached tenant. No system config is set yet but EhCacheCatalogCache returns a default empty one
    VersionedCatalog differentResult = catalogCache.getCatalog(true, true, differentMultiTenantContext);
    Assert.assertNotNull(differentResult);
    Assert.assertEquals(differentResult.getCatalogName(), "EmptyCatalog");
    // Make sure the cache loader isn't invoked, see https://github.com/killbill/killbill/issues/300
    shouldThrow.set(true);
    differentResult = catalogCache.getCatalog(true, true, differentMultiTenantContext);
    Assert.assertNotNull(differentResult);
    Assert.assertEquals(differentResult.getCatalogName(), "EmptyCatalog");
    shouldThrow.set(false);
    // Set a default config
    catalogCache.loadDefaultCatalog(Resources.getResource("SpyCarBasic.xml").toExternalForm());
    // Verify the lookup for this tenant
    final VersionedCatalog result = catalogCache.getCatalog(true, true, multiTenantContext);
    Assert.assertNotNull(result);
    final Collection<Product> products = result.getProducts(clock.getUTCNow());
    Assert.assertEquals(products.size(), 6);
    // Verify the lookup for another tenant
    final VersionedCatalog otherResult = catalogCache.getCatalog(true, true, otherMultiTenantContext);
    Assert.assertNotNull(otherResult);
    final Collection<Product> otherProducts = otherResult.getProducts(clock.getUTCNow());
    Assert.assertEquals(otherProducts.size(), 3);
    shouldThrow.set(true);
    // Verify the lookup for this tenant
    final VersionedCatalog result2 = catalogCache.getCatalog(true, true, multiTenantContext);
    Assert.assertEquals(result2, result);
    // Verify the lookup with another context for the same tenant
    final InternalCallContext sameMultiTenantContext = Mockito.mock(InternalCallContext.class);
    Mockito.when(sameMultiTenantContext.getAccountRecordId()).thenReturn(9102L);
    Mockito.when(sameMultiTenantContext.getTenantRecordId()).thenReturn(multiTenantRecordId);
    Assert.assertEquals(catalogCache.getCatalog(true, true, sameMultiTenantContext), result);
    // Verify the lookup with the other tenant
    Assert.assertEquals(catalogCache.getCatalog(true, true, otherMultiTenantContext), otherResult);
}
Also used : InputStreamReader(java.io.InputStreamReader) InputStream(java.io.InputStream) DefaultProduct(org.killbill.billing.catalog.DefaultProduct) Product(org.killbill.billing.catalog.api.Product) InternalCallContext(org.killbill.billing.callcontext.InternalCallContext) URI(java.net.URI) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) VersionedCatalog(org.killbill.billing.catalog.VersionedCatalog) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) InvocationOnMock(org.mockito.invocation.InvocationOnMock) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) StandaloneCatalogWithPriceOverride(org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride) Test(org.testng.annotations.Test)

Example 3 with VersionedCatalog

use of org.killbill.billing.catalog.VersionedCatalog in project killbill by killbill.

the class CatalogResource method getCatalogJson.

@TimedResource
@GET
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Retrieve the catalog as JSON", response = StaticCatalog.class)
@ApiResponses(value = {})
public Response getCatalogJson(@QueryParam(QUERY_REQUESTED_DT) final String requestedDate, @javax.ws.rs.core.Context final HttpServletRequest request) throws Exception {
    final TenantContext tenantContext = context.createContext(request);
    final DateTime catalogDateVersion = requestedDate != null ? DATE_TIME_FORMATTER.parseDateTime(requestedDate).toDateTime(DateTimeZone.UTC) : null;
    // Yack...
    final VersionedCatalog catalog = (VersionedCatalog) catalogUserApi.getCatalog(catalogName, tenantContext);
    final List<CatalogJson> result = new ArrayList<CatalogJson>();
    if (catalogDateVersion != null) {
        result.add(new CatalogJson(catalog, catalogDateVersion));
    } else {
        for (final StandaloneCatalog v : catalog.getVersions()) {
            result.add(new CatalogJson(catalog, new DateTime(v.getEffectiveDate())));
        }
    }
    return Response.status(Status.OK).entity(result).build();
}
Also used : VersionedCatalog(org.killbill.billing.catalog.VersionedCatalog) StandaloneCatalog(org.killbill.billing.catalog.StandaloneCatalog) ArrayList(java.util.ArrayList) TenantContext(org.killbill.billing.util.callcontext.TenantContext) CatalogJson(org.killbill.billing.jaxrs.json.CatalogJson) DateTime(org.joda.time.DateTime) TimedResource(org.killbill.commons.metrics.TimedResource) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) ApiOperation(io.swagger.annotations.ApiOperation) ApiResponses(io.swagger.annotations.ApiResponses)

Example 4 with VersionedCatalog

use of org.killbill.billing.catalog.VersionedCatalog in project killbill by killbill.

the class DefaultCatalogUserApi method uploadCatalog.

@Override
public void uploadCatalog(final String catalogXML, final CallContext callContext) throws CatalogApiException {
    final InternalTenantContext internalTenantContext = createInternalTenantContext(callContext);
    try {
        final VersionedCatalog versionedCatalog = (VersionedCatalog) catalogService.getFullCatalog(false, true, internalTenantContext);
        // 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);
        if (versionedCatalog != null) {
            // currentCatalog.getCatalogName() could be null if tenant was created with a default catalog
            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, "");
                // Bummer ValidationException CTOR is private to package...
                //final ValidationException validationException = new ValidationException(errors);
                //throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
                logger.info("Failed to load new catalog version: " + errors.toString());
                throw new CatalogApiException(ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
            }
            for (StandaloneCatalog c : versionedCatalog.getVersions()) {
                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, "");
                    // Bummer ValidationException CTOR is private to package...
                    //final ValidationException validationException = new ValidationException(errors);
                    //throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
                    logger.info("Failed to load new catalog version: " + errors.toString());
                    throw new CatalogApiException(ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
                }
            }
        }
        catalogCache.clearCatalog(internalTenantContext);
        tenantApi.addTenantKeyValue(TenantKey.CATALOG.toString(), catalogXML, callContext);
    } catch (final TenantApiException e) {
        throw new CatalogApiException(e);
    } catch (final ValidationException e) {
        throw new CatalogApiException(e, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
    } catch (final JAXBException e) {
        throw new CatalogApiException(e, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
    } catch (final IOException e) {
        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);
    }
}
Also used : ValidationException(org.killbill.xmlloader.ValidationException) ValidationErrors(org.killbill.xmlloader.ValidationErrors) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) JAXBException(javax.xml.bind.JAXBException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) InvalidConfigException(org.killbill.billing.catalog.api.InvalidConfigException) StaticCatalog(org.killbill.billing.catalog.api.StaticCatalog) URI(java.net.URI) SAXException(org.xml.sax.SAXException) VersionedCatalog(org.killbill.billing.catalog.VersionedCatalog) ByteArrayInputStream(java.io.ByteArrayInputStream) InternalTenantContext(org.killbill.billing.callcontext.InternalTenantContext) TenantApiException(org.killbill.billing.tenant.api.TenantApiException) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) StandaloneCatalog(org.killbill.billing.catalog.StandaloneCatalog) TransformerException(javax.xml.transform.TransformerException)

Example 5 with VersionedCatalog

use of org.killbill.billing.catalog.VersionedCatalog in project killbill by killbill.

the class EhCacheCatalogCache method getCatalog.

@Override
public VersionedCatalog getCatalog(final boolean useDefaultCatalog, final boolean filterTemplateCatalog, final InternalTenantContext tenantContext) throws CatalogApiException {
    // STEPH TODO what are the possibilities for caching here ?
    final VersionedCatalog pluginVersionedCatalog = getCatalogFromPlugins(tenantContext);
    if (pluginVersionedCatalog != null) {
        return pluginVersionedCatalog;
    }
    if (tenantContext.getTenantRecordId() == InternalCallContextFactory.INTERNAL_TENANT_RECORD_ID) {
        return useDefaultCatalog ? defaultCatalog : null;
    }
    // but to be on the safe side;;
    try {
        VersionedCatalog tenantCatalog = (VersionedCatalog) cacheController.get(tenantContext.getTenantRecordId(), filterTemplateCatalog ? cacheLoaderArgumentWithTemplateFiltering : cacheLoaderArgument);
        // for test purpose.
        if (useDefaultCatalog && tenantCatalog == null) {
            tenantCatalog = new VersionedCatalog(defaultCatalog.getClock());
            for (final StandaloneCatalog cur : defaultCatalog.getVersions()) {
                final StandaloneCatalogWithPriceOverride curWithOverride = new StandaloneCatalogWithPriceOverride(cur, priceOverride, tenantContext.getTenantRecordId(), internalCallContextFactory);
                tenantCatalog.add(curWithOverride);
            }
            cacheController.add(tenantContext.getTenantRecordId(), tenantCatalog);
        }
        return tenantCatalog;
    } catch (final IllegalStateException e) {
        throw new CatalogApiException(ErrorCode.CAT_INVALID_FOR_TENANT, tenantContext.getTenantRecordId());
    }
}
Also used : StandaloneCatalogWithPriceOverride(org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride) VersionedCatalog(org.killbill.billing.catalog.VersionedCatalog) StandaloneCatalog(org.killbill.billing.catalog.StandaloneCatalog) CatalogApiException(org.killbill.billing.catalog.api.CatalogApiException) PriceOverride(org.killbill.billing.catalog.override.PriceOverride) StandaloneCatalogWithPriceOverride(org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride)

Aggregations

VersionedCatalog (org.killbill.billing.catalog.VersionedCatalog)12 StandaloneCatalog (org.killbill.billing.catalog.StandaloneCatalog)8 Test (org.testng.annotations.Test)7 StandaloneCatalogWithPriceOverride (org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride)5 URI (java.net.URI)4 DateTime (org.joda.time.DateTime)4 CatalogApiException (org.killbill.billing.catalog.api.CatalogApiException)4 IOException (java.io.IOException)3 InputStream (java.io.InputStream)3 URISyntaxException (java.net.URISyntaxException)3 JAXBException (javax.xml.bind.JAXBException)3 TransformerException (javax.xml.transform.TransformerException)3 InvalidConfigException (org.killbill.billing.catalog.api.InvalidConfigException)3 ValidationException (org.killbill.xmlloader.ValidationException)3 SAXException (org.xml.sax.SAXException)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 InternalTenantContext (org.killbill.billing.callcontext.InternalTenantContext)2 DefaultProduct (org.killbill.billing.catalog.DefaultProduct)2 Product (org.killbill.billing.catalog.api.Product)2 PriceOverride (org.killbill.billing.catalog.override.PriceOverride)2