001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.impl.converter; 018 019 import java.beans.PropertyEditor; 020 import java.beans.PropertyEditorManager; 021 import java.util.HashMap; 022 import java.util.Map; 023 024 import org.apache.camel.Exchange; 025 import org.apache.camel.TypeConverter; 026 import org.apache.camel.util.LRUSoftCache; 027 import org.apache.camel.util.ObjectHelper; 028 import org.slf4j.Logger; 029 import org.slf4j.LoggerFactory; 030 031 /** 032 * Uses the {@link java.beans.PropertyEditor} conversion system to convert Objects to 033 * and from String values. 034 * 035 * @deprecated should be removed as it can cause side-effects when using 3rd party property editors 036 * 037 * @version 038 */ 039 @Deprecated 040 public class PropertyEditorTypeConverter implements TypeConverter { 041 042 private static final Logger LOG = LoggerFactory.getLogger(PropertyEditorTypeConverter.class); 043 // use a soft bound cache to avoid using too much memory in case a lot of different classes 044 // is being converted to string 045 private final Map<Class<?>, Class<?>> misses = new LRUSoftCache<Class<?>, Class<?>>(1000); 046 // we don't anticipate so many property editors so we have unbounded map 047 private final Map<Class<?>, PropertyEditor> cache = new HashMap<Class<?>, PropertyEditor>(); 048 049 public void clear() { 050 cache.clear(); 051 misses.clear(); 052 } 053 054 @Override 055 public <T> T convertTo(Class<T> type, Object value) { 056 // We can't convert null values since we can't figure out a property 057 // editor for it. 058 if (value == null) { 059 return null; 060 } 061 062 if (value.getClass() == String.class) { 063 // No conversion needed. 064 if (type == String.class) { 065 return ObjectHelper.cast(type, value); 066 } 067 068 Class<?> key = type; 069 PropertyEditor editor = lookupEditor(key); 070 if (editor != null) { 071 // we are essentially not thread safe as we use 2 calls to convert 072 editor.setAsText(value.toString()); 073 return ObjectHelper.cast(type, editor.getValue()); 074 } 075 } else if (type == String.class) { 076 Class<?> key = value.getClass(); 077 PropertyEditor editor = lookupEditor(key); 078 if (editor != null) { 079 // we are essentially not thread safe as we use 2 calls to convert 080 editor.setValue(value); 081 return ObjectHelper.cast(type, editor.getAsText()); 082 } 083 } 084 085 return null; 086 } 087 088 private PropertyEditor lookupEditor(Class<?> type) { 089 // check misses first 090 if (misses.containsKey(type)) { 091 LOG.trace("No previously found property editor for type: {}", type); 092 return null; 093 } 094 095 synchronized (cache) { 096 // not a miss then try to lookup the editor 097 PropertyEditor editor = cache.get(type); 098 if (editor == null) { 099 // findEditor is synchronized and very slow so we want to only lookup once for a given key 100 // and then we use our own local cache for faster lookup 101 editor = PropertyEditorManager.findEditor(type); 102 103 // either we found an editor, or if not then register it as a miss 104 if (editor != null) { 105 LOG.trace("Found property editor for type: {} -> {}", type, editor); 106 cache.put(type, editor); 107 } else { 108 LOG.trace("Cannot find property editor for type: {}", type); 109 misses.put(type, type); 110 } 111 } 112 return editor; 113 } 114 } 115 116 @Override 117 public <T> T convertTo(Class<T> type, Exchange exchange, Object value) { 118 return convertTo(type, value); 119 } 120 121 @Override 122 public <T> T mandatoryConvertTo(Class<T> type, Object value) { 123 return convertTo(type, value); 124 } 125 126 @Override 127 public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) { 128 return convertTo(type, value); 129 } 130 131 @Override 132 public <T> T tryConvertTo(Class<T> type, Exchange exchange, Object value) { 133 try { 134 return convertTo(type, exchange, value); 135 } catch (Exception e) { 136 return null; 137 } 138 } 139 140 @Override 141 public <T> T tryConvertTo(Class<T> type, Object value) { 142 try { 143 return convertTo(type, null, value); 144 } catch (Exception e) { 145 return null; 146 } 147 } 148 }