001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020 package org.apache.geronimo.deployment.service;
021
022 import java.beans.BeanInfo;
023 import java.beans.IntrospectionException;
024 import java.beans.Introspector;
025 import java.beans.PropertyDescriptor;
026 import java.beans.PropertyEditorSupport;
027 import java.lang.reflect.Method;
028
029 import javax.xml.namespace.QName;
030
031 import org.apache.geronimo.common.DeploymentException;
032 import org.apache.geronimo.common.propertyeditor.PropertyEditorException;
033 import org.apache.geronimo.deployment.javabean.xbeans.BeanPropertyType;
034 import org.apache.geronimo.deployment.javabean.xbeans.JavabeanDocument;
035 import org.apache.geronimo.deployment.javabean.xbeans.JavabeanType;
036 import org.apache.geronimo.deployment.javabean.xbeans.PropertyType;
037 import org.apache.geronimo.crypto.EncryptionManager;
038 import org.apache.xmlbeans.XmlException;
039 import org.apache.xmlbeans.XmlOptions;
040
041 /**
042 *
043 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
044 */
045 public class JavaBeanXmlAttributeEditor extends PropertyEditorSupport {
046 private static final QName QNAME = JavabeanDocument.type.getDocumentElementName();
047 private static final Class[] PRIMITIVES_CLASSES = new Class[] {String.class,
048 Boolean.class,
049 Character.class,
050 Byte.class,
051 Short.class,
052 Integer.class,
053 Long.class,
054 Float.class,
055 Double.class
056 };
057
058 private final Class javaBeanClazz;
059 private final XmlAttributeBuilder xmlAttributeBuilder;
060
061 public JavaBeanXmlAttributeEditor(Class clazz) {
062 if (null == clazz) {
063 throw new IllegalArgumentException("clazz is required");
064 }
065 this.javaBeanClazz = clazz;
066
067 xmlAttributeBuilder = newXmlAttributeBuilder();
068 }
069
070 protected JavaBeanXmlAttributeBuilder newXmlAttributeBuilder() {
071 return new JavaBeanXmlAttributeBuilder();
072 }
073
074 @Override
075 public void setAsText(String text) throws IllegalArgumentException {
076 try {
077 JavabeanDocument document = JavabeanDocument.Factory.parse(text);
078 JavabeanType javaBeanType = document.getJavabean();
079
080 Object javabean = xmlAttributeBuilder.getValue(javaBeanType,
081 javaBeanClazz.getName(),
082 getClass().getClassLoader());
083
084 setValue(javabean);
085 } catch (XmlException e) {
086 throw new PropertyEditorException(e);
087 } catch (DeploymentException e) {
088 throw new PropertyEditorException(e);
089 }
090 }
091
092 @Override
093 public String getAsText() {
094 JavabeanType javabeanType = getJavabeanType(getValue());
095
096 XmlOptions xmlOptions = new XmlOptions();
097 xmlOptions.setSaveSyntheticDocumentElement(QNAME);
098 xmlOptions.setSavePrettyPrint();
099 return javabeanType.xmlText(xmlOptions);
100 }
101
102 protected JavabeanType getJavabeanType(Object javaBean) {
103 JavabeanType javabeanType = JavabeanType.Factory.newInstance();
104
105 javabeanType.setClass1(javaBean.getClass().getName());
106
107 PropertyDescriptor[] propertyDescriptors;
108 try {
109 BeanInfo beanInfo = Introspector.getBeanInfo(javaBean.getClass());
110 propertyDescriptors = beanInfo.getPropertyDescriptors();
111 } catch (IntrospectionException e) {
112 throw new IllegalStateException("See nested", e);
113 }
114
115 for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
116 handle(javaBean, propertyDescriptor, javabeanType);
117 }
118
119 return javabeanType;
120 }
121
122 protected void handle(Object javaBean, PropertyDescriptor propertyDescriptor, JavabeanType javabeanType) {
123 Method readMethod = propertyDescriptor.getReadMethod();
124 if (null == readMethod) {
125 return;
126 } else if (readMethod.isAnnotationPresent(DoNotPersist.class) || readMethod.getName().equals("getClass")) {
127 return;
128 }
129
130 Object value;
131 try {
132 value = readMethod.invoke(javaBean, null);
133 } catch (Exception e) {
134 throw new IllegalStateException("See nested", e);
135 }
136 if (null == value) {
137 return;
138 }
139
140 if (isPrimitive(value)) {
141 PropertyType propertyType = javabeanType.addNewProperty();
142 propertyType.setName(propertyDescriptor.getName());
143
144 String valueAsString = value.toString();
145 if (readMethod.isAnnotationPresent(EncryptOnPersist.class)) {
146 valueAsString = EncryptionManager.encrypt(valueAsString);
147 }
148
149 propertyType.setStringValue(valueAsString);
150 } else {
151 JavabeanType nestedJavabeanType = getJavabeanType(value);
152
153 BeanPropertyType propertyType = javabeanType.addNewBeanProperty();
154 propertyType.setName(propertyDescriptor.getName());
155 propertyType.setJavabean(nestedJavabeanType);
156 }
157 }
158
159 protected boolean isPrimitive(Object propertyValue) {
160 Class valueClass = propertyValue.getClass();
161 for (Class primitiveClass : PRIMITIVES_CLASSES) {
162 if (valueClass.equals(primitiveClass)) {
163 return true;
164 }
165 }
166 return false;
167 }
168
169 }