001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.config; 022 023import java.io.Externalizable; 024import java.io.IOException; 025import java.io.ObjectInput; 026import java.io.ObjectOutput; 027import java.lang.reflect.InvocationTargetException; 028import java.util.List; 029import java.util.concurrent.ConcurrentHashMap; 030 031import org.granite.messaging.amf.io.util.Property; 032import org.granite.messaging.amf.io.util.externalizer.Externalizer; 033import org.granite.messaging.amf.io.util.externalizer.annotation.ExternalizedBean; 034import org.granite.util.TypeUtil; 035import org.granite.util.XMap; 036 037/** 038 * @author Franck WOLFF 039 */ 040public class ExternalizerFactory implements ConfigurableFactory<Externalizer> { 041 042 private static final Externalizer NULL_EXTERNALIZER = new Externalizer() { 043 044 private final static String NOT_IMPLEMENTED = "Not implemented (null externalizer)"; 045 046 public void configure(XMap properties) { 047 throw new RuntimeException(NOT_IMPLEMENTED); 048 } 049 public List<Property> findOrderedFields(Class<?> clazz) { 050 throw new RuntimeException(NOT_IMPLEMENTED); 051 } 052 public Object newInstance(String type, ObjectInput in) 053 throws IOException, ClassNotFoundException, InstantiationException, 054 InvocationTargetException, IllegalAccessException { 055 throw new RuntimeException(NOT_IMPLEMENTED); 056 } 057 public void readExternal(Object o, ObjectInput in) 058 throws IOException, ClassNotFoundException, IllegalAccessException { 059 throw new RuntimeException(NOT_IMPLEMENTED); 060 } 061 public void writeExternal(Object o, ObjectOutput out) 062 throws IOException, IllegalAccessException { 063 throw new RuntimeException(NOT_IMPLEMENTED); 064 } 065 public int accept(Class<?> clazz) { 066 return -1; 067 } 068 }; 069 070 private final ConcurrentHashMap<String, Externalizer> externalizersCache = new ConcurrentHashMap<String, Externalizer>(); 071 072 public Externalizer getNullInstance() { 073 return NULL_EXTERNALIZER; 074 } 075 076 public Externalizer getInstance(String type, GraniteConfig config) throws GraniteConfigException { 077 return newInstance(type, config); 078 } 079 080 public Externalizer getInstanceForBean( 081 List<Externalizer> scannedConfigurables, 082 Class<?> beanClass, 083 GraniteConfig config) throws GraniteConfigException { 084 085 Externalizer externalizer = NULL_EXTERNALIZER; 086 087 if (!Externalizable.class.isAssignableFrom(beanClass)) { 088 ExternalizedBean annotation = beanClass.getAnnotation(ExternalizedBean.class); 089 090 Class<? extends Externalizer> type = null; 091 if (annotation != null && annotation.type() != null) 092 type = annotation.type(); 093 else { 094 int maxWeight = -1; 095 for (Externalizer e : scannedConfigurables) { 096 int weight = e.accept(beanClass); 097 if (weight > maxWeight) { 098 maxWeight = weight; 099 type = e.getClass(); 100 } 101 } 102 } 103 104 if (type != null) 105 externalizer = newInstance(type.getName(), config); 106 } 107 108 return externalizer; 109 } 110 111 private Externalizer newInstance(String externalizerType, GraniteConfig config) { 112 Externalizer externalizer = externalizersCache.get(externalizerType); 113 if (externalizer == null) { 114 try { 115 externalizer = TypeUtil.newInstance(externalizerType, Externalizer.class); 116 } catch (Exception e) { 117 throw new GraniteConfigException("Could not instantiate externalizer: " + externalizerType, e); 118 } 119 Externalizer previous = externalizersCache.putIfAbsent(externalizerType, externalizer); 120 if (previous != null) 121 externalizer = previous; 122 else 123 externalizer.configure(config.getExternalizersConfiguration()); 124 } 125 return externalizer; 126 } 127}