001/** 002 * Copyright (c) 2012, 2014, Credit Suisse (Anatole Tresch), Werner Keil and others by the @author tag. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016package org.javamoney.moneta.internal; 017 018import javax.annotation.Priority; 019import javax.money.spi.ServiceProvider; 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.List; 023import java.util.ServiceLoader; 024import java.util.concurrent.ConcurrentHashMap; 025import java.util.logging.Level; 026import java.util.logging.Logger; 027 028/** 029 * This class implements the (default) {@link javax.money.spi.ServiceProvider} interface and hereby uses the JDK 030 * {@link java.util.ServiceLoader} to load the services required. 031 * 032 * @author Anatole Tresch 033 */ 034public class PriorityAwareServiceProvider implements ServiceProvider { 035 /** 036 * List of services loaded, per class. 037 */ 038 private final ConcurrentHashMap<Class, List<Object>> servicesLoaded = new ConcurrentHashMap<>(); 039 040 /** 041 * Returns a priority value of 10. 042 * 043 * @return 10, overriding the default provider. 044 */ 045 @Override 046 public int getPriority() { 047 return 10; 048 } 049 050 /** 051 * Loads and registers services. 052 * 053 * @param serviceType The service type. 054 * @param <T> the concrete type. 055 * @return the items found, never {@code null}. 056 */ 057 @Override 058 public <T> List<T> getServices(final Class<T> serviceType) { 059 @SuppressWarnings("unchecked") 060 List<T> found = (List<T>) servicesLoaded.get(serviceType); 061 if (found != null) { 062 return found; 063 } 064 065 return loadServices(serviceType); 066 } 067 068 public static int compareServices(Object o1, Object o2) { 069 int prio1 = 0; 070 int prio2 = 0; 071 Priority prio1Annot = o1.getClass().getAnnotation(Priority.class); 072 if (prio1Annot != null) { 073 prio1 = prio1Annot.value(); 074 } 075 Priority prio2Annot = o2.getClass().getAnnotation(Priority.class); 076 if (prio2Annot != null) { 077 prio2 = prio2Annot.value(); 078 } 079 if (prio1 < prio2) { 080 return 1; 081 } 082 if (prio2 < prio1) { 083 return -1; 084 } 085 return o2.getClass().getSimpleName().compareTo(o1.getClass().getSimpleName()); 086 } 087 088 /** 089 * Loads and registers services. 090 * 091 * @param serviceType The service type. 092 * @param <T> the concrete type. 093 * @return the items found, never {@code null}. 094 */ 095 private <T> List<T> loadServices(final Class<T> serviceType) { 096 List<T> services = new ArrayList<>(); 097 try { 098 for (T t : ServiceLoader.load(serviceType)) { 099 services.add(t); 100 } 101 services.sort(PriorityAwareServiceProvider::compareServices); 102 @SuppressWarnings("unchecked") 103 final List<T> previousServices = (List<T>) servicesLoaded.putIfAbsent(serviceType, (List<Object>) services); 104 return Collections.unmodifiableList(previousServices != null ? previousServices : services); 105 } catch (Exception e) { 106 Logger.getLogger(PriorityAwareServiceProvider.class.getName()).log(Level.WARNING, 107 "Error loading services of type " + serviceType, e); 108 services.sort(PriorityAwareServiceProvider::compareServices); 109 return services; 110 } 111 } 112 113}