/* * Copyright © 2013. Palomino Labs (http://palominolabs.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.palominolabs.crm.sf.soap; import com.codahale.metrics.MetricRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; import java.util.HashMap; import java.util.Map; /* * silence complaints about the static logger */ @SuppressWarnings("AccessToStaticFieldLockedOnInstance") @ThreadSafe public final class ConnectionPoolImpl<T> implements ConnectionPool<T> { private static final Logger logger = LoggerFactory.getLogger(ConnectionPoolImpl.class); private static final BundleFactory NORMAL_BUNDLE_FACTORY = new NormalBundleFactory(); private static final BundleFactory SANDBOX_BUNDLE_FACTORY = new SandboxBundleFactory(); private final Map<T, ConnectionBundleImpl> orgIdToBundleMap = new HashMap<T, ConnectionBundleImpl>(); private final Map<T, ConnectionBundleImpl> orgIdToSandboxBundleMap = new HashMap<T, ConnectionBundleImpl>(); private final BindingRepository bindingRepository; private final MetricRegistry metricRegistry; /** * @param partnerKey Your partner key assigned to you by Salesforce. * @param metricRegistry The metric registry that the SF classes should use for metrics. */ public ConnectionPoolImpl(@Nonnull String partnerKey, MetricRegistry metricRegistry) { this.metricRegistry = metricRegistry; this.bindingRepository = new BindingRepository(partnerKey, metricRegistry); } @Nonnull @Override public synchronized ConnectionBundle getConnectionBundle(@Nonnull T orgIdentifier) { return getConnectionBundleImpl(this.orgIdToBundleMap, orgIdentifier); } @Nonnull @Override public synchronized ConnectionBundle getSandboxConnectionBundle(@Nonnull T orgIdentifier) { return getConnectionBundleImpl(this.orgIdToSandboxBundleMap, orgIdentifier); } private ConnectionBundle getConnectionBundleImpl(Map<T, ConnectionBundleImpl> bundles, T orgId) { ConnectionBundle cp = bundles.get(orgId); if (cp == null) { throw new IllegalStateException( "The ConnectionBundle for org id <" + orgId + "> has not been configured yet!"); } return cp; } @Override public synchronized void configureOrg(@Nonnull T orgId, @Nonnull String username, @Nonnull String password, int maxConcurrentApiCalls) { configureOrgImpl(orgId, username, password, maxConcurrentApiCalls, this.orgIdToBundleMap, NORMAL_BUNDLE_FACTORY); } @Override public synchronized void configureSandboxOrg(@Nonnull T orgId, @Nonnull String username, @Nonnull String password, int maxConcurrentApiCalls) { configureOrgImpl(orgId, username, password, maxConcurrentApiCalls, this.orgIdToSandboxBundleMap, SANDBOX_BUNDLE_FACTORY); } private void configureOrgImpl(T orgId, String username, String password, int maxConcurrentApiCalls, Map<T, ConnectionBundleImpl> bundles, BundleFactory bundleFactory) { ConnectionBundleImpl cp = bundles.get(orgId); if (cp == null) { logger.debug("Initial configuration for org " + orgId); bundles.put(orgId, bundleFactory.getBundle(this.bindingRepository, username, password, maxConcurrentApiCalls, metricRegistry)); } else { logger.debug("Updating existing configuration for org " + orgId); cp.updateCredentials(username, password, maxConcurrentApiCalls); } } @ThreadSafe private static interface BundleFactory { @Nonnull ConnectionBundleImpl getBundle(@Nonnull BindingRepository bindingRepository, @Nonnull String username, @Nonnull String password, int maxConcurrentApiCalls, MetricRegistry metricRegistry); } @Immutable private static class NormalBundleFactory implements BundleFactory { @Nonnull @Override public ConnectionBundleImpl getBundle(@Nonnull BindingRepository bindingRepository, @Nonnull String username, @Nonnull String password, int maxConcurrentApiCalls, MetricRegistry metricRegistry) { return ConnectionBundleImpl .getNew(bindingRepository, username, password, maxConcurrentApiCalls, metricRegistry); } } @Immutable private static class SandboxBundleFactory implements BundleFactory { @Nonnull @Override public ConnectionBundleImpl getBundle(@Nonnull BindingRepository bindingRepository, @Nonnull String username, @Nonnull String password, int maxConcurrentApiCalls, MetricRegistry metricRegistry) { return ConnectionBundleImpl .getNewForSandbox(bindingRepository, username, password, maxConcurrentApiCalls, metricRegistry); } } }