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