/*
* Copyright 2004-2005 Revolution Systems Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.revolsys.ui.web.config;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.jsp.PageContext;
import org.apache.commons.jexl.Expression;
import org.apache.log4j.Logger;
import com.revolsys.util.JexlUtil;
public class JavaComponent extends Component {
private static final Logger log = Logger.getLogger(JavaComponent.class);
private static final Class[] SERIALIZE_METHOD_ARGS = new Class[] {
Writer.class
};
private static final Class[] SET_PROPERTY_ARGS = new Class[] {
String.class, Object.class
};
private String className;
private Class componentClass;
private final Map properties = new HashMap();
private Method serializeMethod;
private Method setPropertyMethod;
public JavaComponent(final JavaComponent component) {
super(component);
setClassName(component.className);
this.properties.putAll(component.properties);
}
public JavaComponent(final String area, final String name, final String className) {
super(area, name);
setClassName(className);
}
@Override
public Object clone() {
return new JavaComponent(this);
}
@Override
public boolean equals(final Object o) {
if (o instanceof JavaComponent) {
final JavaComponent c = (JavaComponent)o;
if (c.className.equals(this.className) && super.equals(o)) {
return true;
}
}
return false;
}
/**
* Generate the hash code for the object.
*
* @return The hashCode.
*/
@Override
public int hashCode() {
return this.className.hashCode();
}
@Override
public void includeComponent(final PageContext context) throws ServletException, IOException {
Object instance;
try {
instance = this.componentClass.newInstance();
} catch (final Exception e) {
throw new ServletException("Unable to create component instance", e);
}
try {
final Iterator propertyNames = this.properties.keySet().iterator();
while (propertyNames.hasNext()) {
final String propertyName = (String)propertyNames.next();
Object value = this.properties.get(propertyName);
final WebUiContext niceContext = WebUiContext.get();
try {
final Expression expression = JexlUtil.newExpression(value.toString());
if (expression != null) {
value = niceContext.evaluateExpression(expression);
}
} catch (final Exception e) {
throw new ServletException(e.getMessage(), e);
}
this.setPropertyMethod.invoke(instance, new Object[] {
propertyName, value
});
}
} catch (final IllegalAccessException e) {
log.error("Unable to set component properties", e.getCause());
throw new ServletException("Unable to set component properties", e);
} catch (final InvocationTargetException e) {
log.error("Unable to set component properties", e.getCause());
throw new ServletException("Unable to set component properties", e.getCause());
}
try {
final Writer out = context.getOut();
this.serializeMethod.invoke(instance, new Object[] {
out
});
} catch (final IllegalAccessException e) {
throw new ServletException("Unable to serialize component", e);
} catch (final InvocationTargetException e) {
final Throwable cause = e.getCause();
log.error(cause.getMessage(), cause);
if (cause instanceof IOException) {
throw (IOException)cause;
}
throw new ServletException("Unable to serialize component", cause);
}
}
private void setClassName(final String className) {
this.className = className;
try {
this.componentClass = Class.forName(className);
} catch (final ClassNotFoundException e) {
throw new IllegalArgumentException(e.getMessage());
}
try {
this.setPropertyMethod = this.componentClass.getMethod("setProperty", SET_PROPERTY_ARGS);
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException("Class " + className
+ " must have a method with the signature 'public void setProperty(String name, Object value)'");
}
try {
this.serializeMethod = this.componentClass.getMethod("serialize", SERIALIZE_METHOD_ARGS);
} catch (final NoSuchMethodException e) {
throw new IllegalArgumentException("Class " + className
+ " must have a method with the signature 'public void serialize(Writer out) throws IOException'");
}
}
public void setProperty(final String name, final String value) {
this.properties.put(name, value);
}
@Override
public String toString() {
final StringBuilder s = new StringBuilder(this.className).append("(");
for (final Iterator props = this.properties.entrySet().iterator(); props.hasNext();) {
final Map.Entry prop = (Map.Entry)props.next();
s.append(prop.getKey()).append("=").append(prop.getValue());
if (props.hasNext()) {
s.append(",");
}
}
s.append(")");
return s.toString();
}
}