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 }