/*
* � Copyright IBM Corp. 2010
*
* 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.ibm.xsp.extlib.util.debug;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.convert.Converter;
import javax.faces.el.ValueBinding;
import javax.faces.validator.Validator;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import com.ibm.commons.util.QuickSort;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.util.io.json.JsonJavaFactory;
import com.ibm.commons.util.io.json.JsonObject;
import com.ibm.commons.util.io.json.JsonParser;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.application.ComponentParameters;
import com.ibm.xsp.application.SessionData;
import com.ibm.xsp.complex.ValueBindingObject;
import com.ibm.xsp.registry.FacesComplexDefinition;
import com.ibm.xsp.registry.FacesComponentDefinition;
import com.ibm.xsp.registry.FacesDefinition;
import com.ibm.xsp.registry.FacesProperty;
import com.ibm.xsp.registry.FacesSharableRegistry;
/**
* XPages Basic objects.
* <p>
* Encapsulate main XPages objects.
* </p>
*/
public class XPagesDumpFactory implements DumpAccessorFactory {
private static final boolean USE_JSF_REGISTRY = true;
public DumpAccessor find(DumpContext dumpContext, Object o) {
if(o instanceof ComponentParameters) {
ComponentParameters c = (ComponentParameters)o;
// The only access in 852 is through JSON
try {
JsonObject js = (JsonObject)JsonParser.fromJson(JsonJavaFactory.instanceEx,c.getAsJson());
return new JavaScriptDumpFactory.Json(dumpContext,JsonJavaFactory.instanceEx,js);
} catch(Throwable t) {
return new JavaDumpFactory.ExceptionValue(dumpContext,t);
}
}
// Use of JSF registry
if(USE_JSF_REGISTRY) {
if( (o instanceof UIComponent)
|| (o instanceof Converter)
|| (o instanceof Validator)
|| (o instanceof ValueBindingObject)) {
FacesDefinition def = XPagesDumpFactory.findDefinition(dumpContext, o);
if(def!=null) {
return new JSFRegistryValueMap(dumpContext, def, o);
}
}
}
// Regular component as a bean
if(o instanceof UIComponent) {
return JavaDumpFactory.createJavaBean(dumpContext, o, new JavaDumpFactory.JavaBean.IFilter() {
public boolean accept(PropertyDescriptor desc) {
return true;
}
});
}
if(o instanceof HttpServletRequest) {
return new HttpServletRequestMap(dumpContext,(HttpServletRequest)o);
}
if(o instanceof HttpSession) {
return new HttpSessionMap(dumpContext,(HttpSession)o);
}
if(o instanceof Cookie) {
return new CookieMap(dumpContext,(Cookie)o);
}
if(o instanceof SessionData) {
return new SessionDataMap(dumpContext,(SessionData)o);
}
return null;
}
public static class HttpServletRequestMap extends BasicDumpFactory.PropertyMap {
public HttpServletRequestMap(DumpContext dumpContext, HttpServletRequest req) {
super(dumpContext,"HttpServletRequest"); // $NON-NLS-1$
addCategory("Request Fields"); // $NLS-XPagesDumpFactory.RequestFields-1$
addValue("AuthType", req.getAuthType()); // $NON-NLS-1$
addValue("CharacterEncoding", req.getCharacterEncoding()); // $NON-NLS-1$
addValue("ContentType", req.getContentType()); // $NON-NLS-1$
addValue("ContextPath", req.getContextPath()); // $NON-NLS-1$
addValue("LocalAddr", req.getLocalAddr()); // $NON-NLS-1$
addValue("Locale", req.getLocale()); // $NON-NLS-1$
addValue("Method", req.getMethod()); // $NON-NLS-1$
addValue("PathInfo", req.getPathInfo()); // $NON-NLS-1$
addValue("PathTranslated", req.getPathTranslated()); // $NON-NLS-1$
addValue("Protocol", req.getProtocol()); // $NON-NLS-1$
addValue("QueryString", req.getQueryString()); // $NON-NLS-1$
addValue("RemoteAddr", req.getRemoteAddr()); // $NON-NLS-1$
addValue("RemoteHost", req.getRemoteHost()); // $NON-NLS-1$
addValue("RemoteUser", req.getRemoteUser()); // $NON-NLS-1$
addValue("RequestedSessionId", req.getRequestedSessionId()); // $NON-NLS-1$
addValue("RequestURI", req.getRequestURI()); // $NON-NLS-1$
addValue("RequestURL", req.getRequestURL()); // $NON-NLS-1$
// Not available in Domino
//addValue("RemotePort", req.getRemotePort());
addValue("Scheme", req.getScheme()); // $NON-NLS-1$
addValue("ServerName", req.getServerName()); // $NON-NLS-1$
addValue("ServerPath", req.getServletPath()); // $NON-NLS-1$
addValue("ServerPort", req.getServerPort()); // $NON-NLS-1$
addValue("UserPrincipal", req.getUserPrincipal()); // $NON-NLS-1$
addCategory("Request Parameters"); // $NLS-XPagesDumpFactory.RequestParameters-1$
for( Enumeration e=req.getParameterNames(); e.hasMoreElements(); ) {
String s = (String)e.nextElement();
addValue("a:"+s,req.getParameter(s)); // $NON-NLS-1$
}
addCategory("Request Headers"); // $NLS-XPagesDumpFactory.RequestHeaders-1$
for( Enumeration e=req.getHeaderNames(); e.hasMoreElements(); ) {
String s = (String)e.nextElement();
addValue("h:"+s,req.getHeader(s)); // $NON-NLS-1$
}
addCategory("Request Attributes"); // $NLS-XPagesDumpFactory.RequestAttributes-1$
for( Enumeration e=req.getAttributeNames(); e.hasMoreElements(); ) {
String s = (String)e.nextElement();
addValue("a:"+s,req.getAttribute(s)); // $NON-NLS-1$
}
}
}
public static class HttpSessionMap extends BasicDumpFactory.PropertyMap {
public HttpSessionMap(DumpContext dumpContext, HttpSession session) {
super(dumpContext,"HttpSession"); // $NON-NLS-1$
addCategory("Session Fields"); // $NLS-XPagesDumpFactory.SessionFields-1$
addValue("Id", session.getId()); // $NON-NLS-1$
addValue("CreationTime", session.getCreationTime()); // $NON-NLS-1$
addValue("LastAccessedTime", session.getLastAccessedTime()); // $NON-NLS-1$
addValue("MaxInactiveInterval", session.getMaxInactiveInterval()); // $NON-NLS-1$
addValue("New", session.isNew()); // $NON-NLS-1$
addCategory("Session Attributes"); // $NLS-XPagesDumpFactory.SessionAttributes-1$
for( Enumeration e=session.getAttributeNames(); e.hasMoreElements(); ) {
String s = (String)e.nextElement();
addValue("a:"+s,session.getAttribute(s)); // $NON-NLS-1$
}
}
}
public static class CookieMap extends BasicDumpFactory.PropertyMap {
public CookieMap(DumpContext dumpContext, Cookie cookie) {
super(dumpContext,"Cookie"); // $NON-NLS-1$
addValue("Comment", cookie.getComment()); // $NON-NLS-1$
addValue("Domain", cookie.getDomain()); // $NON-NLS-1$
addValue("Name", cookie.getName()); // $NON-NLS-1$
addValue("MaxAge", cookie.getMaxAge()); // $NON-NLS-1$
addValue("Path", cookie.getPath()); // $NON-NLS-1$
addValue("Secure", cookie.getSecure()); // $NON-NLS-1$
addValue("Value", cookie.getValue()); // $NON-NLS-1$
addValue("Version", cookie.getVersion()); // $NON-NLS-1$
}
}
public static class SessionDataMap extends BasicDumpFactory.PropertyMap {
public SessionDataMap(DumpContext dumpContext, SessionData data) {
super(dumpContext,"SessionData"); // $NON-NLS-1$
addValue("ClientTimeZone", data.getClientTimeZone()); // $NON-NLS-1$
addValue("Locale", data.getLocale()); // $NON-NLS-1$
addValue("RunningContext", data.getRunningContext()); // $NON-NLS-1$
addValue("TimeZone", data.getTimeZone()); // $NON-NLS-1$
addValue("URLs", data.getUrls()); // $NON-NLS-1$
}
}
// =============================================================================
// JSF Registry
// =============================================================================
protected static FacesDefinition findDefinition(DumpContext dumpContext, Object object) {
// Ask Maire for the best way to get the definition
FacesSharableRegistry registry = ApplicationEx.getInstance().getRegistry();
if(registry!=null) {
if(object instanceof UIComponent) {
List<FacesComponentDefinition> defs = registry.findComponentDefs();
for(FacesComponentDefinition def: defs) {
if(def.getJavaClass()==object.getClass()) {
return def;
}
}
} else {
List<FacesComplexDefinition> defs = registry.findComplexDefs();
for(FacesComplexDefinition def: defs) {
if(def.getJavaClass()==object.getClass()) {
return def;
}
}
}
}
return null;
}
public static class JSFRegistryValueMap extends DumpAccessor.Map {
private Object object;
private FacesDefinition definition;
public JSFRegistryValueMap(DumpContext dumpContext, FacesDefinition definition, Object object) {
super(dumpContext);
this.definition = definition;
this.object = object;
}
@Override
public String getStringLabel() {
return definition.getTagName();
}
@Override
public String getTypeAsString() {
return object.getClass().getName();
}
protected boolean accept(Object key) {
return true;
}
@Override
public String[] getCategories() {
//if(definition!=null) {
// definition.
//}
return null;
}
@Override
public boolean shouldDisplay(String name, Object value) {
if(value==null) {
return false;
}
if(name.equals("loaded")) { // no meaning at runtime //$NON-NLS-1$
return false;
}
if(value instanceof Collection) {
Collection c = (Collection)value;
return !c.isEmpty();
}
if(value.getClass().isArray()) {
return java.lang.reflect.Array.getLength(value)>0;
}
if(value instanceof java.util.Map) {
java.util.Map m = (java.util.Map)value;
return !m.isEmpty();
}
FacesProperty p = definition.getProperty(name);
if(p!=null) {
Object v = getDefaultValue(p);
if(v!=null) {
if(v.equals(value)) {
return false;
}
}
}
return true;
}
protected Object getDefaultValue(FacesProperty p) {
// Ask Maire for this
if(StringUtil.equals(p.getName(),"rendered")) {//$NON-NLS-1$
return Boolean.TRUE;
}
if(p.getJavaClass()==Boolean.TYPE) {
return Boolean.FALSE;
}
return null;
}
@Override
public Iterator<Object> getPropertyKeys(String category) {
Collection<String> names = definition.getPropertyNames();
ArrayList<Object> list = new ArrayList<Object>();
for(String s: names) {
//FacesProperty prop = definition.getProperty(s);
// Check the category here...
list.add(s);
}
(new QuickSort.JavaList(list)).sort();
// Pseudo properties, at the end
if(object instanceof UIComponent) {
UIComponent c = (UIComponent)object;
list.add("children");//$NON-NLS-1$
list.add("facets");//$NON-NLS-1$
}
return list.iterator();
}
@Override
public Object getProperty(Object key) {
String propName = (String)key;
// Pseudo properties - No need of wrapping as the objects
// are of type UIComponent.
if(propName.equals("children")) {//$NON-NLS-1$
if (object instanceof UIComponent) {
return ((UIComponent)object).getChildren();
}
}
if(propName.equals("facets")) {//$NON-NLS-1$
if (object instanceof UIComponent) {
return ((UIComponent)object).getFacets();
}
}
FacesProperty p = definition.getProperty(propName);
// Look for a value binding
ValueBinding vb = null;
if(object instanceof UIComponent) {
vb = ((UIComponent)object).getValueBinding(propName);
} else if(object instanceof ValueBindingObject) {
vb = ((ValueBindingObject)object).getValueBinding(propName);
}
if(vb!=null) {
return vb.getExpressionString();
}
// Look for a component property
if(object instanceof UIComponent) {
return ((UIComponent)object).getAttributes().get(key);
}
// Look for a bean property value
try {
BeanInfo bi = java.beans.Introspector.getBeanInfo(object.getClass());
PropertyDescriptor[] desc = bi.getPropertyDescriptors();
return JavaDumpFactory.getBeanProperty(object, desc, key);
} catch(Exception e) {
return e;
}
}
// private Object wrap(Object object) {
// if( object==null
// || (object instanceof String) || (object instanceof Boolean) || (object instanceof Number)
// || (object instanceof UIComponent)
// || (object instanceof Collection)
// || (object instanceof Map)
// || object.getClass().isArray()) {
// return object;
// }
// if(object instanceof List) {
// ArrayList l = new ArrayList();
// for(Object o: (List)object) {
// l.add(wrap(o));
// }
// return l;
// }
// FacesDefinition def = XPagesDumpFactory.findDefinition(getDumpContext(), object);
// if(def!=null) {
// return new JSFRegistryValueMap(getDumpContext(), def, object);
// }
// return object;
// }
}
}