001/* 002 * CREDIT SUISSE IS WILLING TO LICENSE THIS SPECIFICATION TO YOU ONLY UPON THE CONDITION THAT YOU 003 * ACCEPT ALL OF THE TERMS CONTAINED IN THIS AGREEMENT. PLEASE READ THE TERMS AND CONDITIONS OF THIS 004 * AGREEMENT CAREFULLY. BY DOWNLOADING THIS SPECIFICATION, YOU ACCEPT THE TERMS AND CONDITIONS OF 005 * THE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY IT, SELECT THE "DECLINE" BUTTON AT THE 006 * BOTTOM OF THIS PAGE. Specification: JSR-354 Money and Currency API ("Specification") Copyright 007 * (c) 2012-2013, Credit Suisse All rights reserved. 008 */ 009package org.javamoney.moneta.internal; 010 011import javax.annotation.Priority; 012import javax.money.spi.ServiceProvider; 013import java.util.ArrayList; 014import java.util.Collections; 015import java.util.List; 016import java.util.ServiceLoader; 017import java.util.concurrent.ConcurrentHashMap; 018import java.util.logging.Level; 019import java.util.logging.Logger; 020 021/** 022 * This class implements the (default) {@link javax.money.spi.ServiceProvider} interface and hereby uses the JDK 023 * {@link java.util.ServiceLoader} to load the services required. 024 * 025 * @author Anatole Tresch 026 */ 027public class PriorityAwareServiceProvider implements ServiceProvider { 028 /** 029 * List of services loaded, per class. 030 */ 031 private final ConcurrentHashMap<Class, List<Object>> servicesLoaded = new ConcurrentHashMap<>(); 032 033 /** 034 * Returns a prioritx value of 10. 035 * 036 * @return 10, overriding the default provider. 037 */ 038 @Override 039 public int getPriority() { 040 return 10; 041 } 042 043 /** 044 * Loads and registers services. 045 * 046 * @param serviceType The service type. 047 * @param <T> the concrete type. 048 * @param defaultList the list of items returned, if no services were found. 049 * @return the items found, never {@code null}. 050 */ 051 @Override 052 public <T> List<T> getServices(final Class<T> serviceType) { 053 @SuppressWarnings("unchecked") 054 List<T> found = (List<T>) servicesLoaded.get(serviceType); 055 if (found != null) { 056 return found; 057 } 058 059 return loadServices(serviceType); 060 } 061 062 public static int compareServices(Object o1, Object o2) { 063 int prio1 = 0; 064 int prio2 = 0; 065 Priority prio1Annot = o1.getClass().getAnnotation(Priority.class); 066 if (prio1Annot != null) { 067 prio1 = prio1Annot.value(); 068 } 069 Priority prio2Annot = o2.getClass().getAnnotation(Priority.class); 070 if (prio2Annot != null) { 071 prio2 = prio2Annot.value(); 072 } 073 if (prio1 < prio2) { 074 return 1; 075 } 076 if (prio2 < prio1) { 077 return -1; 078 } 079 return o2.getClass().getSimpleName().compareTo(o1.getClass().getSimpleName()); 080 } 081 082 /** 083 * Loads and registers services. 084 * 085 * @param serviceType The service type. 086 * @param <T> the concrete type. 087 * @param defaultList the list of items returned, if no services were found. 088 * @return the items found, never {@code null}. 089 */ 090 private <T> List<T> loadServices(final Class<T> serviceType) { 091 List<T> services = new ArrayList<>(); 092 try { 093 for (T t : ServiceLoader.load(serviceType)) { 094 services.add(t); 095 } 096 services.sort(PriorityAwareServiceProvider::compareServices); 097 @SuppressWarnings("unchecked") 098 final List<T> previousServices = (List<T>) servicesLoaded.putIfAbsent(serviceType, (List<Object>) services); 099 return Collections.unmodifiableList(previousServices != null ? previousServices : services); 100 } catch (Exception e) { 101 Logger.getLogger(PriorityAwareServiceProvider.class.getName()).log(Level.WARNING, 102 "Error loading services of type " + serviceType, e); 103 services.sort(PriorityAwareServiceProvider::compareServices); 104 return services; 105 } 106 } 107 108}