Modified: river/jtsk/skunk/surrogate/nbproject/genfiles.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/genfiles.properties?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/genfiles.properties (original) +++ river/jtsk/skunk/surrogate/nbproject/genfiles.properties Tue May 14 12:20:38 2013 @@ -1,11 +1,11 @@ -build.xml.data.CRC32=8d037bdc -build.xml.script.CRC32=8dea2037 [email protected] -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=092f50fa -nbproject/build-impl.xml.script.CRC32=740e8a1a -nbproject/[email protected] -nbproject/management-build-impl.xml.data.CRC32=318d2fde -nbproject/management-build-impl.xml.script.CRC32=630dcf8f -nbproject/[email protected] +build.xml.data.CRC32=8d037bdc +build.xml.script.CRC32=8dea2037 [email protected] +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=8f1c53be +nbproject/build-impl.xml.script.CRC32=5baae9fa +nbproject/[email protected] +nbproject/management-build-impl.xml.data.CRC32=318d2fde +nbproject/management-build-impl.xml.script.CRC32=630dcf8f +nbproject/[email protected]
Modified: river/jtsk/skunk/surrogate/nbproject/project.xml URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/nbproject/project.xml?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/nbproject/project.xml (original) +++ river/jtsk/skunk/surrogate/nbproject/project.xml Tue May 14 12:20:38 2013 @@ -1,17 +1,22 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://www.netbeans.org/ns/project/1"> - <type>org.netbeans.modules.java.j2seproject</type> - <configuration> - <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> - <name>RiverSurrogate</name> - <source-roots> - <root id="src.dir"/> - </source-roots> - <test-roots> - <root id="test.src.dir"/> - </test-roots> - </data> - <data xmlns="http://www.netbeans.org/ns/jmx/1" version="0.4"/> - <references xmlns="http://www.netbeans.org/ns/ant-project-references/1"/> - </configuration> -</project> +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.java.j2seproject</type> + <configuration> + <buildExtensions xmlns="http://www.netbeans.org/ns/ant-build-extender/1"> + <extension file="groovy-build.xml" id="groovy"> + <dependency dependsOn="-groovy-init-macrodef-javac" target="-pre-pre-compile"/> + </extension> + </buildExtensions> + <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> + <name>RiverSurrogate</name> + <source-roots> + <root id="src.dir"/> + </source-roots> + <test-roots> + <root id="test.src.dir"/> + </test-roots> + </data> + <data xmlns="http://www.netbeans.org/ns/jmx/1" version="0.4"/> + <references xmlns="http://www.netbeans.org/ns/ant-project-references/1"/> + </configuration> +</project> Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Bootstrap.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Bootstrap.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Bootstrap.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Bootstrap.java Tue May 14 12:20:38 2013 @@ -61,9 +61,11 @@ public class Bootstrap { initializeContainer(args); } catch (InvocationTargetException ex) { log.log(Level.SEVERE, MessageNames.INITIALIZATION_EXCEPTION, ex.getCause()); + ex.printStackTrace(); System.exit(-1); } catch (Exception ex) { log.log(Level.SEVERE, MessageNames.INITIALIZATION_EXCEPTION, ex); + ex.printStackTrace(); System.exit(-1); } } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Messages.properties Tue May 14 12:20:38 2013 @@ -52,7 +52,7 @@ configuredClasspath=The configured class contextItem=Context key {0} refers to ''{1}''. createdThread=Created thread named ''{0}'' in thread group ''{1}''. duplicateClasspath=Duplicate class path entry for id ''{0}''. -exceptionThrown=Exception thrown: +exceptionThrown=Exception thrown:\n{0} failedDeployService=Deployment of service archive at ''{0}'' failed. failedReadProperties=Failed to read one or more properties files. foundNoServiceArchives=Found no service archives for deployment dir ''{0}''. Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/Utils.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/Utils.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/Utils.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/Utils.java Tue May 14 12:20:38 2013 @@ -17,6 +17,8 @@ */ package org.apache.river.container; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -125,4 +127,11 @@ public class Utils { parent = parent.getParent(); } } + + public static String stackTrace(Throwable t) { + StringWriter s=new StringWriter(); + PrintWriter pw=new PrintWriter(s); + t.printStackTrace(pw); + return s.toString(); + } } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/ApplicationEnvironment.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/ApplicationEnvironment.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/ApplicationEnvironment.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/ApplicationEnvironment.java Tue May 14 12:20:38 2013 @@ -29,6 +29,25 @@ import org.apache.river.container.codeba public class ApplicationEnvironment { VirtualFileSystemClassLoader classLoader=null; + String serviceName=null; + + public StarterServiceLifeCycle getLifeCycle() { + return lifeCycle; + } + + public void setLifeCycle(StarterServiceLifeCycle lifeCycle) { + this.lifeCycle = lifeCycle; + } + + StarterServiceLifeCycle lifeCycle=null; + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } FileObject serviceArchive=null; FileObject serviceRoot=null; CodebaseContext codebaseContext=null; Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployer.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployer.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployer.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployer.java Tue May 14 12:20:38 2013 @@ -68,7 +68,7 @@ import org.apache.river.container.work.W @author trasukg */ -public class StarterServiceDeployer { +public class StarterServiceDeployer implements StarterServiceDeployerMXBean { private static final Logger log = Logger.getLogger(StarterServiceDeployer.class.getName(), MessageNames.BUNDLE_NAME); @@ -107,7 +107,7 @@ public class StarterServiceDeployer { @Injected(style = InjectionStyle.BY_TYPE) private ArgsParser argsParser = null; @Injected(style = InjectionStyle.BY_TYPE) - private WorkManager workManager = null; + WorkManager workManager = null; @Injected(style = InjectionStyle.BY_TYPE) private DynamicPolicyProvider securityPolicy = null; @@ -341,7 +341,7 @@ public class StarterServiceDeployer { deployServiceArchive(archiveFile); } catch (Throwable t) { log.log(Level.WARNING, MessageNames.FAILED_DEPLOY_SERVICE, archiveFile.toString()); - log.log(Level.WARNING, MessageNames.EXCEPTION_THROWN, t); + log.log(Level.WARNING, MessageNames.EXCEPTION_THROWN, Utils.stackTrace(t)); } } } @@ -352,10 +352,11 @@ public class StarterServiceDeployer { env.setServiceArchive(serviceArchive); env.setServiceRoot( serviceArchive.getFileSystem().getFileSystemManager().createFileSystem(Strings.JAR, serviceArchive)); + env.setLifeCycle(StarterServiceLifeCycleSM.newStarterServiceLifeCycle(env, this)); // Store it in our list of environments. applicationEnvironments.add(env); // Deploy it. - deployService(env); + env.getLifeCycle().start(); } private String findServiceName(FileObject serviceArchive, FileObject serviceRoot) { @@ -372,14 +373,17 @@ public class StarterServiceDeployer { return serviceRoot.getURL(); } - private void deployService(ApplicationEnvironment env) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { + void prepareService(ApplicationEnvironment env) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { String serviceName = findServiceName(env.getServiceArchive(), env.getServiceRoot()); + env.setServiceName(serviceName); CodeSource serviceCodeSource = new CodeSource(findServiceURL(env.getServiceArchive(), env.getServiceRoot()), new Certificate[0]); log.log(Level.INFO, MessageNames.CODESOURCE_IS, new Object[]{serviceName, serviceCodeSource}); VirtualFileSystemClassLoader cl = createServiceClassloader(env.getServiceRoot(), serviceCodeSource); + env.setClassLoader(cl); + /* Create a codebase context. */ @@ -400,12 +404,16 @@ public class StarterServiceDeployer { Permission[] perms = createPermissionsInClassloader(cl); grantPermissions(cl, perms); setupLiaisonConfiguration(env.getServiceArchive(), env.getServiceRoot(), cl); + + } + + void launchService(ApplicationEnvironment env) throws FileSystemException, IOException { Properties startProps = readStartProperties(env.getServiceRoot()); String argLine = startProps.getProperty(Strings.START_PARAMETERS); final String[] args = constructArgs(argLine); - launchService(cl, startProps, args); - log.log(Level.INFO, MessageNames.COMPLETED_SERVICE_DEPLOYMENT, serviceName); + launchService(env.getClassLoader(), startProps, args); + log.log(Level.INFO, MessageNames.COMPLETED_SERVICE_DEPLOYMENT, env.getServiceName()); } Permission[] createPermissionsInClassloader(ClassLoader cl) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { @@ -488,4 +496,31 @@ public class StarterServiceDeployer { private void establishLiveDeploymentMonitoring() { // TODO: Write this } + + @Override + public String shutdown(String appId) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String listApplications() { + StringBuilder sb=new StringBuilder(); + for (ApplicationEnvironment env: applicationEnvironments) { + sb.append(env.getServiceName()); + sb.append(" - "); + sb.append(env.getLifeCycle().getStatus()); + sb.append("\n"); + } + return sb.toString(); + } + + @Override + public String prepare(String appId) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String start(String appId) { + throw new UnsupportedOperationException("Not supported yet."); + } } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceDeployerMXBean.java Tue May 14 12:20:38 2013 @@ -23,4 +23,10 @@ package org.apache.river.container.deplo */ public interface StarterServiceDeployerMXBean { public String shutdown(String appId); + + public String listApplications(); + + public String prepare(String appId); + + public String start(String appId); } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycle.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycle.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycle.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycle.java Tue May 14 12:20:38 2013 @@ -25,4 +25,8 @@ public interface StarterServiceLifeCycle public void start(); public void stop(); + + public void prepare(); + + public String getStatus(); } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycleSM.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycleSM.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycleSM.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StarterServiceLifeCycleSM.java Tue May 14 12:20:38 2013 @@ -21,58 +21,117 @@ import java.util.logging.Logger; import org.apache.river.container.MessageNames; import org.apache.river.container.hsm.Controller; import org.apache.river.container.hsm.Initial; +import org.apache.river.container.hsm.PlainStateMachineExecutor; import org.apache.river.container.hsm.RootState; import org.apache.river.container.hsm.State; import org.apache.river.container.hsm.StateMachineInfo; +import org.apache.river.container.hsm.Transition; +import org.apache.river.container.work.TaskClass; /** - * Life cycle controller for "service-starter" services. - * Idle --> Starting --> Running --> Stopping --> Idle - * --> Zombie + * Life cycle controller for "service-starter" services. Idle --> Starting --> + * Running --> Stopping --> Idle --> Zombie */ -@RootState(StarterServiceLifeCycle.class) -public class StarterServiceLifeCycleSM implements StarterServiceLifeCycle { - - private static final Logger logger=Logger.getLogger(StarterServiceLifeCycleSM.class.getName(), +@RootState({StarterServiceLifeCycle.class, StatusEvents.class}) +public class StarterServiceLifeCycleSM { + + private static final Logger logger = Logger.getLogger(StarterServiceLifeCycleSM.class.getName(), MessageNames.BUNDLE_NAME); - - private ApplicationEnvironment appEnv=null; - private StarterServiceDeployer deployer=null; - - public StarterServiceLifeCycleSM(ApplicationEnvironment appEnv, StarterServiceDeployer deployer) { - this.appEnv=appEnv; - this.deployer=deployer; + private ApplicationEnvironment appEnv = null; + private StarterServiceDeployer deployer = null; + private StatusEvents eventProxy = null; + private StarterServiceLifeCycle lifeCycleProxy = null; + + public static StarterServiceLifeCycle newStarterServiceLifeCycle(ApplicationEnvironment appEnv, StarterServiceDeployer deployer) { + StarterServiceLifeCycleSM machine = new StarterServiceLifeCycleSM(); + machine.appEnv = appEnv; + machine.deployer = deployer; + machine.eventProxy = (StatusEvents) PlainStateMachineExecutor.createProxy(machine); + machine.lifeCycleProxy = (StarterServiceLifeCycle) machine.eventProxy; + return machine.lifeCycleProxy; } - - @State({Idle.class, Starting.class, Running.class, Stopping.class, Idle.class}) + @State({Idle.class, Preparing.class, Prepared.class, Starting.class, Failed.class, Running.class, Stopping.class, Idle.class}) @Initial(Idle.class) private Object state; - @Controller private StateMachineInfo controller; - @Override - public void start() { - } - - @Override - public void stop() { + public String getStatus() { + return state.getClass().getSimpleName(); } public class Idle { - + /* + * To start from idle means to prepare, and then start. + */ + + @Transition(Preparing.class) + public void start() { + Runnable command = new Runnable() { + public void run() { + /* Prepare the application environment. */ + try { + deployer.prepareService(appEnv); + eventProxy.prepareSucceeded(); + } catch (Exception ex) { + eventProxy.prepareFailed(ex); + } + + lifeCycleProxy.start(); + } + }; + deployer.workManager.queueTask(TaskClass.SYSTEM_TASK, null, command); + } + + @Transition(Preparing.class) + public void prepare() { + Runnable command = new Runnable() { + public void run() { + /* Prepare the application environment. */ + try { + deployer.prepareService(appEnv); + eventProxy.prepareSucceeded(); + } catch (Exception ex) { + eventProxy.prepareFailed(ex); + } + } + }; + deployer.workManager.queueTask(TaskClass.SYSTEM_TASK, null, command); + } + } - + + public class Preparing { + } + + public class Prepared { + @Transition(Starting.class) + public void start() { + Runnable command = new Runnable() { + public void run() { + /* Prepare the application environment. */ + try { + deployer.launchService(appEnv); + eventProxy.startSucceeded(); + } catch (Exception ex) { + eventProxy.startFailed(ex); + } + } + }; + deployer.workManager.queueTask(TaskClass.SYSTEM_TASK, null, command); + + } + } + public class Running { - } - + + public class Failed { + } + public class Stopping { - } - + public class Starting { - } - } Added: river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StatusEvents.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StatusEvents.java?rev=1482317&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StatusEvents.java (added) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/deployer/StatusEvents.java Tue May 14 12:20:38 2013 @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.river.container.deployer; + +/** + * + * @author trasukg + */ +interface StatusEvents { + public void prepareSucceeded(); + + public void prepareFailed(Exception ex); + + public void startSucceeded(); + + public void startFailed(Exception ex); + + public void tick(); +} Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/PlainStateMachineExecutor.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/PlainStateMachineExecutor.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/PlainStateMachineExecutor.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/PlainStateMachineExecutor.java Tue May 14 12:20:38 2013 @@ -66,7 +66,7 @@ public class PlainStateMachineExecutor i StateMachineCompiler compiler = new StateMachineCompiler(); try { MetaState rootState = compiler.compile(rootStateInstance.getClass()); - rootState.stateInstance=rootStateInstance; + rootState.stateInstance = rootStateInstance; instantiate(rootState); return createProxy(rootState); } catch (StateMachineException ex) { @@ -87,7 +87,7 @@ public class PlainStateMachineExecutor i @Override public void visit(MetaState metaState) { try { - if (metaState.stateInstance!=null) { + if (metaState.stateInstance != null) { return; } /* @@ -118,9 +118,9 @@ public class PlainStateMachineExecutor i public void visit(MetaState metaState) { try { for (SubstateInfo ssi : metaState.substates) { + ssi.setObjectThatHoldsField(metaState.stateInstance); log.log(Level.FINE, MessageNames.SETTING_FIELD_TO, new Object[]{ssi.getField().getName(), metaState.stateInstance, ssi.getInitialMetaState().stateInstance}); - - ssi.getField().set(metaState.stateInstance, ssi.getInitialMetaState().stateInstance); + writeStateField(ssi, metaState); } } catch (Exception ex) { throw new StateMachineException(ex, MessageNames.BUNDLE_NAME, MessageNames.ERROR_INSTANTIATING); @@ -129,6 +129,13 @@ public class PlainStateMachineExecutor i }); } + private static void writeStateField(SubstateInfo ssi, MetaState metaState) throws IllegalArgumentException, IllegalAccessException, SecurityException { + boolean originalAccess = ssi.getField().isAccessible(); + ssi.getField().setAccessible(true); + ssi.getField().set(ssi.getObjectThatHoldsField(), ssi.getInitialMetaState().stateInstance); + ssi.getField().setAccessible(originalAccess); + } + private static Object findAParentInstance(MetaState metaState, Class enclosingClass) { for (MetaState currentState = metaState.parent; currentState != null; currentState = currentState.parent) { if (currentState.stateClass == enclosingClass) { @@ -141,12 +148,12 @@ public class PlainStateMachineExecutor i public static Object createProxy(MetaState instantiatedMetaState) { RootState rootStateAnnotation = (RootState) instantiatedMetaState.stateClass.getAnnotation(RootState.class); - Class eventInterface = rootStateAnnotation.value(); + Class[] eventInterfaces = rootStateAnnotation.value(); PlainStateMachineExecutor executor = new PlainStateMachineExecutor(instantiatedMetaState); executor.activate(); Object proxy = - Proxy.newProxyInstance(eventInterface.getClassLoader(), - new Class[]{eventInterface}, + Proxy.newProxyInstance(eventInterfaces[0].getClassLoader(), + eventInterfaces, executor.getInvocationHandler()); return proxy; } @@ -306,10 +313,15 @@ public class PlainStateMachineExecutor i private void applyTransition(TransitionOnSubstate tos) { try { tos.substate.setActiveMetaState(tos.targetMetaState); - tos.substate.getField().set(tos.targetMetaState.parent.stateInstance, tos.targetMetaState.stateInstance); + writeStateField(tos.substate, tos.targetMetaState); + /* Get rid of this - it doesn't work on private fields. Use the writeStateField() above. + tos.substate.getField().set(tos.targetMetaState.parent.stateInstance, tos.targetMetaState.stateInstance); + */ } catch (Exception ex) { - throw new StateMachineException(MessageNames.BUNDLE_NAME, MessageNames.ERROR_APPLYING_TRANSITION, + StateMachineException sme = new StateMachineException(ex, MessageNames.BUNDLE_NAME, MessageNames.ERROR_APPLYING_TRANSITION, new Object[]{ex.getMessage()}); + //sme.printStackTrace(); + throw sme; } } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/RootState.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/RootState.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/RootState.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/RootState.java Tue May 14 12:20:38 2013 @@ -33,8 +33,8 @@ import java.lang.annotation.Target; @Target(ElementType.TYPE) public @interface RootState { /** - The event interface that this machine is intended to implement. + The event interfaces that this machine is intended to implement. @return */ - Class value(); + Class[] value(); } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/StateMachineCompiler.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/StateMachineCompiler.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/StateMachineCompiler.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/StateMachineCompiler.java Tue May 14 12:20:38 2013 @@ -36,10 +36,9 @@ import org.apache.river.container.Utils; */ public class StateMachineCompiler { - private static final Logger log= - Logger.getLogger(StateMachineCompiler.class.getName(),MessageNames.BUNDLE_NAME); - - Class eventInterface = null; + private static final Logger log = + Logger.getLogger(StateMachineCompiler.class.getName(), MessageNames.BUNDLE_NAME); + Class[] eventInterfaces = null; /** * Retrieve the event interface, as set by the @@ -47,13 +46,13 @@ public class StateMachineCompiler { * @RootState annotation. * @return The event interface. */ - public Class getEventInterface() { - return eventInterface; + public Class[] getEventInterfaces() { + return eventInterfaces; } public MetaState compile(Class rootStateClass) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { - log.log(Level.FINE, MessageNames.BEGINNING_COMPILE, new Object[] {rootStateClass.getName()}); - findEventInterface(rootStateClass); + log.log(Level.FINE, MessageNames.BEGINNING_COMPILE, new Object[]{rootStateClass.getName()}); + findEventInterfaces(rootStateClass); // First pass: create all metastates MetaState rootMetaState = createMetaState(rootStateClass); // Second pass: Fill in event methods @@ -70,16 +69,16 @@ public class StateMachineCompiler { } } }); - log.log(Level.FINE, MessageNames.COMPILE_COMPLETED, new Object[] {rootStateClass.getName()}); + log.log(Level.FINE, MessageNames.COMPILE_COMPLETED, new Object[]{rootStateClass.getName()}); return rootMetaState; } - private void findEventInterface(Class rootStateClass) { + private void findEventInterfaces(Class rootStateClass) { RootState rootStateAnnotation = (RootState) rootStateClass.getAnnotation(RootState.class); if (rootStateAnnotation == null || rootStateAnnotation.value() == null) { throw new RuntimeException("Root state class must specify @RootState(interfaceClass)."); } - eventInterface = rootStateAnnotation.value(); + eventInterfaces = rootStateAnnotation.value(); } MetaState createMetaState(Class stateClass) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { @@ -131,11 +130,11 @@ public class StateMachineCompiler { info.setActiveMetaState(info.getInitialMetaState()); Retained retainedAnn = f.getAnnotation(Retained.class); info.setRetained(retainedAnn != null); - + /* Add the non-retained metastate to the list of transitions-on-entry of the * parent metastat. */ - if (! info.isRetained()) { + if (!info.isRetained()) { metaState.entryTransitions.add(new TransitionOnSubstate(info, info.getInitialMetaState())); } } @@ -175,41 +174,43 @@ public class StateMachineCompiler { } private void fillInEventMethods(MetaState metaState) throws NoSuchMethodException { - for (Method m : getEventInterface().getMethods()) { - /* See if the state class has a method with the same name and - * parameters. - */ - Method eventMethod = null; - try { - eventMethod = metaState.stateClass.getMethod(m.getName(), m.getParameterTypes()); - } catch (NoSuchMethodException nsme) { - // Silent catch - lets the event method remain null, which we check for. - } - Operation operation = null; - if (eventMethod != null) { - if (eventMethod.getReturnType() != null && !m.getReturnType().isAssignableFrom(eventMethod.getReturnType())) { - throw new RuntimeException("If the event method returns a value, its type must match the event interface's method. Required" - + m.getReturnType() + ", found " + eventMethod.getReturnType()); + for (Class eventInterface : getEventInterfaces()) { + for (Method m : eventInterface.getMethods()) { + /* See if the state class has a method with the same name and + * parameters. + */ + Method eventMethod = null; + try { + eventMethod = metaState.stateClass.getMethod(m.getName(), m.getParameterTypes()); + } catch (NoSuchMethodException nsme) { + // Silent catch - lets the event method remain null, which we check for. } - Transition transition = eventMethod.getAnnotation(Transition.class); - // Fill in from here down! - // Return value, no transition - if (eventMethod.getReturnType() != null && transition == null) { - operation = new InvokeAndTransitionOperation(metaState, eventMethod); - } // Return value with transition - else if (eventMethod.getReturnType() != null && transition != null) { - TransitionOnSubstate[] transitions = resolveTransitions(metaState, transition.value()); - operation = new InvokeAndTransitionOperation(metaState, eventMethod, transitions); - } // No return value, no transition - else if (eventMethod.getReturnType() == null && transition == null) { - operation = new InvokeVoidAndTransitionOperation(metaState, eventMethod); - } // No return value, with transition - else if (eventMethod.getReturnType() == null && transition != null) { - TransitionOnSubstate[] transitions = resolveTransitions(metaState, transition.value()); - operation = new InvokeVoidAndTransitionOperation(metaState, eventMethod, transitions); + Operation operation = null; + if (eventMethod != null) { + if (eventMethod.getReturnType() != null && !m.getReturnType().isAssignableFrom(eventMethod.getReturnType())) { + throw new RuntimeException("If the event method returns a value, its type must match the event interface's method. Required" + + m.getReturnType() + ", found " + eventMethod.getReturnType()); + } + Transition transition = eventMethod.getAnnotation(Transition.class); + // Fill in from here down! + // Return value, no transition + if (eventMethod.getReturnType() != null && transition == null) { + operation = new InvokeAndTransitionOperation(metaState, eventMethod); + } // Return value with transition + else if (eventMethod.getReturnType() != null && transition != null) { + TransitionOnSubstate[] transitions = resolveTransitions(metaState, transition.value()); + operation = new InvokeAndTransitionOperation(metaState, eventMethod, transitions); + } // No return value, no transition + else if (eventMethod.getReturnType() == null && transition == null) { + operation = new InvokeVoidAndTransitionOperation(metaState, eventMethod); + } // No return value, with transition + else if (eventMethod.getReturnType() == null && transition != null) { + TransitionOnSubstate[] transitions = resolveTransitions(metaState, transition.value()); + operation = new InvokeVoidAndTransitionOperation(metaState, eventMethod, transitions); + } } + metaState.eventMethods.put(m, operation); } - metaState.eventMethods.put(m, operation); } } Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/SubstateInfo.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/SubstateInfo.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/SubstateInfo.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/hsm/SubstateInfo.java Tue May 14 12:20:38 2013 @@ -27,6 +27,15 @@ import java.lang.reflect.Field; class SubstateInfo { private Field field; + private Object objectThatHoldsField; + + public Object getObjectThatHoldsField() { + return objectThatHoldsField; + } + + public void setObjectThatHoldsField(Object objectThatHoldsField) { + this.objectThatHoldsField = objectThatHoldsField; + } /** this field will disappear when the StateMachineCompiler is complete. */ private Class[] possibleStates; Modified: river/jtsk/skunk/surrogate/src/org/apache/river/container/work/BasicWorkManager.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/src/org/apache/river/container/work/BasicWorkManager.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/src/org/apache/river/container/work/BasicWorkManager.java (original) +++ river/jtsk/skunk/surrogate/src/org/apache/river/container/work/BasicWorkManager.java Tue May 14 12:20:38 2013 @@ -29,46 +29,47 @@ import org.apache.river.container.Shutdo import org.apache.river.container.Strings; /** - -A Basic implementation of WorkManager that runs the work threads through -a ThreadPoolExecutor. - + * + * A Basic implementation of WorkManager that runs the work threads through a + * ThreadPoolExecutor. + * * @author trasukg */ public class BasicWorkManager implements WorkManager { - private static final Logger log=Logger.getLogger(BasicWorkManager.class.getName(), MessageNames.BUNDLE_NAME); - + + private static final Logger log = Logger.getLogger(BasicWorkManager.class.getName(), MessageNames.BUNDLE_NAME); ExecutorService executor = null; - private MyThreadFactory threadFactory=null; - - private String name=Strings.UNNAMED; - - public BasicWorkManager() {} - + private MyThreadFactory threadFactory = null; + private String name = Strings.UNNAMED; + + public BasicWorkManager() { + threadFactory = new MyThreadFactory(); + executor = Executors.newCachedThreadPool(threadFactory); + } + public BasicWorkManager(String name) { - this.name=name; - threadFactory=new MyThreadFactory(); - executor=Executors.newCachedThreadPool(threadFactory); - } - - int activeCount=0; - + this.name = name; + threadFactory = new MyThreadFactory(); + executor = Executors.newCachedThreadPool(threadFactory); + } + int activeCount = 0; + synchronized void incActiveCount() { activeCount++; } - + synchronized void decActiveCount() { activeCount--; } - + synchronized int getActiveCount() { //return activeCount; return threadFactory.threadGroup.activeCount(); } - + @Override public void queueTask(TaskClass taskClass, ClassLoader contextClassLoader, Runnable task) { - ClassLoader classLoaderToUse = + ClassLoader classLoaderToUse = contextClassLoader != null ? contextClassLoader : Thread.currentThread().getContextClassLoader(); executor.execute(new TaskHolder(task, classLoaderToUse)); } @@ -97,31 +98,29 @@ public class BasicWorkManager implements } } } - + @Init public void init() { log.info(MessageNames.BASIC_WORK_MANAGER_INITIALIZED); } - + @Shutdown public void shutdown() { executor.shutdownNow(); } - + private class MyThreadFactory implements ThreadFactory { - private ThreadGroup threadGroup=new ThreadGroup(name); - private int index=0; - + private ThreadGroup threadGroup = new ThreadGroup(name); + private int index = 0; + @Override public Thread newThread(Runnable r) { - Thread t=new Thread(threadGroup, r); + Thread t = new Thread(threadGroup, r); t.setName(name + Strings.DASH + index++); - log.log(Level.FINE,MessageNames.CREATED_THREAD, - new Object[] { t.getName(), t.getThreadGroup().getName() }); + log.log(Level.FINE, MessageNames.CREATED_THREAD, + new Object[]{t.getName(), t.getThreadGroup().getName()}); return t; } - } - } Added: river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/HSMTestSuite.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/HSMTestSuite.java?rev=1482317&view=auto ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/HSMTestSuite.java (added) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/HSMTestSuite.java Tue May 14 12:20:38 2013 @@ -0,0 +1,38 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.apache.river.container.hsm; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * + * @author trasukg + */ +@RunWith(Suite.class) [email protected]({LoggingTest.class, ReturnTypeTest.class, InitializedMachineTest.class, StateMachineCompilerTest.class, PlainMachineExecutorTest.class}) +public class HSMTestSuite { + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + +} Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/PlainMachineExecutorTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/PlainMachineExecutorTest.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/PlainMachineExecutorTest.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/PlainMachineExecutorTest.java Tue May 14 12:20:38 2013 @@ -17,7 +17,6 @@ */ package org.apache.river.container.hsm; - import java.util.List; import java.lang.reflect.InvocationTargetException; import java.util.logging.Logger; @@ -38,11 +37,11 @@ import static org.junit.Assert.assertTru */ public class PlainMachineExecutorTest { - private static final Logger log= + private static final Logger log = Logger.getLogger(PlainMachineExecutorTest.class.getName()); - + public PlainMachineExecutorTest() throws InstantiationException, IllegalAccessException, - NoSuchMethodException, InvocationTargetException { + NoSuchMethodException, InvocationTargetException { } @BeforeClass @@ -61,13 +60,12 @@ public class PlainMachineExecutorTest { @After public void tearDown() { } - - TestSMInterface UUT=(TestSMInterface) - PlainStateMachineExecutor.createProxy(TestSM.class); + TestSMInterface UUT = (TestSMInterface) PlainStateMachineExecutor.createProxy(TestSM.class); @Test - /** Verify that the list of active states is correct at beginning. - + /** + * Verify that the list of active states is correct at beginning. + * */ public void testActiveStates() { @@ -82,9 +80,9 @@ public class PlainMachineExecutorTest { @Test /** - Test that the top-level (state-invariant) sayHelloConstant() method returns - the correct value. Verifies that the top-level proxy is functioning - correctly. + * Test that the top-level (state-invariant) sayHelloConstant() method + * returns the correct value. Verifies that the top-level proxy is + * functioning correctly. */ public void testStateMachine() throws InstantiationException, IllegalAccessException { assertEquals("Hello", UUT.sayConstantHello()); @@ -92,9 +90,9 @@ public class PlainMachineExecutorTest { @Test /** - Test that the top-level (state-invariant) sayHelloConstant() method returns - the correct value. Verifies that the top-level proxy is functioning - correctly. + * Test that the top-level (state-invariant) sayHelloConstant() method + * returns the correct value. Verifies that the top-level proxy is + * functioning correctly. */ public void testNullReturn() throws InstantiationException, IllegalAccessException { assertEquals(null, UUT.returnNull()); @@ -102,16 +100,12 @@ public class PlainMachineExecutorTest { @Test /** - <p> - Verify that transitions from state A to B work, and that the behaviour - varies with state. - </p> - - <p> - First call to sayHello() should return "Hello", second call should return - "There". - </p> - + * <p> Verify that transitions from state A to B work, and that the + * behaviour varies with state. </p> + * + * <p> First call to sayHello() should return "Hello", second call should + * return "There". </p> + * */ public void testSimpleTransition() throws InstantiationException, IllegalAccessException { assertTrue("activeStates should contain A.", @@ -119,7 +113,7 @@ public class PlainMachineExecutorTest { log.info("\n\nCalling hello()\n\n"); assertEquals("Hello", UUT.sayHello()); log.info("\n\n...done\n\n"); - List<Class> activeStates=UUT.getActiveStates(); + List<Class> activeStates = UUT.getActiveStates(); assertTrue("activeStates should contain B after transition.", activeStates.contains(TestSM.B.class)); log.info("TestSM.B appears to have been active."); @@ -130,7 +124,7 @@ public class PlainMachineExecutorTest { @Test /** - When we enter a state, the entry method should be called. + * When we enter a state, the entry method should be called. */ public void testEntryMethodExecution() { assertEquals(1, UUT.getAEntryCount()); @@ -140,8 +134,8 @@ public class PlainMachineExecutorTest { @Test /** - When we transition to a state but we are already in that state, the - onEntry method should not be run. + * When we transition to a state but we are already in that state, the + * onEntry method should not be run. */ public void testNullTransition() { UUT.nullTransition(); @@ -152,19 +146,19 @@ public class PlainMachineExecutorTest { @Test /** - Make sure that the gotoA() and gotoB() methods cause the appropriate - transitions. + * Make sure that the gotoA() and gotoB() methods cause the appropriate + * transitions. */ public void testABTransitions() { UUT.gotoA(); assertTrue("activeStates should contain A.", UUT.getActiveStates().contains(TestSM.A.class)); assertFalse("activeStates should not contain B.", - UUT.getActiveStates().contains(TestSM.B.class)); + UUT.getActiveStates().contains(TestSM.B.class)); UUT.gotoB(); assertFalse("activeStates should not contain A.", - UUT.getActiveStates().contains(TestSM.A.class)); + UUT.getActiveStates().contains(TestSM.A.class)); assertTrue("activeStates should contain B.", UUT.getActiveStates().contains(TestSM.B.class)); @@ -172,24 +166,25 @@ public class PlainMachineExecutorTest { assertTrue("activeStates should contain A.", UUT.getActiveStates().contains(TestSM.A.class)); assertFalse("activeStates should not contain B.", - UUT.getActiveStates().contains(TestSM.B.class)); + UUT.getActiveStates().contains(TestSM.B.class)); } @Test /** - @Retained annotations should be respected, and states should be - initialized on entry if the @Retained is not there. + * @Retained annotations should be respected, and states should be + * initialized on entry if the + * @Retained is not there. */ public void testStateInitialization() { UUT.gotoA(); assertTrue("activeStates should contain A.", UUT.getActiveStates().contains(TestSM.A.class)); assertFalse("activeStates should not contain B.", - UUT.getActiveStates().contains(TestSM.B.class)); + UUT.getActiveStates().contains(TestSM.B.class)); UUT.gotoB(); assertFalse("activeStates should not contain A.", - UUT.getActiveStates().contains(TestSM.A.class)); + UUT.getActiveStates().contains(TestSM.A.class)); assertTrue("activeStates should contain B.", UUT.getActiveStates().contains(TestSM.B.class)); assertTrue("activeStates should contain B1.", @@ -208,4 +203,26 @@ public class PlainMachineExecutorTest { } + + @Test + /** + * <p> Verify that the second interface is on the proxy and effective. </p> + * + * <p> After call to doSecondInterfaceAction(), call to sayHello() should + * return "HelloFromC". </p> + * + */ + public void testSecondInterface() throws InstantiationException, IllegalAccessException { + log.info("\n\nCalling doSecondInterfaceAction()\n\n"); + TestSMSecondInterface UUT2=(TestSMSecondInterface) UUT; + UUT2.doSecondInterfaceAction(); + log.info("\n\n...done\n\n"); + List<Class> activeStates = UUT.getActiveStates(); + assertTrue("activeStates should contain C after transition.", + activeStates.contains(TestSM.C.class)); + log.info("TestSM.C appears to have been active."); + assertFalse("activeStates should not contain A after transition.", + activeStates.contains(TestSM.A.class)); + assertEquals("HelloFromC", UUT.sayHello()); + } } \ No newline at end of file Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/ReturnTypeTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/ReturnTypeTest.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/ReturnTypeTest.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/ReturnTypeTest.java Tue May 14 12:20:38 2013 @@ -43,7 +43,7 @@ public class ReturnTypeTest { @Test public void testVoidReturnType() throws Exception { Method m=this.getClass().getMethod("testVoidReturnType", new Class[0]); - assertEquals("return type wasn't null", null, m.getReturnType()); + assertEquals("return type wasn't void", void.class, m.getReturnType()); } } Modified: river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSM.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSM.java?rev=1482317&r1=1482316&r2=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSM.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSM.java Tue May 14 12:20:38 2013 @@ -25,10 +25,10 @@ import java.util.logging.Logger; * * @author trasukg */ -@RootState(TestSMInterface.class) +@RootState({TestSMInterface.class, TestSMSecondInterface.class}) public class TestSM { - @State({A.class, B.class}) + @State({A.class, B.class, C.class}) @Initial(A.class) @Retained public Object state; @@ -58,6 +58,9 @@ public class TestSM { //controller.transition(B.class); } + @Transition(C.class) + public void doSecondInterfaceAction() { } + public int getAEntryCount() { return aEntryCount; } @@ -134,4 +137,10 @@ public class TestSM { public class B3 { } + + public class C { + public String sayHello() { + return "HelloFromC"; + } + } } Copied: river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMSecondInterface.java (from r1427243, river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMInterface.java) URL: http://svn.apache.org/viewvc/river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMSecondInterface.java?p2=river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMSecondInterface.java&p1=river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMInterface.java&r1=1427243&r2=1482317&rev=1482317&view=diff ============================================================================== --- river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMInterface.java (original) +++ river/jtsk/skunk/surrogate/test/org/apache/river/container/hsm/TestSMSecondInterface.java Tue May 14 12:20:38 2013 @@ -23,26 +23,7 @@ import java.util.List; * * @author trasukg */ -public interface TestSMInterface { +public interface TestSMSecondInterface { - public String sayHello(); - - public String sayConstantHello(); - - public Object returnNull(); - - public int getNullTransitionEntryCount(); - - public void nullTransition(); - - public int getAEntryCount(); - - public int getAExitCount(); - - public void moveSubstateOfB(); - - public void gotoA(); - public void gotoB(); - - List<Class> getActiveStates(); + public void doSecondInterfaceAction(); }
