package org.ow2.choreos.selectors; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Return always the same object. * * @author leonardo * * @param <T> * @param <R> */ public class SingletonSelector<T, R> implements Selector<T, R> { private T theObject; private ObjectFactory<T, R> factory; private ExecutorService executor = Executors.newSingleThreadExecutor(); boolean creating = false; public SingletonSelector(ObjectFactory<T, R> factory) { this.factory = factory; } @Override public List<T> select(R requirements, int objectsQuantity) throws NotSelectedException { if (objectsQuantity != 1) throw new IllegalArgumentException("Current implementation supports only objectsQuantity=1"); createObjectIfNecessary(requirements); if (objectIsBeenCreated()) waitObjectCreation(); if (objectIsNotCreated()) throw new NotSelectedException(); return Collections.singletonList(theObject); } private void createObjectIfNecessary(R requirements) { if (objectIsNotCreated() && !objectIsBeenCreated()) { synchronized (this) { if (objectIsNotCreated() && !objectIsBeenCreated()) { createTheObject(requirements); } } } } private void createTheObject(R requirements) { creating = true; CreationTask task = new CreationTask(requirements); executor.submit(task); executor.shutdown(); } private boolean objectIsNotCreated() { return theObject == null; } private boolean objectIsBeenCreated() { return creating; } private void waitObjectCreation() throws NotSelectedException { boolean ok = false; try { ok = executor.awaitTermination(factory.getTimeoutInSeconds(), TimeUnit.SECONDS); } catch (InterruptedException e) { throw new NotSelectedException(); } if (!ok) { throw new NotSelectedException(); } } private class CreationTask implements Runnable { R requirements; CreationTask(R requirements) { this.requirements = requirements; } @Override public void run() { try { theObject = factory.createNewInstance(requirements); } catch (ObjectCreationException e) { theObject = null; } creating = false; } } }