Java tutorial
/* * Copyright 2006-2012 Amazon Technologies, Inc. or its affiliates. * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks * of Amazon Technologies, Inc. or its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.amazon.carbonado.spi; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.Log; import com.amazon.carbonado.IsolationLevel; import com.amazon.carbonado.Repository; import com.amazon.carbonado.RepositoryBuilder; import com.amazon.carbonado.RepositoryException; import com.amazon.carbonado.Storable; import com.amazon.carbonado.Storage; import com.amazon.carbonado.SupportException; import com.amazon.carbonado.Transaction; import com.amazon.carbonado.capability.Capability; import com.amazon.carbonado.util.BelatedCreator; /** * Generic one-shot Repository builder which supports late object creation. If * the Repository building results in an exception or is taking too long, the * Repository produced instead is a bogus one. Many operations result in an * IllegalStateException. After retrying, if the real Repository is created, * then the bogus Repository turns into a wrapper to the real Repository. * * @author Brian S O'Neill * @see BelatedStorageCreator */ public class BelatedRepositoryCreator extends BelatedCreator<Repository, SupportException> { final Log mLog; final RepositoryBuilder mBuilder; final AtomicReference<Repository> mRootRef; private boolean mRetry; /** * @param log error reporting log * @param builder builds real Repository * @param minRetryDelayMillis minimum milliseconds to wait before retrying * to create object after failure; if negative, never retry */ public BelatedRepositoryCreator(Log log, RepositoryBuilder builder, int minRetryDelayMillis) { this(log, builder, new AtomicReference<Repository>(), minRetryDelayMillis); } /** * @param log error reporting log * @param builder builds real Repository * @param rootRef reference to root repository * @param minRetryDelayMillis minimum milliseconds to wait before retrying * to create object after failure; if negative, never retry */ public BelatedRepositoryCreator(Log log, RepositoryBuilder builder, AtomicReference<Repository> rootRef, int minRetryDelayMillis) { super(Repository.class, minRetryDelayMillis); mLog = log; mBuilder = builder; mRootRef = rootRef; } @Override protected Repository createReal() throws SupportException { // For first attempt, use the real root reference. For retries, it // should not be used because it will destroy the root which was // successfully built and is in use. Instead, pass a dummy ref. AtomicReference<Repository> rootRef = mRetry ? new AtomicReference<Repository>() : mRootRef; mRetry = true; Exception error; try { return mBuilder.build(rootRef); } catch (SupportException e) { // Cannot recover from this. throw e; } catch (RepositoryException e) { Throwable cause = e.getCause(); if (cause instanceof ClassNotFoundException) { // If a class cannot be loaded, then I don't expect this to be // a recoverable situation. throw new SupportException(cause); } error = e; } catch (Exception e) { error = e; } mLog.error("Error building Repository \"" + mBuilder.getName() + '"', error); return null; } @Override protected Repository createBogus() { return new BogusRepository(); } @Override protected void timedOutNotification(long timedOutMillis) { mLog.error("Timed out waiting for Repository \"" + mBuilder.getName() + "\" to build after waiting " + timedOutMillis + " milliseconds"); } private class BogusRepository implements Repository { public String getName() { return mBuilder.getName(); } public synchronized <S extends Storable> Storage<S> storageFor(Class<S> type) { throw error(); } public Transaction enterTransaction() { throw error(); } public Transaction enterTransaction(IsolationLevel level) { throw error(); } public Transaction enterTopTransaction(IsolationLevel level) { throw error(); } public IsolationLevel getTransactionIsolationLevel() { return null; } public <C extends Capability> C getCapability(Class<C> capabilityType) { throw error(); } public void close() { } public boolean isClosed() { return false; } private IllegalStateException error() { return new IllegalStateException("Creation of Repository \"" + mBuilder.getName() + "\" is delayed"); } } }