001package org.cache2k.storage; 002 003/* 004 * #%L 005 * cache2k core package 006 * %% 007 * Copyright (C) 2000 - 2015 headissue GmbH, Munich 008 * %% 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as 011 * published by the Free Software Foundation, either version 3 of the 012 * License, or (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public 020 * License along with this program. If not, see 021 * <http://www.gnu.org/licenses/gpl-3.0.html>. 022 * #L% 023 */ 024 025import java.util.HashMap; 026import java.util.HashSet; 027import java.util.Map; 028import java.util.ServiceLoader; 029import java.util.Set; 030 031/** 032 * Singleton which provides a top level MarshallerFactory which 033 * in turn delegates to marshaller factories that are registered 034 * via the service loader. 035 * 036 * @author Jens Wilke; created: 2014-04-19 037 */ 038public class Marshallers implements MarshallerFactory { 039 040 private static ServiceLoader<? extends MarshallerFactory> loader = 041 ServiceLoader.load(MarshallerFactory.class); 042 043 private static MarshallerFactory instance; 044 045 public static MarshallerFactory getInstance() { 046 if (instance == null) { 047 instance = new Marshallers(); 048 } 049 return instance; 050 } 051 052 private Set<MarshallerFactory> factorySet = new HashSet<MarshallerFactory>(); 053 private Map<Class<?>, MarshallerFactory> type2factory = new HashMap<Class<?>, MarshallerFactory>(); 054 private Map<Class<?>, MarshallerFactory> factoryType2factory = new HashMap<Class<?>, MarshallerFactory>(); 055 056 /** 057 * Directly register a marshallerfactory. This is an alternative to the automatic 058 * discovery via the service loader. Useful to provide a marshaller for a 059 * custom bean and register it within the class load (static constructor section). 060 */ 061 public synchronized void registerMarshallerFactory(MarshallerFactory f) { 062 factorySet.add(f); 063 type2factory.clear(); 064 factoryType2factory.clear(); 065 } 066 067 @Override 068 public Class<?> getType() { 069 return Object.class; 070 } 071 072 @Override 073 public int getPriority() { 074 return 0; 075 } 076 077 @Override 078 public synchronized Marshaller createMarshaller(Class<?> _type) { 079 return resolveFactory(_type).createMarshaller(_type); 080 } 081 082 @Override 083 public synchronized Marshaller createMarshaller(Parameters c) { 084 if (c.getMarshallerFactory() != null) { 085 MarshallerFactory f = factoryType2factory.get(c.getMarshallerFactory()); 086 if (f == null) { 087 try { 088 f = (MarshallerFactory) c.getMarshallerFactory().newInstance(); 089 } catch (Exception e) { 090 throw new IllegalArgumentException(e); 091 } 092 factoryType2factory.put(c.getMarshallerFactory(), f); 093 } 094 return f.createMarshaller(c); 095 } 096 try { 097 Marshaller m = (Marshaller) c.getMarshallerType().newInstance(); 098 return m; 099 } catch (Exception e) { 100 throw new IllegalArgumentException(e); 101 } 102 } 103 104 MarshallerFactory resolveFactory(Class<?> _type) { 105 MarshallerFactory f = type2factory.get(_type); 106 if (f != null) { 107 return f; 108 } 109 for (MarshallerFactory i : loader) { 110 factorySet.add(i); 111 } 112 for (MarshallerFactory i : factorySet) { 113 if (i.getType().isAssignableFrom(_type)) { 114 if (f == null || f.getPriority() < i.getPriority()) { 115 f = i; 116 } 117 } 118 } 119 type2factory.put(_type, f); 120 return f; 121 } 122 123}