Author: niclas Date: Sun Aug 15 13:30:48 2004 New Revision: 36418 Added: avalon/trunk/planet/facilities/reflector/ avalon/trunk/planet/facilities/reflector/README.TXT avalon/trunk/planet/facilities/reflector/api/ avalon/trunk/planet/facilities/reflector/api/build.properties (contents, props changed) avalon/trunk/planet/facilities/reflector/api/build.xml (contents, props changed) avalon/trunk/planet/facilities/reflector/api/src/ avalon/trunk/planet/facilities/reflector/api/src/main/ avalon/trunk/planet/facilities/reflector/api/src/main/org/ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionEvent.java (contents, props changed) avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionException.java (contents, props changed) avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionListener.java (contents, props changed) avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectorService.java (contents, props changed) avalon/trunk/planet/facilities/reflector/build.properties (contents, props changed) avalon/trunk/planet/facilities/reflector/build.xml (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/ avalon/trunk/planet/facilities/reflector/impl/build.properties (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/build.xml (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/src/ avalon/trunk/planet/facilities/reflector/impl/src/main/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ModelRegistrator.java (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectionHandler.java (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectorImpl.java (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/RequestContext.java (contents, props changed) avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/package.html (contents, props changed) avalon/trunk/planet/facilities/reflector/static_request.log avalon/trunk/planet/facilities/reflector/test/ avalon/trunk/planet/facilities/reflector/test/etc/ avalon/trunk/planet/facilities/reflector/test/etc/config.xml (contents, props changed) Modified: avalon/trunk/planet/facilities/index.xml Log: A brand new facility. Allows you to 'browse' the java instances, change the values and even instantiate (if classloaders allow) new objects and assign them.
Modified: avalon/trunk/planet/facilities/index.xml ============================================================================== --- avalon/trunk/planet/facilities/index.xml (original) +++ avalon/trunk/planet/facilities/index.xml Sun Aug 15 13:30:48 2004 @@ -627,5 +627,34 @@ </dependencies> </project> + <project basedir="reflector/api"> + <info> + <group>metro/facilities/reflector</group> + <name>metro-reflector-api</name> + <version>1.0.0</version> + <status>SNAPSHOT</status> + <type>jar</type> + </info> + </project> + <project basedir="reflector/impl"> + <info> + <group>metro/facilities/reflector</group> + <name>metro-reflector-impl</name> + <version>1.0.0</version> + <status>SNAPSHOT</status> + <type>jar</type> + </info> + <dependencies> + <include key="avalon-framework-api"/> + <include key="metro-reflector-api"/> + <include key="avalon-composition-api"/> + <include key="org.mortbay.jetty"/> + <include key="avalon-http-spi"/> + <include key="avalon-http-impl"/> + </dependencies> + <plugins> + <include key="avalon-meta-tools"/> + </plugins> + </project> </index> Added: avalon/trunk/planet/facilities/reflector/README.TXT ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/README.TXT Sun Aug 15 13:30:48 2004 @@ -0,0 +1,15 @@ + +To build: + + $ cd planet/facilities/http + $ ant + +To start the http server: + + $ cd test + $ merlin target/deliverables/blocks/avalon-http-test.block + +To see the result: + + http://localhost:8080/test/primary + Added: avalon/trunk/planet/facilities/reflector/api/build.properties ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/build.properties Sun Aug 15 13:30:48 2004 @@ -0,0 +1,2 @@ +project.system = ../../../../central/system +project.home = ../.. Added: avalon/trunk/planet/facilities/reflector/api/build.xml ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/build.xml Sun Aug 15 13:30:48 2004 @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<project name="metro-reflector-api" default="install" basedir="." + xmlns:x="antlib:org.apache.avalon.tools"> + + <property file="build.properties"/> + <import file="${project.system}/build/standard.xml"/> + +</project> + Added: avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionEvent.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionEvent.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,59 @@ +/* + * 1.0 1999/07/30 Niclas Hedhman First Public Release + * + * Copyright (c) 1996-1999 Bali Automation. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * BALI AUTOMATION MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BALI AUTOMATION + * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A + * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + */ +package org.apache.metro.facilities.reflector; + +import java.util.EventObject; +import java.io.Serializable; + +public final class ReflectionEvent extends EventObject + implements Serializable +{ + static final long serialVersionUID = 1L; + + private final Object m_Object; + private final Object m_Value; + private final String m_Method; + + public ReflectionEvent( Object source, + Object object, + Object value, + String method ) + { + super(source); + m_Object = object; + m_Value = value; + m_Method = method; + } + + public Object getObject() + { + return m_Object; + } + + public Object getValue() + { + return m_Value; + } + + public String getMethod() + { + return m_Method; + } +} Added: avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionException.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionException.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1996-2003 Bali Automation. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * BALI AUTOMATION MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BALI AUTOMATION + * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A + * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + */ +package org.apache.metro.facilities.reflector; + +public class ReflectionException extends Exception +{ + static final long serialVersionUID = 1L; + + public ReflectionException() + { + super(); + } + + public ReflectionException( String message ) + { + super(message); + } + + public ReflectionException( String message, Exception exception ) + { + super(message, exception); + } +} Added: avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionListener.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectionListener.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1996-2003 Bali Automation. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * BALI AUTOMATION MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BALI AUTOMATION + * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A + * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + */ +package org.apache.metro.facilities.reflector; + +import java.util.EventListener; + +public interface ReflectionListener extends EventListener +{ + void reflected( ReflectionEvent event ); +} Added: avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectorService.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/api/src/main/org/apache/metro/facilities/reflector/ReflectorService.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,53 @@ +/* + * Copyright 2004 Apache Software Foundation + * 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 org.apache.metro.facilities.reflector; + +/** + * @avalon.service name="ReflectorService" + */ +public interface ReflectorService +{ + String get( String object ) throws ReflectionException; + Object getObject( String object ) throws ReflectionException; + Object getObject( Object container, String memberName ) throws ReflectionException; + + void set( String object, String value ) throws ReflectionException; + void setObject( String objectname, Object object ) throws ReflectionException; + void setObject( Object container, String memberName, Object object ) throws ReflectionException; + + String[] getNames( String object ) throws ReflectionException; + String[] getNames( Object object ) throws ReflectionException; + + Class getClass( String objectname ) throws ReflectionException; + Class getClass( Object container, String memberName ) throws ReflectionException; + + String getClassName( String objectname ) throws ReflectionException; + String getClassName( Object container, String memberName ) throws ReflectionException; + + boolean isSettable( String objectname ) throws ReflectionException; + boolean isSettable( Object container, String member) throws ReflectionException; + + String getContainer( String objectname ) throws ReflectionException; + String getMember( String objectname ) throws ReflectionException; + + void addRootObject( String name, Object object ) throws ReflectionException; + void removeRootObject( String name ) throws ReflectionException; + + void addReflectionListener( ReflectionListener listener ); + void removeReflectionListener( ReflectionListener listener ); +} Added: avalon/trunk/planet/facilities/reflector/build.properties ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/build.properties Sun Aug 15 13:30:48 2004 @@ -0,0 +1,2 @@ +project.system = ../../../central/system +project.home = .. Added: avalon/trunk/planet/facilities/reflector/build.xml ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/build.xml Sun Aug 15 13:30:48 2004 @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<project name="reflector" default="default" basedir="."> + + <property file="build.properties"/> + <import file="${project.system}/build/reactor.xml"/> + +</project> Added: avalon/trunk/planet/facilities/reflector/impl/build.properties ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/build.properties Sun Aug 15 13:30:48 2004 @@ -0,0 +1,2 @@ +project.system = ../../../../central/system +project.home = ../.. Added: avalon/trunk/planet/facilities/reflector/impl/build.xml ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/build.xml Sun Aug 15 13:30:48 2004 @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<project name="metro-reflector-impl" default="install" basedir="." + xmlns:x="antlib:org.apache.avalon.tools"> + + <property file="build.properties"/> + <import file="${project.system}/build/standard.xml"/> + + <target name="build" depends="standard.build"> + + <x:block name="reflector"> + <x:component name="impl" class="org.apache.metro.facilities.reflector.impl.ReflectorImpl" /> + <x:component name="model-registrar" class="org.apache.metro.facilities.reflector.impl.ModelRegistrator" /> + <x:component name="reflector-http-handler" class="org.apache.metro.facilities.reflector.impl.ReflectionHandler" > + <x:parameters> + <x:parameter name="handler-index" value="0" /> + <x:parameter name="context-path" value="/inspect" /> + </x:parameters> + </x:component> + <x:include name="http" artifact="block:avalon/http/avalon-http-static#SNAPSHOT" /> + <x:include name="http-server" artifact="block:avalon/http/avalon-http-server#SNAPSHOT" /> + </x:block> + </target> + +</project> Added: avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ModelRegistrator.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ModelRegistrator.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,80 @@ +/* + * Copyright 2004 Apache Software Foundation + * 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 org.apache.metro.facilities.reflector.impl; + +import org.apache.avalon.framework.activity.Initializable; + +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; + +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; + +import org.apache.avalon.composition.model.ContainmentModel; + +import org.apache.metro.facilities.reflector.ReflectorService; + +/** This component will lookup the composition model and register + * + * @avalon.component name="model-registrator" lifestyle="singleton" + * collection="weak" + */ +public class ModelRegistrator + implements Contextualizable, Serviceable, Initializable +{ + private ContainmentModel m_Model; + private ReflectorService m_Reflector; + + /** + * Contextulaization of the listener by the container during + * which we are supplied with the root composition model for + * the application. + * + * @param ctx the supplied listener context + * + * @exception ContextException if a contextualization error occurs + * + * @avalon.entry key="urn:composition:containment.model" + * type="org.apache.avalon.composition.model.ContainmentModel" + */ + public void contextualize( Context ctx ) + throws ContextException + { + m_Model = (ContainmentModel) ctx.get( "urn:composition:containment.model" ); + } + + /** The service method is called by the Avalon framework container. + * <p>It is imoprtant that this method is not called directly.</p> + * + * @avalon.dependency type="org.apache.metro.facilities.reflector.ReflectorService" + * key="reflector" + */ + public void service( ServiceManager man ) + throws ServiceException + { + m_Reflector = (ReflectorService) man.lookup( "reflector" ); + } + + public void initialize() + throws Exception + { + m_Reflector.addRootObject( "model", m_Model ); + } +} Added: avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectionHandler.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectionHandler.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,626 @@ +/* + * Copyright 2004 Apache Software Foundation + * 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 org.apache.metro.facilities.reflector.impl; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.OutputStreamWriter; + +import java.util.Collection; +import java.util.Dictionary; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.apache.avalon.framework.activity.Startable; + +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; + +import org.apache.avalon.framework.logger.LogEnabled; +import org.apache.avalon.framework.logger.Logger; + +import org.apache.avalon.framework.parameters.ParameterException; +import org.apache.avalon.framework.parameters.Parameterizable; +import org.apache.avalon.framework.parameters.Parameters; + +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; + +import org.apache.avalon.http.HttpContextService; + +import org.apache.metro.facilities.reflector.ReflectionException; +import org.apache.metro.facilities.reflector.ReflectorService; + +import org.mortbay.http.HttpContext; +import org.mortbay.http.HttpHandler; +import org.mortbay.http.HttpRequest; +import org.mortbay.http.HttpResponse; + +/** + * @avalon.component name="reflector-http-handler" lifestyle="singleton" + * @avalon.service type="org.mortbay.http.HttpHandler" + */ +public class ReflectionHandler + implements Startable, Parameterizable, LogEnabled, + Serviceable, Contextualizable, HttpHandler +{ + private String m_Name; + private Logger m_Logger; + private HttpContextService m_ContextService; + private HttpContext m_Context; + private int m_Index; + private boolean m_Started; + + private ReflectorService m_Reflector; + private String m_ContextPath; + private String m_Encoding; + + private Vector m_Reserved; + + public ReflectionHandler() + { + m_Started = false; + m_Reserved = new Vector(); + m_Reserved.addElement("debug"); + m_Reserved.addElement("app"); + m_Reserved.addElement(""); + } + + /** + * Enable the logging system. + * + * @avalon.logger name="http" + */ + public void enableLogging( Logger logger ) + { + m_Logger = logger; + } + + public Logger getLogger() + { + return m_Logger; + } + + /** + * Contextulaization of the Handler. + * + * @param ctx the supplied listener context + * + * @exception ContextException if a contextualization error occurs + * + * @avalon.entry key="urn:avalon:name" + * type="java.lang.String" + */ + public void contextualize( Context ctx ) + throws ContextException + { + m_Name = (String) ctx.get( "urn:avalon:name" ); + } + + public void parameterize( Parameters params ) + throws ParameterException + { + m_Index = params.getParameterAsInteger( "handler-index", -1 ); + m_ContextPath = params.getParameter( "context-path" ); + m_Encoding = params.getParameter( "encoding", "ISO-8859-1" ); + } + + /** + * @avalon.dependency type="org.apache.avalon.http.HttpContextService" + * key="http-context" + * @avalon.dependency type="org.apache.metro.facilities.reflector.ReflectorService" + * key="reflector" + */ + public void service( ServiceManager man ) + throws ServiceException + { + m_ContextService = (HttpContextService) man.lookup( "http-context" ); + m_Reflector = (ReflectorService) man.lookup( "reflector" ); + } + + public void initialize( HttpContext context ) + { + if( m_Logger.isDebugEnabled() ) + m_Logger.debug( "Initializing ReflectorHandler: " + context ); + m_Context = context; + } + + public String getName() + { + return m_Name; + } + + public void setName( String name ) + { + m_Name = name; + } + + public HttpContext getHttpContext() + { + return m_Context; + } + + public void start() + throws Exception + { + m_Started = true; + if( m_Index >= 0 ) + m_ContextService.addHandler( m_Index, this ); + else + m_ContextService.addHandler( this ); + if( m_Logger.isDebugEnabled() ) + m_Logger.debug( "Starting ReflectorHandler: " + this ); + } + + public boolean isStarted() + { + return m_Started; + } + + public void stop() + throws InterruptedException + { + m_Started = false; + if( m_Logger.isDebugEnabled() ) + m_Logger.debug( "Stopping ReflectorHandler: " + this ); + m_ContextService.removeHandler( this ); + } + + public void handle( String pathInContext, String pathParams, + HttpRequest request, HttpResponse response ) + throws IOException + { + m_Logger.info( "Request: " + pathInContext ); + if( ! pathInContext.startsWith( m_ContextPath ) ) + return; + pathInContext = pathInContext.substring( m_ContextPath.length() ); + + response.setContentType("text/html"); + RequestContext ctx = new RequestContext( pathInContext, request, response, m_Encoding ); + try + { + String method = request.getMethod(); + if( method.equals( "GET" ) ) + doGet( ctx ); + if( method.equals( "POST" ) ) + doPost( ctx ); + } catch( Exception e ) + { + ctx.out.println( "<html><body><h1>Exception occurred in service.</h1><hr><pre>" ); + e.printStackTrace( ctx.out ); + ctx.out.println( "</pre></body></html>" ); + } finally + { + ctx.dispose(); + } + } + + private void doGet( RequestContext ctx ) + throws IOException, ReflectionException + { + if( m_Logger.isDebugEnabled() ) + { + String s1 = "Reflector get:[" + ctx.req.getRemoteAddr() + ":" + ctx.req.getUserPrincipal() + "] --> " + ctx.req.getRequestURL() + "?" + ctx.req.getQuery(); + m_Logger.debug(s1); + } + + ctx.out.println( "<html>" ); + formatGet( ctx ); + formatDebug(ctx); + ctx.out.println( "</body></html>" ); + } + + private void doPost( RequestContext ctx ) + throws IOException + { + if( m_Logger.isDebugEnabled() ) + { + String s1 = "Reflector set:[" + ctx.req.getRemoteAddr() + ":" + ctx.req.getUserPrincipal() + "] --> " + ctx.req.getRequestURL() + "?" + ctx.req.getQuery(); + m_Logger.debug( s1 ); + } + + ctx.out.println( "<html><head>" ); + ctx.out.println( "</head><body>" ); + ctx.out.println( "<h3>Changes made:</h3><hr>" ); + ctx.out.println( "<table border=1 cellspacing=0 cellpadding=2 width=\"100%\">" ); + ctx.out.println( "<tr><td><b><u>Member</b></u></td><td><b><u>Changed to</b></u></td></tr>" ); + + Iterator names = ctx.req.getParameterNames().iterator(); + while( names.hasNext() ) + { + String name = (String) names.next(); + if( ! isReserved(name) ) + { + List values = ctx.req.getParameterValues( name ); + for( int i=0 ; i < values.size() ; i++ ) + { + String value = (String) values.get(i); + if( value != null ) + { + if( ! value.equals("") )try + { + ctx.out.print( "<tr><td>" ); + ctx.out.print( name ); + ctx.out.print( "</td><td>" ); + m_Reflector.set( name, value ); + ctx.out.print( value ); + } catch( Exception e ) + { + e.printStackTrace( ctx.out ); + } + ctx.out.print( "</td></tr>" ); + } + } + } + } + ctx.out.println( "</table>" ); + if( ctx.debug ) + ctx.out.println("<hr>Execution Time:" + (System.currentTimeMillis()-ctx.start) + " ms" ); + ctx.out.println( "</body></html>" ); + } + + private void formatGet( RequestContext ctx ) + throws IOException, ReflectionException + { + // then get the writer and write the response data + String title = null; + if( ctx.objectname == null || ctx.objectname.equals("") ) + title = "Application Root Names"; + else + title = ctx.objectname; + PrintWriter out = ctx.out; + + out.println( "<head><title>" ); + out.println( title ); + out.println( "</title></head><body>" ); + out.println( "<h1>" ); + out.println( title ); + out.println( "</h1>" ); + if( ctx.objectname == null || ctx.objectname.equals("") ) + out.println( "<hr>" ); + else + { + String container = m_Reflector.getContainer( ctx.objectname ); + String member = m_Reflector.getMember( ctx.objectname ); + if( container == null || "".equals(container) ) + { + out.print( "<A href=" ); + out.print( "\"/bali/debug/" ); + out.print( "\">Application Root</A><hr>" ); + } + else + { + out.print( "<A href=" ); + formatURL( ctx, container ); + out.println( "\">" ); + out.println( container ); + out.println( "</A><hr>" ); + } + } + out.print( "<FORM Method=\"POST\" Action=\"modify" ); + if( ctx.debug ) + out.print( "?debug=true" ); + out.print( "\">" ); + boolean error = false; + if( ctx.objectname != null ) + { + if( ! ctx.objectname.equals("") ) + { + Class cls = m_Reflector.getClass(ctx.objectname); + if( cls == null ) + { + formatNotFound(ctx); + error = true; + } + else if( cls.isArray() || + Collection.class.isAssignableFrom(cls) || + Map.class.isAssignableFrom(cls) || + Dictionary.class.isAssignableFrom(cls) + ) + formatArray( ctx ); + else + formatObject(ctx); + } + else + formatObject(ctx); + } + else + formatObject(ctx); + if( ! error ) + formatButton( ctx ); + out.println( "</FORM>" ); + } + + private void formatNotFound( RequestContext ctx ) + { + ctx.out.println( "<h2>Object not found.</h2>" ); + } + + private void formatObject( RequestContext ctx) + throws ReflectionException + { + String[] names = m_Reflector.getNames( ctx.objectname ); + formatTableHeader(ctx); + for( int i=0; i<names.length ; i++ ) + { + ctx.out.print( "<tr>" ); + formatMember( ctx, names[i] ); + ctx.out.println( "</tr>" ); + } + ctx.out.println( "</table>" ) ; + } + + private void formatMember( RequestContext ctx, String member) + { + int columncount = 0; + long then = System.currentTimeMillis(); + ctx.out.print( "<td><A href=" ); + columncount++; + String str = ""; + if( ctx.objectname != null && ! "".equals(ctx.objectname) ) + str = ctx.objectname + "."; + str = str + member; + formatURL(ctx, str ); + ctx.out.print ( ">" ); + ctx.out.print( member ); + ctx.out.print( "</A></td><td>" ); + columncount++; + try + { + String value; + String membername; + if( ctx.objectname == null || "".equals(ctx.objectname) ) + membername = member; + else + membername = ctx.objectname + "." + member; + + String obj = m_Reflector.get( membername ); + if( obj == null ) + value = "<null>"; + else + value = obj; + ctx.out.print( value ); + + if( m_Reflector.isSettable(membername) ) + { + ctx.out.print( "</td><td><INPUT Name=\"" ); + ctx.out.print( str ); + ctx.out.print( "\" TYPE=\"TEXT\" SIZE=\"15\" MAXLENGTH=\"300\" >" ); + } + else + { + ctx.out.print( "</td><td><br>" ); + } + columncount++; + ctx.out.print( "</td><td>" ); + columncount++; + String name = m_Reflector.getClassName( membername ); + if( name == null ) + ctx.out.print( "" ); + else + ctx.out.print( name ); + } + catch( Exception e ) + { + m_Logger.error( e.toString() ); + ctx.out.print( "<pre>" ); + ctx.out.print( e.toString() ); + e.printStackTrace( ctx.out ); + ctx.out.print( "</pre>" ); + for( ; columncount < 4 ; columncount++ ) + ctx.out.print( "</td><td><br>" ); + } + ctx.out.print( "</td>" ); + long now = System.currentTimeMillis(); + if( ctx.debug ) + ctx.out.print( "<td>" + (now-then) + " ms</td>" ); + } + + private void formatArrayMember( RequestContext ctx, String membername) + { + long then = System.currentTimeMillis(); + int columncount = 0; + + ctx.out.print( "<td><A href=" ); + columncount++; + formatURL( ctx, ctx.objectname + membername ); + ctx.out.print ( ">" ); + ctx.out.print( membername ); + ctx.out.print( "</A></td><td>" ); + columncount++; + try + { + String value = m_Reflector.get(ctx.objectname + membername); + Class cls = m_Reflector.getClass(ctx.objectname + membername); + ctx.out.print( value ); + + if( m_Reflector.isSettable(ctx.objectname + membername) ) + { + ctx.out.print( "</td><td><INPUT Name=\"" ); + ctx.out.print( ctx.objectname + membername ); + ctx.out.print( "\" TYPE=\"TEXT\" SIZE=\"10\" MAXLENGTH=\"30\" >" ); + } + else + { + ctx.out.print( "</td><td><br>" ); + } + columncount++; + ctx.out.print( "</td><td>" ); + columncount++; + if( cls == null ) + ctx.out.print( "<unknown>" ); + else + ctx.out.print( cls.getName() ); + } + catch( Exception e ) + { + m_Logger.error( e.getMessage(), e ); + ctx.out.print( "<pre>" ); + ctx.out.print( e.toString() ); + e.printStackTrace( ctx.out ); + ctx.out.print( "</pre>" ); + for( ; columncount < 4 ; columncount++ ) + ctx.out.print( "</td><td>" ); + } + ctx.out.println( "</td>" ); + + long now = System.currentTimeMillis(); + if( ctx.debug ) + ctx.out.print( "<td>" + (now-then) + " ms</td>" ); + } + + private void formatMapMember( RequestContext ctx, Object key, Object value) + { + long then = System.currentTimeMillis(); + int columncount = 0; + + ctx.out.print( "<td><A href=" ); + columncount++; + formatURL( ctx, ctx.objectname + "['" + key + "']" ); + ctx.out.print ( ">" ); + ctx.out.print( "[\"" + key + "\"]" ); + ctx.out.print( "</A></td><td>" ); + columncount++; + try + { + ctx.out.print( value ); + Class cls = key.getClass(); + ctx.out.print( "</td><td>" ); + if( isPrimitive( cls ) ) + { + ctx.out.print( "<INPUT Name=\"" ); + ctx.out.print( ctx.objectname + "[\"" + key + "\"]" ); + ctx.out.print( "\" TYPE=\"TEXT\" SIZE=\"10\" MAXLENGTH=\"30\" >" ); + } + columncount++; + ctx.out.print( "</td><td>" ); + columncount++; + ctx.out.print( cls.getName() ); + } + catch( Exception e ) + { + m_Logger.error( e.getMessage(), e ); + ctx.out.print( "<pre>" ); + ctx.out.print( e.toString() ); + e.printStackTrace( ctx.out ); + ctx.out.print( "</pre>" ); + for( ; columncount < 4 ; columncount++ ) + ctx.out.print( "</td><td>" ); + } + ctx.out.println( "</td>" ); + + long now = System.currentTimeMillis(); + if( ctx.debug ) + ctx.out.print( "<td>" + (now-then) + " ms</td>" ); + } + + private void formatArray( RequestContext ctx ) + throws ReflectionException + { + formatTableHeader(ctx); + String[] names = m_Reflector.getNames(ctx.objectname); + for( int i=0; i < names.length ; i++ ) + { + ctx.out.print( "<tr>" ); + formatArrayMember( ctx, "[\'" + names[i] + "\']" ); + ctx.out.println( "</tr>" ); + } + ctx.out.println( "</table>" ) ; + } + + private void formatButton( RequestContext ctx ) + { + ctx.out.print( "<p><center><INPUT TYPE=\"SUBMIT\" VALUE=\"Change\"></center></p>" ); + } + + private void formatDebug( RequestContext ctx ) + { + if( ctx.debug ) + { + long i = System.currentTimeMillis() - ctx.start; + ctx.out.println( "<hr>Execution time:" + i + " ms" ); + } + } + + private boolean isPrimitive( Class cls ) + { + if( cls.isPrimitive() ) + return true; + + if( cls.equals( Boolean.class ) ) + return true; + if( cls.equals( Number.class ) ) + return true; + else if( cls.equals(Character.class) ) + return true; + else if( cls.equals(Void.class) ) + return true; + else if( cls.equals(String.class) ) + return true; + else + return false; + } + + private void formatURL( RequestContext ctx, String objectname ) + { + ctx.out.print( "\"" ); + ctx.out.print( encode( objectname ) ); + if( ctx.debug ) + ctx.out.print( "?debug=true" ); + ctx.out.print( "\"" ); + } + + private String encode( String text ) + { + StringBuffer buf = new StringBuffer(); + + for( int i=0 ; i < text.length() ; i++ ) + { + + char ch = text.charAt(i); + if( (ch >= 'A' && ch <= 'z') || (ch >= '(' && ch <= '9') && + ( ch != '/' ) + ) + { + buf.append( ch ); + } + else + { + buf.append( '{' ); + buf.append( "" + ((int) ch) ); + buf.append( '}' ); + } + } + return buf.toString(); + } + + private void formatTableHeader( RequestContext ctx ) + { + ctx.out.println( "<table border=1 cellspacing=0 cellpadding=2 width=\"100%\">" ); + ctx.out.println( "<tr><td><b><u>Member</b></u></td><td><b><u>Value</b></u></td><td><b><u>Change</b></u></td><td><b><u>Class/Type</b></u></td></tr>" ); + } + + private boolean isReserved( String text ) + { + return m_Reserved.contains(text); + } +} Added: avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectorImpl.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/ReflectorImpl.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,1159 @@ +/* + * 1.0 1999/07/30 Niclas Hedhman First Public Release + * + * Copyright (c) 1996-1999 Bali Automation. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * BALI AUTOMATION MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BALI AUTOMATION + * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A + * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + */ +package org.apache.metro.facilities.reflector.impl; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import java.util.Map; +import java.util.List; +import java.util.Vector; +import java.util.Iterator; +import java.util.Hashtable; +import java.util.Collection; +import java.util.Dictionary; +import java.util.Properties; +import java.util.Enumeration; + +import java.io.IOException; +import java.io.Serializable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.apache.avalon.framework.activity.Disposable; + +import org.apache.metro.facilities.reflector.ReflectorService; +import org.apache.metro.facilities.reflector.ReflectionListener; +import org.apache.metro.facilities.reflector.ReflectionEvent; +import org.apache.metro.facilities.reflector.ReflectionException; + +/** The Reflector Implementation is capable of digging through any +* Java application that is added as a root object. +* +* @avalon.component name="reflector" lifestyle="singleton" +* @avalon.service type="org.apache.metro.facilities.reflector.ReflectorService" +*/ +public final class ReflectorImpl + implements ReflectorService, Disposable +{ + private Map m_Properties; + private Vector m_Listeners; + private Hashtable m_RootObjects; + + public ReflectorImpl() + { + super(); + m_RootObjects = new Hashtable(); + } + + public void addRootObject( String name, Object obj ) + { + m_RootObjects.put( name, obj ); + ReflectionEvent event = + new ReflectionEvent(this, name, obj, "addRootObject" ); + fireEvent(event); + } + + public void removeRootObject( String name ) + { + m_RootObjects.remove(name); + ReflectionEvent event = + new ReflectionEvent(this, name, null, "removeRootObject" ); + fireEvent(event); + } + + public Object getRootObject( String name ) + { + Object result = m_RootObjects.get(name); + ReflectionEvent event = + new ReflectionEvent(this, name, result, "getRootObject" ); + fireEvent(event); + return result; + } + + public Map getRootObjects() + { + return m_RootObjects; + } + + public String[] getAllRootNames() + { + synchronized( m_RootObjects ) + { + Enumeration list = m_RootObjects.keys(); + String[] names = new String[m_RootObjects.size()]; + + for( int i=0; list.hasMoreElements() ; i++ ) + names[i] = (String) list.nextElement(); + + ReflectionEvent event = + new ReflectionEvent(this, null, names, "getAllRootNames" ); + fireEvent(event); + return names; + } + } + + public String[] getNames( String object) + throws ReflectionException + { + Object container; + + try + { + if( object == null ) + return getAllRootNames(); + if( object.equals("") ) + return getAllRootNames(); + container = resolveObject(object); + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in Server.", e ); + } + String[] result = getNames( container ); + ReflectionEvent event = + new ReflectionEvent(this, object, result, "getNames" ); + fireEvent(event); + return result; + } + + public String[] getNames( Object container) + throws ReflectionException + { + Vector names = new Vector(); + + try + { + if( container == null ) + return getAllRootNames(); + + if( container instanceof Collection ) + return getCollectionNames((Collection) container); + else if( container instanceof Map ) + return getMapNames( (Map) container); + else if( container instanceof Dictionary ) + return getDictionaryNames( (Dictionary) container); + else if( container.getClass().isArray() ) + return getArrayNames( (Object[]) container); + else + { + ///// NORMAL OBJECT + // Retrieve all PUBLIC, non-STATIC fields. + Field[] flds = container.getClass().getDeclaredFields(); + for( int i=0 ; i < flds.length ; i++ ) + { + int mod = flds[i].getModifiers(); + if( Modifier.isPublic( mod ) && !Modifier.isStatic( mod ) ) + { + String str = flds[i].getName(); + int j = str.indexOf( '_' ); + if( j == 1 ) + str = str.substring( 2 ); + names.addElement( str); + } + } + // Retrieve PUBLIC non-STATIC GET methods + Method[] methods = container.getClass().getMethods(); + for( int i=0 ; i < methods.length ; i++ ) + { + int mod = methods[i].getModifiers(); + if( Modifier.isPublic( mod ) && ! Modifier.isStatic( mod )) + { + String str = methods[i].getName(); + if( str.startsWith("get") ) + { + if( methods[i].getParameterTypes().length == 0 ) + { + str = str.substring( 3 ); + if( ! names.contains(str) ) + names.addElement( str ); + } + } + else if( str.startsWith("is") ) + { + if( methods[i].getParameterTypes().length == 0 ) + { + str = str.substring( 2 ); + if( ! names.contains(str) ) + names.addElement( str ); + } + } + } + } + } + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in Server.", e ); + } + String[] ret = new String[names.size()]; + for( int i= 0; i < names.size() ; i++ ) + ret[i] = (String) names.elementAt(i); + return ret; + } + + public String get( String object ) + throws ReflectionException + { + String str = null; + try + { + Object obj = resolveObject( object ); + str = "" + obj; + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in ReflectorServer.", e ); + } + ReflectionEvent event = + new ReflectionEvent(this, object, str, "get" ); + fireEvent(event); + return str; + } + + public void set( String object, String value ) + throws ReflectionException + { + String str = null; + + try + { + String container = dropLast( object ); + String member = getLast(object); + Object obj = resolveObject( container ); + setObject( obj, member, value ); //calls private setObject( Object, String, String) + ReflectionEvent event = + new ReflectionEvent(this, object, value, "set" ); + fireEvent(event); + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in ReflectorServer.", e ); + } + } + + public Object getObject( String object ) + throws ReflectionException + { + Object obj = null; + try + { + obj = resolveObject( object ); + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in Server.", e ); + } + ReflectionEvent event = + new ReflectionEvent(this, object, obj, "getObject" ); + fireEvent(event); + return obj; + } + + public Object getObject( Object container, String memberName ) + throws ReflectionException + { + try + { + if( container == null || container.equals("") ) + { + Object root = m_RootObjects.get(memberName); + return root; + } + if( container.getClass().isPrimitive() ) + return null; + if( memberName.startsWith("[") ) + { + return getCollection(container, memberName); + } + else + { + Method method = findMethod( container, "get" + memberName ); + if( method == null ) + method = findMethod( container, "is" + memberName ); + + Object obj = null; + + if( method != null ) + { + try + { + obj = method.invoke(container, new Object[0] ); + } catch( IllegalAccessException e ) + { + throw new ReflectionException( container.getClass().toString() + ".get" + memberName + "() is not declared public.", e ); + } catch( IllegalArgumentException e ) + { + throw new ReflectionException(container.getClass().toString() + ".get" + memberName + "() received illegal arguments. Internal Error?", e); + } catch( InvocationTargetException e ) + { + Exception exc; + Throwable t = e.getTargetException(); + if( t instanceof Exception ) + exc = (Exception) t; + else + exc = null; + throw new ReflectionException( container.getClass().toString() + ".get" + memberName + "() resulted in an exception.\n" + e , exc ); + } + ReflectionEvent event = + new ReflectionEvent(this, container, obj, "getObject[" + memberName + "]" ); + fireEvent(event); + return obj; + } + if( method == null ) + { + Field fld=findField( container, memberName ); + obj = fld.get( container ); + ReflectionEvent event = + new ReflectionEvent(this, container, obj, "getObject[" + memberName + "]" ); + fireEvent(event); + return obj; + } + } + return null; + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container="+container + ", member=" + memberName, e ); + } + } + + public void setObject( String objectname, Object object ) + throws ReflectionException + { + String str = null; + + try + { + String containerName = dropLast( objectname ); + String member = getLast(objectname); + Object container = resolveObject( containerName ); + setObject( container, member, object ); + + ReflectionEvent event = + new ReflectionEvent(this, objectname, object, "setObject" ); + fireEvent(event); + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Exception in Server.", e ); + } + } + + public void setObject( Object container, String member, Object value ) + throws ReflectionException + { + try + { + Object obj = null; + Class cls = container.getClass(); + Field[] flds = cls.getDeclaredFields(); + + if( member.startsWith("[") ) + { + setCollection(container, member, value); + } + else + { + Method method = findMethod( container, "set" + member ); + if( method != null ) + { + try + { + Class[] argTypes = method.getParameterTypes(); + Object[] args = new Object[1]; + args[0] = value; + obj = method.invoke(container, args ); + ReflectionEvent event = + new ReflectionEvent(this, container, obj, "setObject[" + member + "]" ); + fireEvent(event); + } catch( IllegalAccessException e ) + { + throw new ReflectionException( container.getClass().toString() + ".set" + member + "() is not declared public.", e); + } catch( IllegalArgumentException e ) + { + throw new ReflectionException( container.getClass().toString() + ".set" + member + "() .", e); + } + } + if( method == null ) + { + for( int i=0; i < flds.length ; i++ ) + { + if( matchField( flds[i].getName(), member ) ) + { + setObject( flds[i], container, value ); + ReflectionEvent event = + new ReflectionEvent(this, container, obj, "setObject[" + member + "]" ); + fireEvent(event); + } + } + } + } + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container=:" + container + ", Member=" + member + ", Object=" + value, e ); + } + } + + public String getContainer( String objectname ) + { + String result = dropLast(objectname); + ReflectionEvent event = + new ReflectionEvent(this, objectname, result, "getContainer" ); + fireEvent(event); + return result; + } + + public String getMember( String objectname ) + { + String result = getLast(objectname); + ReflectionEvent event = + new ReflectionEvent(this, objectname, result, "getMember" ); + fireEvent(event); + return result; + } + + private Object resolveObject( String name ) + throws ReflectionException + { + Object obj = null; + + if( "".equals(name) || name == null) + return null; + String container = dropLast(name); + String member = getLast(name); + obj = resolveObject( container ); + obj = getObject( obj, member ); + return obj; + } + + private String dropLast( String name ) + { + int pos1 = name.lastIndexOf( '[' ); + int pos2 = name.lastIndexOf( '.' ); + int pos3 = name.lastIndexOf( ']' ); + if( pos1 == -1 && pos2 == -1 ) + return ""; + String result = name.substring( 0, pos3 > pos2 ? pos1 : pos2 ); + return result; + } + + private String getLast( String name ) + { + int pos1 = name.lastIndexOf( '[' ); + int pos2 = name.lastIndexOf( '.' ); + int pos3 = name.lastIndexOf( ']' ); + if( pos1 == -1 && pos2 == -1 ) + return name; + String result = name.substring( pos3 > pos2 ? pos1 : pos2+1 ); + return result; + } + + public String getClassName( String name ) + throws ReflectionException + { + return getClass(name).getName(); + } + + public String getClassName( Object container, String memberName ) + throws ReflectionException + { + return getClass(container, memberName).getName(); + } + + public Class getClass( String name ) + throws ReflectionException + { + if( "".equals(name) || name == null) + return null; + String container = dropLast(name); + String member = getLast(name); + Object obj = resolveObject( container ); + return getClass( obj, member ); + } + + public Class getClass( Object container, String memberName ) + throws ReflectionException + { + try + { + if( container == null || container.equals("") ) + { + Object root = m_RootObjects.get(memberName); + return root.getClass(); + } + if( isPrimitive(container) ) + return null; + + if( memberName.startsWith("[") ) + { + return getClassInCollection(container, memberName); + } + else + { + Method method = findMethod( container, "get" + memberName ); + if( method == null ) + method = findMethod( container, "is" + memberName ); + + if( method != null ) + { + Class retClass = method.getReturnType(); + if( Modifier.isNative(retClass.getModifiers()) ) + return retClass; + + // Native classes are not properly serialized/deserialized over RMI. + + return expandNativeClass( retClass ); + } + + Field fld=findField( container, memberName ); + return fld.getType(); + } + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container="+container + ", member=" + memberName, e ); + } + } + + public boolean isSettable( String name ) + throws ReflectionException + { + if( "".equals(name) || name == null) + return false; + String container = dropLast(name); + String member = getLast(name); + Object obj = resolveObject( container ); + return isSettable( obj, member ); + } + + public boolean isSettable( Object container, String memberName) + throws ReflectionException + { + try + { + if( container == null || "".equals(container) ) + return false; + if( isPrimitive(container) ) + return false; + + Method method = findMethod( container, "set" + memberName ); + + if( method != null ) + return true; + else + return false; + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container="+container + ", member=" + memberName, e ); + } + } + + private void setPrimitive( Field fld, Object obj, String value ) + throws IllegalAccessException, ClassNotFoundException + { + Class fldClass = fld.getType(); + if( fldClass == Boolean.TYPE ) + { + fld.setBoolean(obj, (new Boolean(value)).booleanValue()); + } + else if( fldClass == Double.TYPE ) + { + fld.setDouble(obj, (new Double(value)).doubleValue()); + } + else if( fldClass == Integer.TYPE ) + { + fld.setInt(obj, (new Integer(value)).intValue()); + } + else if( fldClass == Short.TYPE ) + { + fld.setShort(obj, (new Short(value)).shortValue()); + } + else if( fldClass == Byte.TYPE ) + { + fld.setByte(obj, (new Byte(value)).byteValue()); + } + else if( fldClass == Float.TYPE ) + { + fld.setFloat(obj, (new Float(value)).floatValue()); + } + else if( fldClass == Long.TYPE ) + { + fld.setLong(obj, (new Long(value)).longValue()); + } + else if( fldClass == Character.TYPE ) + { + fld.setChar(obj, value.charAt(0) ); + } + else if( fldClass == Void.TYPE ) + { + throw new IllegalAccessException( " Can not set void primitives." ); + } + else + throw new ClassNotFoundException( "Invalid primitive Class.Type()." ); + } + + private Object convPrimitive( Class type, String value ) + throws IllegalAccessException, ClassNotFoundException, + InstantiationException, NoSuchMethodException, InvocationTargetException + { + Object ret ; + if( type.isPrimitive() ) + { + if( type.equals(Boolean.TYPE) ) + ret = new Boolean( value ); + else if( type.equals(Double.TYPE) ) + ret = new Double( value ); + else if( type.equals(Integer.TYPE) ) + ret = new Integer( value ); + else if( type.equals(Short.TYPE) ) + ret = new Short( value ); + else if( type.equals(Byte.TYPE) ) + ret = new Byte( value ); + else if( type.equals(Float.TYPE) ) + ret = new Float( value ); + else if( type.equals(Long.TYPE ) ) + ret = new Long( value ); + else if( type.equals(Character.TYPE) ) + ret = new Character( value.charAt(0) ); + else if( type.equals( String.class ) ) + ret = value; + else if( type == Void.TYPE ) + throw new IllegalAccessException( " Can not set void primitives." ); + else + throw new IllegalAccessException( " Unknown primitive type." ); + } + else + { + if( Boolean.class.isAssignableFrom(type) ) + ret = new Boolean( value ); + else if( Double.class.isAssignableFrom(type)) + ret = new Double( value ); + else if( Integer.class.isAssignableFrom(type)) + ret = new Integer( value ); + else if( Short.class.isAssignableFrom(type)) + ret = new Short( value ); + else if( Byte.class.isAssignableFrom(type)) + ret = new Byte( value ); + else if( Float.class.isAssignableFrom(type)) + ret = new Float( value ); + else if( Long.class.isAssignableFrom(type)) + ret = new Long( value ); + else if( Character.class.isAssignableFrom(type)) + ret = new Character( value.charAt(0) ); + else if( type.equals( String.class ) ) + ret = value; + else if( Void.class.isAssignableFrom(type) ) + throw new IllegalAccessException( " Can not set void primitives." ); + else if( Number.class.isAssignableFrom(type)) + { + ret = new Double( value ); + } + else + { + // Class name is assumed in value... + // create a new instance of this class and return as the + // value to assign + ret = Class.forName(value).newInstance(); + } + } + return ret; + } + + private Class expandNativeClass( Class nativeClass ) + { + Class ret = nativeClass; + + if( nativeClass.equals(Boolean.TYPE) ) + { + ret = Boolean.class; + } + else if( nativeClass.equals(Double.TYPE) ) + { + ret = Double.class; + } + else if( nativeClass.equals(Integer.TYPE) ) + { + ret = Integer.class; + } + else if( nativeClass.equals(Short.TYPE) ) + { + ret = Short.class; + } + else if( nativeClass.equals(Byte.TYPE) ) + { + ret = Byte.class; + } + else if( nativeClass.equals(Float.TYPE) ) + { + ret = Float.class; + } + else if( nativeClass.equals(Long.TYPE ) ) + { + ret = Long.class; + } + else if( nativeClass.equals(Character.TYPE) ) + { + ret = Character.class; + } + return ret; + } + + private Object getCollection( Object container, String memberName ) + { + Object obj = null; + + String index = memberName.substring( 1, memberName.length()-1); + int numindex = 0; + try + { + if( index.startsWith( "\'" ) ) + index = index.substring( 1, index.length() - 1); + numindex = Integer.parseInt( index ); + } catch( NumberFormatException e ) {} // Ignore + + if( container.getClass().isArray() ) + { + obj = Array.get(container, numindex); + } + else if( container instanceof List ) + { + obj = ((List) container).get(numindex); + } + else if( container instanceof Collection ) + { + synchronized( container ) + { + Object arr[] = ((Collection) container).toArray(); + if( numindex < arr.length ) + obj = arr[numindex]; + } + } + else if( container instanceof Map ) + { + synchronized( container ) + { + obj = ((Map) container).get(index); + } + } + else if( container instanceof Dictionary ) + { + synchronized( container ) + { + obj = ((Dictionary) container).get(index); + } + } + return obj; + } + + private void setCollection( Object container, String memberName, Object value ) + throws ReflectionException + { + try + { + Object obj = null; + + String index = memberName.substring( 1, memberName.length()-1); + int numindex = 0; + try + { + numindex = Integer.parseInt( index ); + } catch( NumberFormatException e ){} // Ignore + synchronized( container ) + { + if( container.getClass().isArray() ) + { + obj = Array.get(container, numindex ); + if( ! obj.getClass().isInstance( value ) ) + { + if( value instanceof String ) + value = convPrimitive( obj.getClass(), (String) value); + } + Array.set(container, numindex, value); + } + else if( container instanceof List ) + { + obj = ((List) container).get(numindex); + if( ! obj.getClass().isInstance( value ) ) + { + if( value instanceof String ) + value = convPrimitive( obj.getClass(), (String) value); + } + ((List) container).set(numindex, value); + } + else if( container instanceof Collection ) + { + Iterator collection = ((Collection) container).iterator(); + for( int i=0; i < numindex && collection.hasNext(); collection.next() ); + obj = collection.next(); + if( ! obj.getClass().isInstance( value ) ) + { + if( value instanceof String ) + value = convPrimitive( obj.getClass(), (String) value); + } + collection.remove(); + ((Collection) container).add(value); + } + else if( container instanceof Map ) + { + index = index.substring( 1, index.length() - 1 ); + obj = ((Map) container).get( index ); + if( ! obj.getClass().isInstance( value ) ) + { + if( value instanceof String ) + value = convPrimitive( obj.getClass(), (String) value); + } + ((Map) container).put(index, value); + } + else if( container instanceof Dictionary ) + { + index = index.substring( 1, index.length() - 1 ); + obj = ((Dictionary) container).get( index ); + if( ! obj.getClass().isInstance( value ) ) + { + if( value instanceof String ) + value = convPrimitive( obj.getClass(), (String) value); + } + ((Dictionary) container).put(index, value); + } + } + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container=" + container + ", Member=" + memberName + ", Value=" + value, e ); + } + } + + private Class getClassInCollection(Object container, String memberName) + { + String index = memberName.substring( 1, memberName.length()-1); + int numindex = 0; + try + { + if( index.startsWith( "\'" ) ) + index = index.substring( 1, index.length() - 1); + numindex = Integer.parseInt( index ); + } catch( NumberFormatException e ) {} // Ignore + + Class result = null; + Object obj; + synchronized( container ) + { + if( container.getClass().isArray() ) + { + // If primitive types, Serialization does not work anyway, + // so the expansion to wrapper classes is OK, for now. + result = Array.get(container, numindex).getClass(); + } + else if( container instanceof List ) + { + obj = ((List) container).get(numindex); + if( obj == null ) + return null; + result = obj.getClass(); + } + else if( container instanceof Collection ) + { + Object arr[] = ((Collection) container).toArray(); + if( numindex < arr.length ) + result = arr[numindex].getClass(); + else + result = null; + } + else if( container instanceof Map ) + { + obj = ((Map) container).get(index); + if( obj == null ) + return null; + result = obj.getClass(); + } + else if( container instanceof Dictionary) + { + obj = ((Dictionary) container).get(index); + if( obj == null ) + return null; + result = obj.getClass(); + } + } + return result; + } + + private void setObject( Object container, String member, String value ) + throws ReflectionException + { + try + { + Object obj = null; + Class cls = container.getClass(); + Field[] flds = cls.getDeclaredFields(); + + if( member.startsWith("[") ) + { + setCollection(container, member, value); + } + else + { + Method method = findMethod( container, "set" + member ); + if( method != null ) + { + try + { + Class[] argTypes = method.getParameterTypes(); + Object arg = convPrimitive( argTypes[0], value); + Object[] args = { arg }; + obj = method.invoke(container, args ); + } catch( IllegalAccessException e ) + { + throw new ReflectionException( container.getClass().toString() + ".set" + member + "() is not declared public.", e); + } catch( IllegalArgumentException e ) + { + throw new ReflectionException( container.getClass().toString() + ".set" + member + "() .", e); + } + } + if( method == null ) + { + for( int i=0; i < flds.length ; i++ ) + { + if( matchField( flds[i].getName(), member ) ) + { + if( flds[i].getType().isPrimitive() ) + setPrimitive( flds[i], container, value ); + else + setObject( flds[i], container, value ); + } + } + } + } + } catch( Exception e ) + { + if( e instanceof ReflectionException ) + throw (ReflectionException) e.fillInStackTrace(); + else + throw new ReflectionException( "Container=" + container + ", Member=" + member + ", Value=" + value, e ); + } + } + + private void setObject( Field fld, Object obj, Object value ) + throws IllegalAccessException, InvocationTargetException, + InstantiationException + { + // Create a new instance of the object + // Assign instance to reference. + Class fldClass = fld.getType(); + + Constructor[] constructors = fldClass.getConstructors(); + Constructor constr = null; + for( int j=0; j < constructors.length ; j++ ) + { + Class[] params = constructors[j].getParameterTypes(); + if( params.length == 1 && params[0].getName().equals("String")) + { + constr = constructors[j]; + break; + } + } + + if( constr != null ) + { + Object[] args = {value}; + Object newObj = constr.newInstance( args ); + fld.set(obj, newObj ); + } + else + throw new IllegalAccessException( "No valid Constructors available for object:" + fldClass ); + } + + private Field findField( Object container, String memberName ) + throws NoSuchFieldException + { + Class cls = container.getClass(); + try + { + Field fld = cls.getDeclaredField( memberName ); + return fld; + } catch( NoSuchFieldException e ) + { + Field fld = cls.getDeclaredField( "m_" + memberName ); + return fld; + } + } + + private Method findMethod( Object container, String methodName ) + { + Method[] methods = container.getClass().getMethods(); + for( int i = 0; i < methods.length ; i++ ) + { + if( methods[i].getName().equals( methodName ) ) + return methods[i]; + } + return null; + } + + private boolean matchField( String programmatic, String global ) + { + int i = programmatic.indexOf( '_' ); + if( i >= 0 ) + programmatic = programmatic.substring( i + 1 ); + return global.equalsIgnoreCase( programmatic ); + } + + private boolean isPrimitive( Object obj ) + { + // This doesn't seem to work!!! + // Class cls = obj.getClass(); + // return cls.isPrimitive(); + + // So need to do this???? + if( obj instanceof Boolean ) + return true; + else if( obj instanceof Double ) + return true; + else if( obj instanceof Integer ) + return true; + else if( obj instanceof Long ) + return true; + else if( obj instanceof Byte ) + return true; + else if( obj instanceof Float ) + return true; + else if( obj instanceof Character ) + return true; + else if( obj instanceof Short ) + return true; + else if( obj instanceof Void ) + return true; + else + return false; + } + + private String[] getCollectionNames(Collection container) + { + String[] sa = new String[container.size()]; + for( int i=0; i < container.size() ; i++ ) + sa[i] = "" + i; + return sa; + } + + private String[] getMapNames( Map container) + { + String[] sa = new String[container.size()]; + int i=0; + + Iterator list = container.keySet().iterator(); + while( list.hasNext() ) + { + sa[i++] = list.next().toString(); + } + return sa; + } + + private String[] getDictionaryNames( Dictionary container) + { + String[] sa = new String[container.size()]; + int i=0; + + Enumeration list = container.keys(); + while( list.hasMoreElements() ) + { + sa[i++] = list.nextElement().toString(); + } + return sa; + } + + private String[] getArrayNames( Object[] container) + { + String[] sa = new String[container.length]; + for( int i=0 ; i < sa.length ; i++ ) + sa[i] = "" + i; + return sa; + } + + public synchronized void addReflectionListener( ReflectionListener listener ) + { + Vector v; + if( m_Listeners == null ) + v = new Vector(); + else + v = (Vector) m_Listeners.clone(); + v.add( listener ); + m_Listeners = v; + } + + public synchronized void removeReflectionListener( ReflectionListener listener ) + { + if( m_Listeners == null ) + return; + Vector v = (Vector) m_Listeners.clone(); + v.remove( listener ); + m_Listeners = v; + } + + private void fireEvent( ReflectionEvent event ) + { + // Use intermediary Vector reference for atomicity without synchronized + Vector v = m_Listeners; + + if( v == null ) + return; + for( int i=0; i < v.size() ; i++ ) + { + ReflectionListener listener = (ReflectionListener) v.elementAt(i); + listener.reflected( event ); + } + } + + public void dispose() + { + if( m_Listeners != null ) + m_Listeners.removeAllElements(); + m_Listeners = null; + + m_RootObjects.clear(); + m_RootObjects = null; + } +} Added: avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/RequestContext.java ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/RequestContext.java Sun Aug 15 13:30:48 2004 @@ -0,0 +1,147 @@ +/* + * 1.0 1999/07/30 Niclas Hedhman First Public Release + * + * Copyright (c) 1996-1999 Bali Automation. All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for NON-COMMERCIAL purposes and without + * fee is hereby granted provided that this copyright notice + * appears in all copies. Please refer to the file "copyright.html" + * for further important copyright and licensing information. + * + * BALI AUTOMATION MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE + * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BALI AUTOMATION + * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A + * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS + * DERIVATIVES. + */ + +package org.apache.metro.facilities.reflector.impl; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +import java.util.List; + +import org.apache.metro.facilities.reflector.ReflectorService; +import org.apache.metro.facilities.reflector.ReflectionException; + +import org.mortbay.http.HttpRequest; +import org.mortbay.http.HttpResponse; + +final class RequestContext +{ + HttpRequest req; + HttpResponse res; + PrintWriter out; + + String objectname; + + long start; + boolean debug; + + + RequestContext( String path, + HttpRequest request, + HttpResponse response, + String encoding + ) + throws IOException + { + start = System.currentTimeMillis(); + + req = request; + res = response; + OutputStreamWriter osw = new OutputStreamWriter( response.getOutputStream(), encoding ); + + out = new PrintWriter( osw, true ); + + List dblist = req.getParameterValues( "debug" ); + debug = (dblist != null) && ( dblist.size() > 0 ); + + String str = path; + if( str.startsWith("//") ) + str = str.substring(2); + if( str.startsWith("/") ) + str = str.substring(1); + + objectname = decode( str ); + objectname = replace( objectname, '/', '.' ); + + if( objectname.endsWith( "/" ) ) + objectname = objectname.substring( 0, objectname.length()-1 ); + + if( debug ) + out.print( "object=" + objectname + "<hr>" ); + } + + void dispose() + throws IOException + { + if( out != null ) + { + out.flush(); + out.close(); + } + } + + + private String replace( String text, char original, char replacement ) + { + StringBuffer buf = new StringBuffer(); + int mode = 0; + + for( int i=0 ; i < text.length() ; i++ ) + { + char ch = text.charAt(i); + switch( mode ) + { + case 0: + if( ch == '"' ) + mode = 1; + else if( ch == '\'' ) + mode = 2; + else if( ch == original ) + ch = replacement; + buf.append(ch); + break; + case 1: + if( ch == '"' ) + mode = 0; + buf.append(ch); + break; + case 2: + if( ch == '\'' ) + mode = 0; + buf.append(ch); + break; + } + } + return buf.toString(); + } + + private String decode( String text ) + { + StringBuffer buf = new StringBuffer(); + for( int i=0 ; i < text.length() ; i++ ) + { + char ch = text.charAt(i); + if( ch == '{' ) + { + int pos = text.indexOf( '}', i ); + String numtxt = text.substring( i+1, pos ); + int num = Integer.parseInt( numtxt ); + buf.append( (char) num ); + i = pos; + } + else + buf.append( ch ); + } + return buf.toString(); + } + + +} Added: avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/package.html ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/impl/src/main/org/apache/metro/facilities/reflector/impl/package.html Sun Aug 15 13:30:48 2004 @@ -0,0 +1,5 @@ +<body> +<p> + Implementation of the Reflector facility. +</p> +</body> Added: avalon/trunk/planet/facilities/reflector/static_request.log ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/static_request.log Sun Aug 15 13:30:48 2004 @@ -0,0 +1,5 @@ +127.0.0.1 - - [16/Aug/2004:03:36:02 +0800] "GET /demo/ HTTP/1.1" 200 1027 "http://localhost:8080/" "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" +127.0.0.1 - - [16/Aug/2004:03:37:02 +0800] "GET /demo/inspect HTTP/1.1" 404 1253 "-" "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" +127.0.0.1 - - [16/Aug/2004:03:37:05 +0800] "GET /demo/inspect/ HTTP/1.1" 404 1256 "-" "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" +127.0.0.1 - - [16/Aug/2004:03:38:27 +0800] "GET /demo/inspect/ HTTP/1.1" 404 1256 "-" "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" +127.0.0.1 - - [16/Aug/2004:03:38:32 +0800] "GET /demo/ HTTP/1.1" 200 1029 "-" "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)" Added: avalon/trunk/planet/facilities/reflector/test/etc/config.xml ============================================================================== --- (empty file) +++ avalon/trunk/planet/facilities/reflector/test/etc/config.xml Sun Aug 15 13:30:48 2004 @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<targets> + + <target path="/reflector/http/context"> + <configuration> + <context-path>/demo</context-path> + <resource-base>.</resource-base> + </configuration> + </target> + +</targets> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]