Author: tcurdt Date: Fri Nov 5 12:22:33 2004 New Revision: 56693 Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ReflectionUtils.java Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationContext.java cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java cocoon/branches/BRANCH_2_1_X/status.xml Log: fixes bug 31297 due to Nikolaus Rath ([EMAIL PROTECTED])
Javaflow: also support inherited methods Javaflow: ported back parameter support from trunk Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationContext.java ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationContext.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/ContinuationContext.java Fri Nov 5 12:22:33 2004 @@ -19,6 +19,7 @@ import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.logger.Logger; +import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.service.ServiceManager; import org.apache.cocoon.environment.Redirector; @@ -27,7 +28,7 @@ * * @author <a href="mailto:[EMAIL PROTECTED]">Torsten Curdt</a> * @author <a href="mailto:[EMAIL PROTECTED]">Stephan Michels</a> - * @version CVS $Id: ContinuationContext.java,v 1.1 2004/03/29 17:47:21 stephan Exp $ + * @version CVS $Id$ */ public class ContinuationContext { @@ -38,6 +39,8 @@ private Context avalonContext; private ServiceManager manager; private Redirector redirector; + + private Parameters parameters; public ContinuationContext() { } @@ -89,4 +92,12 @@ public Redirector getRedirector() { return redirector; } + + public Parameters getParameters() { + return parameters; + } + + public void setParameters(Parameters parameters) { + this.parameters = parameters; + } } Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java ============================================================================== --- cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java (original) +++ cocoon/branches/BRANCH_2_1_X/src/blocks/javaflow/java/org/apache/cocoon/components/flow/java/JavaInterpreter.java Fri Nov 5 12:22:33 2004 @@ -20,33 +20,36 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.avalon.framework.configuration.Configurable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.components.ContextHelper; import org.apache.cocoon.components.flow.AbstractInterpreter; import org.apache.cocoon.components.flow.FlowHelper; import org.apache.cocoon.components.flow.InvalidContinuationException; import org.apache.cocoon.components.flow.WebContinuation; +import org.apache.cocoon.components.flow.Interpreter.Argument; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Session; +import org.apache.cocoon.util.ReflectionUtils; import org.apache.commons.jxpath.JXPathIntrospector; /** * Implementation of the java flow interpreter. * * @author <a href="mailto:[EMAIL PROTECTED]">Stephan Michels</a> - * @version CVS $Id: JavaInterpreter.java,v 1.5 2004/04/04 06:40:33 antonio Exp $ + * @version CVS $Id$ */ public class JavaInterpreter extends AbstractInterpreter implements Configurable { private boolean initialized = false; - private int timeToLive = 600000; - private static final String ACTION_METHOD_PREFIX = "do"; + private int timeToLive = 600000; /** * Key for storing a global scope object in the Cocoon session @@ -54,7 +57,8 @@ public static final String USER_GLOBAL_SCOPE = "JAVA GLOBAL SCOPE"; private ClassLoader classloader; - private HashMap methods = new HashMap(); + + private Map methods = new HashMap(); static { JXPathIntrospector.registerDynamicClass(VarMap.class, VarMapHandler.class); @@ -64,19 +68,11 @@ super.configure(config); } - private static String removePrefix(String name) { - int prefixLen = ACTION_METHOD_PREFIX.length(); - return name.substring(prefixLen, prefixLen + 1).toLowerCase() - + name.substring(prefixLen + 1); - } - public void initialize() throws Exception { if (getLogger().isDebugEnabled()) getLogger().debug("initialize java flow interpreter"); - initialized = true; - classloader = new ContinuationClassLoader(Thread.currentThread().getContextClassLoader()); for (Iterator scripts = needResolve.iterator(); scripts.hasNext();) { @@ -93,23 +89,15 @@ Class clazz = classloader.loadClass(classname); try { - Method[] methods = clazz.getMethods(); - - for (int i = 0; i < methods.length; i++) { - String methodName = methods[i].getName(); - if (methodName.startsWith(ACTION_METHOD_PREFIX)) { - String function = removePrefix(methodName); - this.methods.put(function, methods[i]); - - if (getLogger().isDebugEnabled()) - getLogger().debug("registered method \"" + methodName + - "\" as function \"" + function + "\""); - } - } + final Map m = ReflectionUtils.discoverMethods(clazz); + methods.putAll(m); } catch (Exception e) { throw new ConfigurationException("cannot get methods by reflection", e); } + } + + initialized = true; } /** @@ -123,16 +111,16 @@ * @param redirector * @exception Exception if an error occurs */ - public void callFunction(String function, List params, Redirector redirector) - throws Exception { + public void callFunction(String function, List params, Redirector redirector) throws Exception { if (!initialized) initialize(); Method method = (Method) methods.get(function); - if (method == null) - throw new ProcessingException("No method found for '" + function + "'"); + if (method == null) { + throw new ProcessingException("No method '" + function + "' found. " + methods); + } if (getLogger().isDebugEnabled()) getLogger().debug("calling method \"" + method + "\""); @@ -152,11 +140,16 @@ context.setLogger(getLogger()); context.setServiceManager(manager); context.setRedirector(redirector); + Parameters parameters = new Parameters(); + for(Iterator i=params.iterator(); i.hasNext();) { + Argument argument = (Argument)i.next(); + parameters.setParameter(argument.name, argument.value); + } + context.setParameters(parameters); Continuation continuation = new Continuation(context); - WebContinuation wk = - continuationsMgr.createWebContinuation(continuation, null, timeToLive, null); + WebContinuation wk = continuationsMgr.createWebContinuation(continuation, null, timeToLive, null); FlowHelper.setWebContinuation(ContextHelper.getObjectModel(this.avalonContext), wk); continuation.registerThread(); @@ -219,6 +212,13 @@ context.setLogger(getLogger()); context.setServiceManager(manager); context.setRedirector(redirector); + Parameters parameters = new Parameters(); + for(Iterator i=params.iterator(); i.hasNext();) { + Argument argument = (Argument)i.next(); + parameters.setParameter(argument.name, argument.value); + } + context.setParameters(parameters); + Continuation continuation = new Continuation(parentContinuation, context); Request request = ContextHelper.getRequest(this.avalonContext); Added: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ReflectionUtils.java ============================================================================== --- (empty file) +++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/util/ReflectionUtils.java Fri Nov 5 12:22:33 2004 @@ -0,0 +1,137 @@ +/* + * Copyright 1999-2004 The 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.cocoon.util; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; + +/** + * @author tcurdt + * + */ +public final class ReflectionUtils { + + public interface Matcher { + boolean matches(final String pName); + } + + public interface Indexer { + void put(final Map pMap, final String pKey, final Object pObject); + }; + + private static DefaultIndexer defaultIndexer = new DefaultIndexer(); + private static DefaultMatcher defaultMatcher = new DefaultMatcher(); + + private static class DefaultMatcher implements Matcher { + public boolean matches(final String pName) { + return pName.startsWith("do"); + } + } + + private static class DefaultIndexer implements Indexer { + public void put(final Map pMap, final String pKey, final Object pObject) { + + // doAction -> action + final String name = Character.toLowerCase(pKey.charAt(2)) + pKey.substring(3); + + System.out.println("reflecting " + name); + pMap.put(name, pObject); + } + }; + + public static Map discoverFields( + final Class pClazz, + final Matcher pMatcher + ) { + + return discoverFields(pClazz, pMatcher, defaultIndexer); + } + + public static Map discoverFields( + final Class pClazz + ) { + + return discoverFields(pClazz, defaultMatcher, defaultIndexer); + } + + public static Map discoverFields( + final Class pClazz, + final Matcher pMatcher, + final Indexer pIndexer + ) { + + System.out.println("discovering fields on " + pClazz.getName()); + + final Map result = new HashMap(); + + Class current = pClazz; + do { + final Field[] fields = current.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + final String fname = fields[i].getName(); + if (pMatcher.matches(fname)) { + pIndexer.put(result, fname, fields[i]); + } + } + current = current.getSuperclass(); + } while(current != null); + + return result; + } + + + public static Map discoverMethods( + final Class pClazz, + final Matcher pMatcher + ) { + + return discoverMethods(pClazz, pMatcher, defaultIndexer); + } + + public static Map discoverMethods( + final Class pClazz + ) { + + return discoverMethods(pClazz, defaultMatcher, defaultIndexer); + } + + public static Map discoverMethods( + final Class pClazz, + final Matcher pMatcher, + final Indexer pIndexer + ) { + + System.out.println("discovering methods on " + pClazz.getName()); + + final Map result = new HashMap(); + + Class current = pClazz; + do { + final Method[] methods = current.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + final String mname = methods[i].getName(); + if (pMatcher.matches(mname)) { + pIndexer.put(result, mname, methods[i]); + } + } + current = current.getSuperclass(); + } while(current != null); + + return result; + } + +} Modified: cocoon/branches/BRANCH_2_1_X/status.xml ============================================================================== --- cocoon/branches/BRANCH_2_1_X/status.xml (original) +++ cocoon/branches/BRANCH_2_1_X/status.xml Fri Nov 5 12:22:33 2004 @@ -199,6 +199,12 @@ <changes> <release version="@version@" date="@date@"> + <action dev="TC" type="fix" fixes-bug="31297" due-to="Nikolaus Rath" due-to-email="[EMAIL PROTECTED]"> + Javaflow: also support inherited methods + </action> + <action dev="TC" type="add"> + Javaflow: ported back parameter support from trunk + </action> <action dev="SW" type="add"> CForms: added widget states. All widgets can now have an "active" (default), "disabled" or "invisible" state. Updated the stylesheets accordingly to use HTML's disabled inputs.