summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbkolb2007-09-25 14:09:06 (EDT)
committerbkolb2007-09-25 14:09:06 (EDT)
commit405a46d9696d39620d0447999232e398790dbfe7 (patch)
tree60128cdd055d9c4e60969c93fa9ddeb9ab2fc5f1
parent5bc619e7833d7a5c00e17acec041383e0a8ffbd2 (diff)
downloadorg.eclipse.mwe-405a46d9696d39620d0447999232e398790dbfe7.zip
org.eclipse.mwe-405a46d9696d39620d0447999232e398790dbfe7.tar.gz
org.eclipse.mwe-405a46d9696d39620d0447999232e398790dbfe7.tar.bz2
initial check-in
* restructured projects * separation between internal and external API * replaced some internals with Eclipse/EMF features
-rw-r--r--plugins/org.eclipse.emf.mwe.core/.classpath7
-rw-r--r--plugins/org.eclipse.emf.mwe.core/.project28
-rw-r--r--plugins/org.eclipse.emf.mwe.core/META-INF/MANIFEST.MF38
-rw-r--r--plugins/org.eclipse.emf.mwe.core/build.properties14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/plugin.properties12
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/log4j.properties29
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ConfigurationException.java58
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponent.java75
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponentWithID.java31
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowContext.java51
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowInterruptedException.java32
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowRunner.java404
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/Parameter.java48
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/WorkflowAntTask.java94
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ao/AbstractWorkflowAdvice.java54
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/AttributeNotFound.java14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/ConfigurationModel.java14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureComponent.java68
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureNotFound.java14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/GlobalConfigurationHolder.java24
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/CompositeComponent.java281
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionEvaluationException.java14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionalComponent.java65
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/IfComponent.java37
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/WorkflowConditional.java8
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/CustomizationException.java14
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/WorkflowCustomization.java32
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/model/SyntaxElement.java72
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/processing/ElementAdapter.java157
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/Issues.java176
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/IssuesImpl.java187
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/MWEDiagnostic.java255
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/AbstractWorkflowComponent.java130
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/WorkflowComponentWithModelSlot.java32
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/NullProgressMonitor.java112
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/ProgressMonitor.java83
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoader.java47
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoaderFactory.java75
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/Workflow.java31
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkflowContextDefaultImpl.java56
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkfowComponentHelper.java164
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/AbstractASTBase.java55
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ComponentAST.java84
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyAST.java50
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyFileAST.java105
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/InclusionAST.java80
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/NamedAST.java15
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ReferenceAST.java57
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/SimpleParamAST.java44
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/Location.java75
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/ParseException.java29
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/WorkflowParser.java195
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/XmlLocationAnalyser.java333
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/Injector.java21
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorFactory.java111
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorList.java45
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorPut.java60
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorSimple.java45
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorAnalyzer.java176
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorBase.java90
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorCreator.java202
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorInitializer.java264
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowContainer.java30
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowFactory.java138
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/BooleanConverter.java19
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/Converter.java15
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/IntegerConverter.java19
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringArrayConverter.java19
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringConverter.java19
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/Connection.java215
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketReceiver.java176
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketSender.java119
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/AbstractPacket.java75
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/BreakpointPacket.java58
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/CommandPacket.java49
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/ConfirmationPacket.java42
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacket.java53
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacketWithFrames.java69
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/HandshakePacket.java31
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RegisterPacket.java57
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RequireVarPacket.java57
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/VarDataPacket.java61
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/NameValuePair.java31
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValue.java39
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValueTO.java65
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/ReflectionUtil.java154
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/WorkflowElementAdapter.java200
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/CommandListener.java30
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebugMonitor.java320
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebuggerInterruptedException.java33
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/EventHandler.java39
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/ProcessHandler.java68
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandler.java37
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandlerManager.java107
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/BreakpointRuntimeHandler.java189
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/CommandRuntimeHandler.java307
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/EventRuntimeHandler.java177
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/VariablesRuntimeHandler.java297
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderDefaultImpl.java118
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderImpl.java39
-rw-r--r--plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/util/ComponentPrinter.java94
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/.classpath7
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/.project28
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/META-INF/MANIFEST.MF11
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/build.properties5
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/icons/workflowfile.gifbin0 -> 936 bytes
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/plugin.xml16
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/ColorManager.java43
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/NonRuleBasedDamagerRepairer.java136
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/TagRule.java46
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/WorkflowEditor.java74
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLColorConstants.java29
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLConfiguration.java91
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDocumentProvider.java36
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDoubleClickStrategy.java131
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLPartitionScanner.java42
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLScanner.java38
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLTagScanner.java41
-rw-r--r--plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLWhitespaceDetector.java24
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/.classpath7
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/.cvsignore5
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/.project28
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/META-INF/MANIFEST.MF34
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/build.properties17
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/icons/oawlaunch.gifbin0 -> 878 bytes
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/icons/workflowfile.gifbin0 -> 936 bytes
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/plugin.properties12
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/plugin.xml179
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/schema/adapters.exsd150
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/schema/handlers.exsd176
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/BreakpointActionGroup.java172
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/EnableDisableBreakpointAction.java110
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/ToggleBreakpointAction.java95
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigMainTab.java260
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigTabGroup.java34
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugElement.java75
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugStackFrame.java188
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugTarget.java275
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugThread.java197
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugValue.java128
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugVariable.java83
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/MWEBreakpoint.java102
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/DebugModelPresentation.java99
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/JarEntryEditorInput.java48
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/VariableSorter.java41
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/DebugModelManager.java281
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginAdapter.java41
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginExtensionManager.java210
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginHandler.java22
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/BreakpointPluginHandler.java51
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/CommandPluginHandler.java77
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/EventPluginHandler.java114
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/VariablesPluginHandler.java54
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupDirector.java21
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupParticipant.java28
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourcePathComputerDelegate.java35
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/PackageFragmentRootContainer.java97
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceFolderSourceContainer.java114
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceLookupUtil.java121
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWEDebuggerLauncher.java239
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchConfigurationConstants.java28
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchDelegate.java189
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchShortcut.java184
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/wizard/NewWorkflowFileWizard.java118
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/Activator.java87
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/debug/MWEPluginAdapter.java180
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/util/PluginConfigurationElementUtil.java51
-rw-r--r--plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/util/ProjectIncludingResourceLoader.java71
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/.classpath7
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/.project28
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/META-INF/MANIFEST.MF11
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/build.properties4
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/internal/utils/SingleGlobalResourceSet.java17
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/AbstractEMFWorkflowComponent.java40
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/DirectoryCleaner.java141
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/Mapping.java45
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/Reader.java78
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/StandaloneSetup.java240
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/StandartComponentMappingHelper.java16
-rw-r--r--plugins/org.eclipse.emf.mwe.utils/src/org/eclipse/emf/mwe/utils/Writer.java144
-rw-r--r--tests/org.eclipse.emf.mwe.tests/.classpath8
-rw-r--r--tests/org.eclipse.emf.mwe.tests/.project28
-rw-r--r--tests/org.eclipse.emf.mwe.tests/META-INF/MANIFEST.MF21
-rw-r--r--tests/org.eclipse.emf.mwe.tests/build.properties12
-rw-r--r--tests/org.eclipse.emf.mwe.tests/plugin.properties12
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/Component.java130
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/SubComponent.java25
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/aBean.oaw5
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/aCartridge.oaw9
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/aComp.oaw2
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/importingWorkflow.oaw20
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/inheritAll1.oaw6
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/complex/inheritAll2.oaw7
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/testPropertyResolution.oaw14
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/testPropertyResolution.properties12
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/testSimpleLinker.oaw8
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/workflow.properties12
-rw-r--r--tests/org.eclipse.emf.mwe.tests/resources/test/res/workflowWithPropertyFile.xml12
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/WorkflowRunnerTest.java21
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/ast/WorkflowParserTest.java66
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/ast/parser/XmlLocationAnalyserTest.java199
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/ast/util/AbstractWorkflowParsingTestBase.java53
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/ast/util/VisitorAnalyzerTest.java32
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/ast/util/WorkflowFactoryTest.java174
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/lib/AbstractWorkflowComponentTest.java58
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/util/DummyResourceLoader.java47
-rw-r--r--tests/org.eclipse.emf.mwe.tests/src/org/eclipse/emf/mwe/core/tests/util/ResourceLoaderFactoryTest.java77
208 files changed, 16512 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.mwe.core/.classpath b/plugins/org.eclipse.emf.mwe.core/.classpath
new file mode 100644
index 0000000..d524183
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="org/eclipse/emf/mwe/core/issues/Issue.java" kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.emf.mwe.core/.project b/plugins/org.eclipse.emf.mwe.core/.project
new file mode 100644
index 0000000..8e2b155
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.emf.mwe.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.emf.mwe.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.mwe.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..4644f73
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/META-INF/MANIFEST.MF
@@ -0,0 +1,38 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.emf.mwe.core
+Bundle-Version: 1.0.0.qualifier
+Bundle-Localization: plugin
+Bundle-Vendor: %providerName
+Require-Bundle: org.apache.ant,
+ org.apache.commons.cli,
+ org.apache.commons.logging,
+ org.eclipse.emf.ecore
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Eclipse-BuddyPolicy: dependent
+Export-Package: org.eclipse.emf.mwe.core,
+ org.eclipse.emf.mwe.core.ant,
+ org.eclipse.emf.mwe.core.ao,
+ org.eclipse.emf.mwe.core.config,
+ org.eclipse.emf.mwe.core.container,
+ org.eclipse.emf.mwe.core.customizer,
+ org.eclipse.emf.mwe.core.debug.model,
+ org.eclipse.emf.mwe.core.debug.processing,
+ org.eclipse.emf.mwe.core.issues,
+ org.eclipse.emf.mwe.core.lib,
+ org.eclipse.emf.mwe.core.monitor,
+ org.eclipse.emf.mwe.core.resources,
+ org.eclipse.emf.mwe.internal.core;x-friends:="org.eclipse.emf.mwe.ui.wtpeditor,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.ast;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.ast.parser;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.ast.util;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.ast.util.converter;x-friends:="org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.communication;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.communication.packets;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.model;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.mwe;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.processing;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.debug.processing.handlers;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.resources;x-friends:="org.eclipse.emf.mwe.ui,org.eclipse.emf.mwe.core.tests",
+ org.eclipse.emf.mwe.internal.core.util;x-friends:="org.eclipse.emf.mwe.core.tests"
diff --git a/plugins/org.eclipse.emf.mwe.core/build.properties b/plugins/org.eclipse.emf.mwe.core/build.properties
new file mode 100644
index 0000000..29e32b3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/build.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# committers of openArchitectureWare - initial API and implementation
+###############################################################################
+source.. = src/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties
diff --git a/plugins/org.eclipse.emf.mwe.core/plugin.properties b/plugins/org.eclipse.emf.mwe.core/plugin.properties
new file mode 100644
index 0000000..5f717e8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2000, 2006 openArchitectureWare commiters and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# openArchitectureWare commiters - initial API and implementation
+###############################################################################
+pluginName=openArchitectureWare core workflow
+providerName=openArchitectureWare.org
diff --git a/plugins/org.eclipse.emf.mwe.core/src/log4j.properties b/plugins/org.eclipse.emf.mwe.core/src/log4j.properties
new file mode 100644
index 0000000..b650528
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/log4j.properties
@@ -0,0 +1,29 @@
+###############################################################################
+# Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# committers of openArchitectureWare - initial API and implementation
+###############################################################################
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=INFO, A1
+#, FILE
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %-18C{1} - %m%n
+
+# file appender
+#log4j.appender.FILE=org.apache.log4j.FileAppender
+#log4j.appender.FILE.File=src/workflow.oaw.log
+#log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+#log4j.appender.FILE.layout.ConversionPattern=%-5c ///// %-5p ///// - %m%n
+
+# suppress jalopy logging
+log4j.logger.de.hunsicker=ERROR \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ConfigurationException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ConfigurationException.java
new file mode 100644
index 0000000..53ea777
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ConfigurationException.java
@@ -0,0 +1,58 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core;
+
+/**
+ * Thrown if the workflow configuration is invalid.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class ConfigurationException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 734514205644504349L;
+
+ /**
+ *
+ */
+ public ConfigurationException() {
+ super();
+ }
+
+ /**
+ * @param message
+ */
+ public ConfigurationException(final String message) {
+ super(message);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public ConfigurationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @param cause
+ */
+ public ConfigurationException(final Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponent.java
new file mode 100644
index 0000000..09ef025
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponent.java
@@ -0,0 +1,75 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core;
+
+import org.eclipse.emf.mwe.core.container.CompositeComponent;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+/**
+ * WorkflowComponents are components that can be executed by the
+ * openArchitectureWare Workflow Engine.
+ * <p>
+ * The Workflow Engine will call the
+ * {@link #invoke(WorkflowContext, ProgressMonitor)} method at the appropriate
+ * time to execute the component's service.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+ */
+public interface WorkflowComponent {
+
+ /**
+ * @param ctx
+ * current workflow context
+ * @param monitor
+ * implementors should provide some feedback about the progress
+ * using this monitor
+ * @param issues
+ */
+ public void invoke(WorkflowContext ctx, ProgressMonitor monitor, Issues issues);
+
+ /**
+ * Is called by the container after configuration so the component can
+ * validate the configuration before invocation.
+ *
+ * @param issues -
+ * implementors should report configuration issues to this.
+ */
+ public void checkConfiguration(Issues issues);
+
+ /**
+ * returns the containing component, if there is one
+ * @return
+ */
+ public CompositeComponent getContainer();
+
+ /**
+ * set the containing component
+ * @return
+ */
+ public void setContainer( CompositeComponent container );
+
+ /**
+ * set the location in the source file that invokes the current component.
+ */
+ public void setLocation( Location location);
+
+ /**
+ * return the location
+ * @return the location
+ */
+ public Location getLocation();
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponentWithID.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponentWithID.java
new file mode 100644
index 0000000..1fe0faa
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowComponentWithID.java
@@ -0,0 +1,31 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Markus Voelter - initial
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core;
+
+/**
+ * This is a workflow component that has an ID, so that it can be output in the
+ * logger.
+ *
+ * @author Markus Voelter
+ */
+public interface WorkflowComponentWithID extends WorkflowComponent {
+
+ public void setId(String id);
+
+ public String getId();
+
+ public String getLogMessage();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowContext.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowContext.java
new file mode 100644
index 0000000..2351146
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowContext.java
@@ -0,0 +1,51 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core;
+
+/**
+ * A WorkflowContext is a container for models and other objects.
+ *
+ * @author Sven Efftige
+
+ */
+public interface WorkflowContext {
+ /** Identifier of the default slot. */
+ public final static String DEFAULT_SLOT = "default";
+
+ /**
+ * returns the object of the given slot name.
+ *
+ * @param slotName
+ * The slot's name.
+ * @return The object associated to the specified slot or <tt>null</tt> if
+ * no such slot exists.
+ */
+ Object get(String slotName);
+
+ /**
+ * Sets the passed Model the specified slot. Removes the model currently set
+ * to the specified slot.
+ *
+ * @param slotName
+ * The slot's name.
+ * @param value
+ * object to store in the slot (set <code>null</code> to remove
+ * the slot)
+ */
+ void set(String slotName, Object value);
+
+ public String[] getSlotNames();
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowInterruptedException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowInterruptedException.java
new file mode 100644
index 0000000..140958b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowInterruptedException.java
@@ -0,0 +1,32 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core;
+
+public class WorkflowInterruptedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7995016626229631046L;
+
+ public WorkflowInterruptedException() {
+ super();
+ }
+
+ public WorkflowInterruptedException(final String message) {
+ super(message);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowRunner.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowRunner.java
new file mode 100644
index 0000000..67ab8f3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/WorkflowRunner.java
@@ -0,0 +1,404 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.Manifest;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.PosixParser;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.issues.IssuesImpl;
+import org.eclipse.emf.mwe.core.monitor.NullProgressMonitor;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+import org.eclipse.emf.mwe.internal.core.Workflow;
+import org.eclipse.emf.mwe.internal.core.WorkflowContextDefaultImpl;
+import org.eclipse.emf.mwe.internal.core.ast.util.WorkflowFactory;
+
+/**
+ * Main class to run a workflow.
+ * <p>
+ * Arguments:
+ * <ul>
+ * <li>Workflow configuration filename.
+ * <li>an optional ProgressMonitor
+ * <li>optional runtime properties that override those in workflow files
+ * </ul>
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+ * @author Clemens Kadura (zAJKa) - adapted for debugger handling (since 4.2)
+ *
+ */
+public class WorkflowRunner {
+ private static final String PARAM = "p";
+
+ private static final String MONITOR = "m";
+
+ private static final String ANT = "a";
+
+ private WorkflowContextDefaultImpl wfContext;
+
+ private ProgressMonitor monitor;
+
+ private static final Log logger = LogFactory.getLog(WorkflowRunner.class);
+
+ private Map<String, String> params;
+
+ private Workflow workflow;
+
+ /**
+ * Starts a workflow.
+ *
+ * @param args
+ * Program arguments. See class documentation.
+ */
+ @SuppressWarnings("static-access")
+ public static void main(final String[] args) {
+
+ // // only for test: to be able to connect remote java debugger right
+ // from the beginning
+ // // VM args for remote debug: -Xdebug -Xnoagent
+ // // -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888
+ // try {
+ // Thread.sleep(5000);
+ // } catch (InterruptedException e) {
+ // e.printStackTrace();
+ // }
+ // System.out.println("starting");
+
+ final Options options = new Options();
+ options
+ .addOption(OptionBuilder
+ .hasArgs()
+ .withArgName("className,moreArgs")
+ .withDescription(
+ "the name of a class that implements ProgressMonitor. More arguments can be appended that will be injected to the monitor,"
+ + " if it has a init(String[] args) method.")
+ .withLongOpt("monitorClass").withValueSeparator(',')
+ .create(MONITOR));
+ options.addOption(OptionBuilder.withLongOpt("ant").withDescription(
+ "must be set when using in Ant context").create(ANT));
+ final Option paramOption = OptionBuilder
+ .withArgName("key=value")
+ .withDescription(
+ "external property that is handled as workflow property")
+ .hasArg().create(PARAM);
+ paramOption.setLongOpt("param");
+ options.addOption(paramOption);
+
+ // create the parser
+ final CommandLineParser parser = new PosixParser();
+ CommandLine line = null;
+ try {
+ line = parser.parse(options, args);
+ } catch (final ParseException exp) {
+ System.err.println("Parsing arguments failed. Reason: "
+ + exp.getMessage());
+ wrongCall(options);
+ return;
+ }
+ if (line.getArgs().length != 1) {
+ wrongCall(options);
+ } else {
+ ProgressMonitor monitor = null;
+
+ String[] monitorOptValues = line.getOptionValues(MONITOR);
+ if (monitorOptValues != null) {
+ try {
+ final Class<?> clazz = ResourceLoaderFactory
+ .createResourceLoader().loadClass(
+ monitorOptValues[0]);
+ if (clazz == null)
+ throw new ClassNotFoundException("Didn't find class "
+ + monitorOptValues[0]);
+ monitor = (ProgressMonitor) clazz.newInstance();
+ Method method = monitor.getClass().getMethod("init",
+ new Class[] { String[].class });
+ if (method != null)
+ method.invoke(monitor,
+ new Object[] { monitorOptValues });
+ } catch (final Exception e) {
+ logger.error(e.getMessage(), e);
+ if (line.hasOption(ANT))
+ System.exit(1);
+ return;
+ }
+ }
+
+ final Map<String, String> params = resolveParams(line
+ .getOptionValues(PARAM));
+ String wfFile = line.getArgs()[0];
+
+ // normalize wfFile name so that it can be found in the class path
+ // (necessary for debugger source lookup)
+ URL wfUrl;
+ int index = 0;
+ do {
+ wfUrl = ResourceLoaderFactory.createResourceLoader()
+ .getResource(wfFile);
+ if (wfUrl == null) {
+ index = wfFile.indexOf('/');
+ if (index >= 0)
+ wfFile = wfFile.substring(index + 1);
+ }
+ } while (wfUrl == null && index >= 0);
+
+ WorkflowRunner runner = new WorkflowRunner();
+
+ if (wfUrl == null) {
+ runner.logger.error("can't find the workflow file '"
+ + line.getArgs()[0] + "' in the current class path");
+ if (line.hasOption(ANT))
+ System.exit(1);
+ return;
+ }
+
+ boolean success = runner.run(wfFile, monitor, params, null);
+ if (!success && line.hasOption(ANT)) {
+ System.exit(1);
+ }
+ }
+ }
+
+ /**
+ * Convert type line arguments into a hashmap. Each parameter is expected in
+ * format -pkey=value
+ *
+ * @param args
+ * Program arguments
+ * @return A map containing all identified parameters
+ */
+ private static Map<String, String> resolveParams(final String[] args) {
+ final Map<String, String> params = new HashMap<String, String>();
+ if (args == null)
+ return params;
+ for (int i = 0; i < args.length; i++) {
+ final String[] string = args[i].split("=");
+ if (string.length != 2)
+ throw new IllegalArgumentException(
+ "wrong param syntax (-pkey=value). was : " + args[i]);
+ params.put(string[0], string[1]);
+ }
+ return params;
+ }
+
+ /**
+ * Print usage information and terminate the program.
+ *
+ * @param options
+ */
+ private static void wrongCall(final Options options) {
+ final HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("java " + WorkflowRunner.class.getName()
+ + " some_workflow_file.mwe [options]\nor\njava "
+ + WorkflowRunner.class.getName()
+ + " some_workflow_file.oaw [options]\n", options);
+ System.exit(0);
+ }
+
+ /**
+ * @param workFlowFile
+ * @param monitor
+ * @param logger
+ * @param params
+ */
+ public boolean run(final String workFlowFile,
+ final ProgressMonitor theMonitor,
+ final Map<String, String> theParams,
+ final Map<String, ?> externalSlotContents) {
+ final boolean configOK = prepare(workFlowFile, theMonitor, theParams);
+ final Issues issues = new IssuesImpl();
+ if (configOK)
+ return executeWorkflow(externalSlotContents, issues);
+ return false;
+ }
+
+ public boolean prepare(final String workFlowFile,
+ final ProgressMonitor theMonitor,
+ final Map<String, String> theParams) {
+ if (workFlowFile == null)
+ throw new NullPointerException("workflowFile is null");
+
+ if (theMonitor == null)
+ monitor = new NullProgressMonitor();
+ else
+ monitor = theMonitor;
+ params = theParams;
+
+ logger
+ .info("--------------------------------------------------------------------------------------");
+ logger.info("EMF Modeling Workflow Engine " + getVersion());
+ logger.info("(c) 2005-2007 openarchitectureware.org and contributors");
+ logger
+ .info("--------------------------------------------------------------------------------------");
+ logger.info("running workflow: " + workFlowFile);
+ logger.info("");
+
+ if (!params.isEmpty()) {
+ logger.debug("Params:" + params.toString());
+ }
+ final Issues issues = new IssuesImpl();
+
+ try {
+ final WorkflowFactory factory = new WorkflowFactory();
+
+ // see Bug#155854: WorkflowFactory will throw an
+ // IllegalArgumentException which indicates
+ // a configuration problem.
+ // Detect this very special case
+ try {
+ workflow = factory.parseInitAndCreate(workFlowFile, params,
+ WorkflowFactory.getDefaultConverter(), issues);
+ } catch (IllegalArgumentException illegalArg) {
+ if (illegalArg.getMessage().startsWith("Couldn't load file")) {
+ throw new ConfigurationException(illegalArg.getMessage());
+ }
+ throw illegalArg;
+ }
+ logIssues(logger, issues);
+ if (issues.hasErrors()) {
+ logger
+ .error("Workflow interrupted because of configuration errors.");
+ return false;
+ }
+ if (workflow != null)
+ workflow.checkConfiguration(issues);
+ logIssues(logger, issues);
+ if (issues.hasErrors()) {
+ logger
+ .error("Workflow interrupted because of configuration errors.");
+ return false;
+ }
+ } catch (final ConfigurationException ex) {
+ logger.fatal(ex.getMessage(), ex);
+ logIssues(logger, issues);
+ return false;
+ }
+
+ return true;
+
+ }
+
+ public boolean executeWorkflow(final Map<?, ?> externalSlotContents,
+ final Issues issues) {
+ try {
+ wfContext = new WorkflowContextDefaultImpl();
+ addExternalSlotContents(externalSlotContents);
+ final long time = System.currentTimeMillis();
+ monitor.started(workflow, wfContext);
+ workflow.invoke(wfContext, monitor, issues);
+ monitor.finished(workflow, wfContext);
+ final long duration = System.currentTimeMillis() - time;
+ logger.info("workflow completed in " + duration + "ms!");
+ if (issues.getErrors().length > 0)
+ return false;
+ return true;
+ } catch (final Exception e) {
+ if (e.getClass().getName().indexOf("Interrupt") > -1)
+ logger.error("Workflow interrupted. Reason: " + e.getMessage());
+ else
+ logger.error(e.getMessage(), e);
+ } finally {
+ logIssues(logger, issues);
+ }
+ return false;
+ }
+
+ private void addExternalSlotContents(final Map<?, ?> slotContents) {
+ if (slotContents == null)
+ return;
+ for (final Iterator<?> iter = slotContents.keySet().iterator(); iter
+ .hasNext();) {
+ final String key = (String) iter.next();
+ wfContext.set(key, slotContents.get(key));
+ }
+ }
+
+ private void logIssues(final Log logger, final Issues issues) {
+ // log any configuration warning messages
+ Diagnostic[] issueArray = issues.getIssues();
+ for (int i = 0; i < issueArray.length; i++) {
+ final Diagnostic issue = issueArray[i];
+ if (issue.getSeverity() == Diagnostic.ERROR) {
+ logger.error(issue.toString());
+ }
+ if (issue.getSeverity() == Diagnostic.WARNING) {
+ logger.warn(issue.toString());
+ }
+ if (issue.getSeverity() == Diagnostic.INFO) {
+ logger.info(issue.toString());
+ }
+ }
+ }
+
+ public WorkflowContext getContext() {
+ return wfContext;
+ }
+
+ /**
+ * Tries to read the exact build version from the Manifest of the
+ * core.workflow plugin. Therefore the Manifest file is located and the
+ * version is read from the attribute 'Bundle-Version'.
+ *
+ * @return The build version string, format "4.1.1, Build 200609291913"
+ * @author Karsten Thoms
+ */
+ private String getVersion() {
+ String version = null;
+
+ // get all META-INF/MANIFEST.MF found in the classpath
+ Enumeration<URL> manifestURLs = null;
+ manifestURLs = ResourceLoaderFactory.createResourceLoader()
+ .getResources("META-INF/MANIFEST.MF");
+
+ while (manifestURLs.hasMoreElements()) {
+ URL url = manifestURLs.nextElement();
+ try {
+ Manifest manifest = new Manifest(url.openStream());
+ // identify the manifest from core.workflow plugin
+ if ("org.eclipse.emf.mwe.core".equals(manifest
+ .getMainAttributes().getValue("Bundle-SymbolicName"))) {
+ // Read bundle version an split it.
+ // Original value : "4.1.1.200609291913"
+ // Resulting value : "4.1.1, Build 200609291913"
+ version = manifest.getMainAttributes().getValue(
+ "Bundle-Version");
+ int lastPoint = version.lastIndexOf('.');
+ version = version.substring(0, lastPoint) + ", Build "
+ + version.substring(lastPoint + 1);
+ return version;
+ }
+ } catch (IOException e) {
+ logger.debug("Failed to read Manifest file: " + url);
+ }
+ }
+ // build version not detected from manifest, fallback
+ // this will only occur in developer's workbench
+ return "Development-Snapshot";
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/Parameter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/Parameter.java
new file mode 100644
index 0000000..24a338a
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/Parameter.java
@@ -0,0 +1,48 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.ant;
+
+/**
+ * Simple bean that holds a name/value pair.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class Parameter {
+ private String name;
+
+ private String value;
+
+ /** Property getter */
+ public String getName() {
+ return name;
+ }
+
+ /** Property setter */
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ /** Property getter */
+ public String getValue() {
+ return value;
+ }
+
+ /** Property setter */
+ public void setValue(final String value) {
+ this.value = value;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/WorkflowAntTask.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/WorkflowAntTask.java
new file mode 100644
index 0000000..724e2b4
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ant/WorkflowAntTask.java
@@ -0,0 +1,94 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.ant;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Java;
+import org.eclipse.emf.mwe.core.WorkflowRunner;
+
+/**
+ * Ant task that runs the openArchitectureWare Workflow Engine.
+ * <p>
+ * This task specializes the <tt>Java</tt> task.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class WorkflowAntTask extends Java {
+ private String file;
+
+ private final List<Parameter> params = new ArrayList<Parameter>();
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFile(final String file) {
+ this.file = file;
+ }
+
+ /**
+ * Executes the {@link org.eclipse.emf.mwe.core.WorkflowRunner}.
+ */
+ @Override
+ public void execute() throws BuildException {
+ for (final Iterator<Parameter> iter = params.iterator(); iter.hasNext();) {
+ final Parameter param = iter.next();
+ if (param != null) {
+ final String paramString = "-p" + param.getName() + "=" + param.getValue();
+ super.createArg().setValue(paramString);
+ log("Adding param: " + paramString);
+ }
+ }
+ log("Adding param: " + getFile());
+ super.createArg().setValue(getFile());
+ log("Adding param: --ant");
+ super.createArg().setValue("--ant");
+ super.setFailonerror(true);
+ super.setClassname(WorkflowRunner.class.getName());
+ try {
+ super.execute();
+ } catch (BuildException ex) {
+ if (ex.getCause() != null) {
+ ex.getCause().printStackTrace();
+ }
+
+ String message = "workflow failed: " + String.valueOf(ex.getMessage());
+ // exceptions do not always have a cause; only append if a cause exists
+ if (ex.getCause() != null) {
+ message += " cause: " + String.valueOf(ex.getCause().getMessage());
+ }
+ throw new BuildException(message, ex);
+ }
+ }
+
+ /**
+ * Creates a parameter. Invoked by ant for each
+ * <tt>&lt;param name="..." value="..."/&gt;</tt> statement in the Ant
+ * file.
+ *
+ * @return New {@link Parameter} instance
+ */
+ public Object createParam() {
+ final Parameter param = new Parameter();
+ params.add(param);
+ return param;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ao/AbstractWorkflowAdvice.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ao/AbstractWorkflowAdvice.java
new file mode 100644
index 0000000..4976d31
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/ao/AbstractWorkflowAdvice.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.ao;
+
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.lib.AbstractWorkflowComponent;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+
+public abstract class AbstractWorkflowAdvice extends AbstractWorkflowComponent {
+
+ private String target;
+
+ public final void invokeInternal(WorkflowContext ctx,
+ ProgressMonitor monitor, Issues issues) {
+ }
+
+ public void checkConfiguration(Issues issues) {
+ }
+
+ public void setAdviceTarget(String adviceTarget) {
+ this.target = adviceTarget;
+ }
+
+ public String getAdviceTarget() {
+ return target;
+ }
+
+ public abstract void weave(WorkflowComponent c, Issues issues);
+
+ protected String buildList(List<String> list) {
+ StringBuilder b = new StringBuilder();
+ boolean firstTime = true;
+ for (String s : list) {
+ if (!firstTime)
+ b.append(", ");
+ b.append(s);
+ firstTime = false;
+ }
+ return b.toString();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/AttributeNotFound.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/AttributeNotFound.java
new file mode 100644
index 0000000..e679aed
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/AttributeNotFound.java
@@ -0,0 +1,14 @@
+package org.eclipse.emf.mwe.core.config;
+
+public class AttributeNotFound extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public AttributeNotFound() {
+ super();
+ }
+
+ public AttributeNotFound(String message) {
+ super(message);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/ConfigurationModel.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/ConfigurationModel.java
new file mode 100644
index 0000000..cbe2656
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/ConfigurationModel.java
@@ -0,0 +1,14 @@
+package org.eclipse.emf.mwe.core.config;
+
+
+public interface ConfigurationModel {
+
+ Object getFeature( String featureName );
+
+ boolean featureExists( String featureName );
+
+ boolean isFeatureSelected(String featureName) throws FeatureNotFound;
+
+ public Object getAttributeValue( String featureName, String attributeName ) throws FeatureNotFound, AttributeNotFound;
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureComponent.java
new file mode 100644
index 0000000..bf1f813
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureComponent.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.config;
+
+import org.eclipse.emf.mwe.core.ConfigurationException;
+import org.eclipse.emf.mwe.core.container.ConditionEvaluationException;
+import org.eclipse.emf.mwe.core.container.ConditionalComponent;
+import org.eclipse.emf.mwe.core.issues.Issues;
+
+public class FeatureComponent extends ConditionalComponent {
+
+ public FeatureComponent() {
+ super("feature");
+ }
+
+ private String isSelected = null;
+ private String isNotSelected = null;
+
+ public void setIsSelected( String name ) {
+ this.isSelected = name;
+ }
+
+ public void setIsNotSelected( String name ) {
+ this.isNotSelected = name;
+ }
+
+ @Override
+ public void checkConfiguration(Issues issues) throws ConfigurationException {
+ super.checkConfiguration(issues);
+ if ( isSelected == null && isNotSelected == null ) {
+ issues.addError(this, "you have to specify eithre an exists or notExits.");
+ }
+ }
+
+ public boolean evaluate() {
+ ConfigurationModel configuration = GlobalConfigurationHolder.getConfiguration();
+ if ( configuration == null ) throw new ConditionEvaluationException("no configuration model specified.");
+ if ( isSelected != null && !configuration.featureExists(isSelected) ) throw new ConditionEvaluationException("the feature '"+isSelected+"' is not defined in the configuration model.");
+ if ( isNotSelected != null && !configuration.featureExists(isNotSelected) ) throw new ConditionEvaluationException("the feature '"+isNotSelected+"' is not defined in the configuration model.");
+ try {
+ if ( isSelected != null && isNotSelected == null ) return configuration.isFeatureSelected(isSelected);
+ if ( isSelected == null && isNotSelected != null ) return !configuration.isFeatureSelected(isNotSelected);
+ if ( isSelected != null && isNotSelected != null ) return configuration.isFeatureSelected(isSelected) && !configuration.isFeatureSelected(isNotSelected);
+ } catch ( FeatureNotFound cannotHappen ) {
+ // this has been handled before in the checks above.
+ throw new ConditionEvaluationException("exception: "+cannotHappen.getMessage());
+ }
+ return false;
+ }
+
+ public String getLogMessage() {
+ try {
+ return "feature ( exists "+isSelected+" ): "+evaluate();
+ } catch ( ConditionEvaluationException ex ) {
+ return "feature ( exists "+isSelected+" ): cannot be evaluated; "+ex.getMessage();
+ }
+ }
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureNotFound.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureNotFound.java
new file mode 100644
index 0000000..1f72b53
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/FeatureNotFound.java
@@ -0,0 +1,14 @@
+package org.eclipse.emf.mwe.core.config;
+
+public class FeatureNotFound extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public FeatureNotFound() {
+ super();
+ }
+
+ public FeatureNotFound(String message) {
+ super(message);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/GlobalConfigurationHolder.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/GlobalConfigurationHolder.java
new file mode 100644
index 0000000..85475e3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/config/GlobalConfigurationHolder.java
@@ -0,0 +1,24 @@
+package org.eclipse.emf.mwe.core.config;
+
+import org.eclipse.emf.mwe.core.issues.Issues;
+
+public class GlobalConfigurationHolder {
+
+ private static ConfigurationModel configModel = null;
+
+ public static void setConfigurationModel( ConfigurationModel cm, Issues issues ) {
+ if ( configModel != null ) {
+ if ( !configModel.equals(cm)) {
+ issues.addError("configuration model already set!");
+ }
+ } else {
+ configModel = cm;
+ }
+ }
+
+ public static ConfigurationModel getConfiguration() {
+ return configModel;
+ }
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/CompositeComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/CompositeComponent.java
new file mode 100644
index 0000000..2b56f0b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/CompositeComponent.java
@@ -0,0 +1,281 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.container;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.ConfigurationException;
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.core.WorkflowComponentWithID;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.ao.AbstractWorkflowAdvice;
+import org.eclipse.emf.mwe.core.config.FeatureComponent;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.internal.core.Workflow;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.util.ComponentPrinter;
+
+/**
+ * A composite <tt>WorkflowComponent</tt>.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+ *
+ */
+public class CompositeComponent implements WorkflowComponentWithID {
+ protected static final Log log = LogFactory.getLog(CompositeComponent.class);
+
+ private String name;
+
+ private String resource;
+
+ private Location location;
+
+ private Location ownLocation;
+
+ private CompositeComponent container;
+
+ public CompositeComponent(final String name) {
+ this.name = name;
+ }
+
+ /** All components aggregated by this composite */
+ protected List<WorkflowComponent> components = new ArrayList<WorkflowComponent>();
+
+ private String id;
+
+ public List<WorkflowComponent> getComponents() {
+ return components;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getLogMessage() {
+ return "CompositeComponent " + (id != null ? id : "");
+ }
+
+ /**
+ * Dispatches the invocation to all aggregated components.
+ */
+ public void invoke(final WorkflowContext ctx,
+ final ProgressMonitor monitor, final Issues issues) {
+ internalInvoke(ctx, monitor, issues);
+ }
+
+ private void internalInvoke(final WorkflowContext model,
+ final ProgressMonitor monitor, final Issues issues) {
+ for (final Iterator<WorkflowComponent> iter = components.iterator(); iter
+ .hasNext();) {
+ final WorkflowComponent comp = iter.next();
+ if ((!(comp instanceof AbstractWorkflowAdvice))) {
+ comp.setContainer(this);
+ if (monitor != null)
+ monitor.preTask(comp, model);
+ log.info(ComponentPrinter.getString(comp));
+ comp.invoke(model, monitor, issues);
+ if (monitor != null)
+ monitor.postTask(comp, model);
+ }
+ }
+ }
+
+ public void checkConfiguration(final Issues issues)
+ throws ConfigurationException {
+ for (final Iterator<WorkflowComponent> iter = components.iterator(); iter
+ .hasNext();) {
+ final WorkflowComponent comp = iter.next();
+ if (comp instanceof AbstractWorkflowAdvice) {
+ AbstractWorkflowAdvice advice = (AbstractWorkflowAdvice) comp;
+ String adviceTargetID = advice.getAdviceTarget();
+ if (adviceTargetID == null) {
+ issues.addError(advice, "No 'adviceTarget' given.");
+ continue;
+ }
+ // log.info("Weaving Advice: " +
+ // ComponentPrinter.getString(comp));
+ Collection<WorkflowComponent> targetComponents = findComponentByID(adviceTargetID);
+ if (targetComponents.size() == 0) {
+ issues.addWarning(advice, "No component with ID '"
+ + adviceTargetID + "' found.");
+ }
+ if (targetComponents.size() > 1) {
+ issues.addWarning(advice,
+ "More than on component with ID '" + adviceTargetID
+ + "' found.");
+ }
+ if (needsToWeave(comp, issues)) {
+ for (WorkflowComponent c : targetComponents) {
+ ((AbstractWorkflowAdvice) comp).weave(c, issues);
+ }
+ }
+ }
+ }
+ for (final Iterator<WorkflowComponent> iter = components.iterator(); iter
+ .hasNext();) {
+ final WorkflowComponent comp = iter.next();
+ if ((!(comp instanceof AbstractWorkflowAdvice))) {
+ log.debug("Checking configuration of: "
+ + ComponentPrinter.getString(comp));
+ comp.checkConfiguration(issues);
+ }
+ }
+ }
+
+ private boolean needsToWeave(WorkflowComponent comp, Issues issues) {
+ try {
+ WorkflowComponent current = comp;
+ while (current != null) {
+ if (current instanceof WorkflowConditional) {
+ WorkflowConditional cond = (WorkflowConditional) current;
+ if (!cond.evaluate())
+ return false;
+ }
+ current = current.getContainer();
+ }
+ return true;
+ } catch (ConditionEvaluationException ex) {
+ issues.addError(this, ex.getMessage());
+ return false;
+ }
+ }
+
+ private Collection<WorkflowComponent> findComponentByID(
+ String adviceTargetID) {
+ List<WorkflowComponent> hits = new ArrayList<WorkflowComponent>();
+ WorkflowComponent c = this;
+ while (c.getContainer() != null)
+ c = c.getContainer();
+ ((CompositeComponent) c).resolveComponentByID(adviceTargetID, hits);
+ return hits;
+ }
+
+ private void resolveComponentByID(String adviceTargetID,
+ List<WorkflowComponent> hits) {
+ for (WorkflowComponent component : components) {
+ if (component instanceof WorkflowComponentWithID) {
+ if (adviceTargetID.equals(((WorkflowComponentWithID) component)
+ .getId()))
+ hits.add(component);
+ }
+ }
+ for (WorkflowComponent component : components) {
+ if (component instanceof CompositeComponent) {
+ ((CompositeComponent) component).resolveComponentByID(
+ adviceTargetID, hits);
+ }
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ // the file name of this workflow
+ public String getResource() {
+ return resource;
+ }
+
+ public void setResource(final String resource) {
+ this.resource = resource;
+ }
+
+ // the location of the entry in the parent workflow file
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(final Location location) {
+ this.location = location;
+ }
+
+ // the location of the start and closing tags in the actual workflow file
+ public Location getOwnLocation() {
+ return ownLocation;
+ }
+
+ // locations are set from VisitorCreator by reflection
+ public void setOwnLocation(Location endLocation) {
+ this.ownLocation = endLocation;
+ }
+
+ /**
+ * Sets the aggregated components of this composite.
+ *
+ * @param components
+ * Components to aggregate.
+ */
+ public void addComponent(final WorkflowComponent component) {
+ components.add(component);
+ component.setContainer(this);
+ }
+
+ /**
+ * Sets the aggregated components of this composite.
+ *
+ * @param components
+ * Components to aggregate.
+ */
+ public void addCartridge(final Workflow cartridge) {
+ components.add(cartridge);
+ cartridge.setContainer(this);
+ }
+
+ /**
+ * adds a conditionalcompositecomponent to the list of components
+ *
+ * @param comp
+ */
+ public void addIf(final IfComponent comp) {
+ addComponent(comp);
+ }
+
+ /**
+ * adds a feature components to the list of components
+ *
+ * @param comp
+ */
+ public void addFeature(final FeatureComponent comp) {
+ addComponent(comp);
+ }
+
+ public CompositeComponent getContainer() {
+ return container;
+ }
+
+ public void setContainer(CompositeComponent container) {
+ this.container = container;
+ }
+
+ public void put(@SuppressWarnings("unused")
+ String name, WorkflowComponent comp) {
+ addComponent(comp);
+ }
+
+ public void addBean(final Object obj) {
+ // noop
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionEvaluationException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionEvaluationException.java
new file mode 100644
index 0000000..3dd244a
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionEvaluationException.java
@@ -0,0 +1,14 @@
+package org.eclipse.emf.mwe.core.container;
+
+@SuppressWarnings("serial")
+public class ConditionEvaluationException extends RuntimeException {
+
+ public ConditionEvaluationException() {
+ super();
+ }
+
+ public ConditionEvaluationException( String message ) {
+ super( message );
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionalComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionalComponent.java
new file mode 100644
index 0000000..5d3dc87
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/ConditionalComponent.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.container;
+
+import java.util.Iterator;
+
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.WorkflowInterruptedException;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.internal.core.util.ComponentPrinter;
+
+public abstract class ConditionalComponent extends CompositeComponent implements WorkflowConditional {
+
+ private WorkflowComponent elseComp;
+
+ public ConditionalComponent( String name ) {
+ super(name);
+ }
+
+ public void setElse(final CompositeComponent comp) {
+ elseComp = comp;
+ }
+
+ /**
+ * Dispatches the invocation to all aggregated components.
+ */
+ @Override
+ public void invoke(final WorkflowContext ctx, final ProgressMonitor monitor, final Issues issues) {
+ internalInvoke(ctx, monitor, issues);
+ }
+
+ private void internalInvoke(final WorkflowContext model, final ProgressMonitor monitor, final Issues issues) {
+ try {
+ if (evaluate()) {
+ for (final Iterator<WorkflowComponent> iter = components.iterator(); iter.hasNext();) {
+ final WorkflowComponent comp = iter.next();
+ try {
+ log.info(ComponentPrinter.getString(comp));
+ } catch (final WorkflowInterruptedException wfi) {
+ throw wfi;
+ } catch (final Throwable t) {
+ issues.addError(comp, "Error during execution: " + t.getMessage());
+ log.error("Exception occured: ", t);
+ }
+ comp.invoke(model, monitor, issues);
+ }
+ } else if (elseComp != null) {
+ elseComp.invoke(model, monitor, issues);
+ }
+ } catch ( ConditionEvaluationException ex ) {
+ issues.addError(this, "cannot evaluate condition: "+ex.getMessage() );
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/IfComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/IfComponent.java
new file mode 100644
index 0000000..06ec3a6
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/IfComponent.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.container;
+
+
+public class IfComponent extends ConditionalComponent {
+
+ public IfComponent() {
+ super("if");
+ }
+
+ private String condition = null;
+
+ public void setCond(final String condition) {
+ this.condition = condition;
+ }
+
+ public boolean evaluate() {
+ return Boolean.valueOf(condition).booleanValue();
+ }
+
+ public String getLogMessage() {
+ return "if ( "+condition+" ): "+evaluate();
+ }
+
+
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/WorkflowConditional.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/WorkflowConditional.java
new file mode 100644
index 0000000..15a06d0
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/container/WorkflowConditional.java
@@ -0,0 +1,8 @@
+package org.eclipse.emf.mwe.core.container;
+
+
+public interface WorkflowConditional {
+
+ public boolean evaluate();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/CustomizationException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/CustomizationException.java
new file mode 100644
index 0000000..df726b0
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/CustomizationException.java
@@ -0,0 +1,14 @@
+package org.eclipse.emf.mwe.core.customizer;
+
+@SuppressWarnings("serial")
+public class CustomizationException extends RuntimeException {
+
+ public CustomizationException() {
+ super();
+ }
+
+ public CustomizationException( String message ) {
+ super(message);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/WorkflowCustomization.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/WorkflowCustomization.java
new file mode 100644
index 0000000..b0a6848
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/customizer/WorkflowCustomization.java
@@ -0,0 +1,32 @@
+package org.eclipse.emf.mwe.core.customizer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class WorkflowCustomization {
+
+ private static Map<String,Class<?>> keywordmapping = new HashMap<String,Class<?>>();
+
+ private static final Log logger = LogFactory.getLog(WorkflowCustomization.class);
+
+ public static void registerKeywordMapping( String keyword, Class<?> componentClass ) {
+ keywordmapping .put( keyword, componentClass );
+ }
+
+ public static void registerKeywordMapping( String keyword, String componentClassName ) {
+ try {
+ keywordmapping .put( keyword, Class.forName(componentClassName) );
+ } catch (ClassNotFoundException e) {
+ logger.warn("Cannot resolve keyword class "+componentClassName);
+ }
+ }
+
+ public static Class<?> getKeywordMapping( String keyword ) {
+ return keywordmapping.get(keyword);
+ }
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/model/SyntaxElement.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/model/SyntaxElement.java
new file mode 100644
index 0000000..25dc612
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/model/SyntaxElement.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.debug.model;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Transfer object class for syntax element description in a normalized form.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class SyntaxElement {
+
+ public String resource = "";
+
+ public int start;
+
+ public int end;
+
+ public int line;
+
+ public int frameId;
+
+ public String containerName = "";
+
+ public String elementName = "";
+
+ public String type = "";
+
+ public boolean visible = true;
+
+ // -------------------------------------------------------------------------
+
+ public void readContent(DataInputStream in) throws IOException {
+ resource = in.readUTF();
+ start = in.readInt();
+ end = in.readInt();
+ line = in.readInt();
+ frameId = in.readInt();
+ containerName = in.readUTF();
+ elementName = in.readUTF();
+ type = in.readUTF();
+ visible = in.readBoolean();
+ }
+
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeUTF(resource);
+ out.writeInt(start);
+ out.writeInt(end);
+ out.writeInt(line);
+ out.writeInt(frameId);
+ out.writeUTF(containerName);
+ out.writeUTF(elementName);
+ out.writeUTF(type);
+ out.writeBoolean(visible);
+ }
+
+ public boolean equalsBP(SyntaxElement se){
+ return resource.equals(se.resource) && line == se.line && start == se.start;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/processing/ElementAdapter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/processing/ElementAdapter.java
new file mode 100644
index 0000000..116d7d7
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/debug/processing/ElementAdapter.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.debug.processing;
+
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.internal.core.debug.model.NameValuePair;
+
+/**
+ * An adapter to the <code>DebugMonitor</code> that handle all element type specific activities on the runtime
+ * side.<br>
+ * That is process specific decisions and syntax element and variable normalisation.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface ElementAdapter {
+
+ /**
+ * returns true, if the implementation handles the element type
+ *
+ * @param element the element that is going to be debugged
+ * @return true, if this class handles the element type
+ */
+ public boolean canHandle(Object element);
+
+ /**
+ * this method is called from the DebugMonitor prior to all other suspension activities (e.g. breakpoint
+ * check, subroutine level check)<br>
+ * this provides the opportunity to handle specific elements individually<br>
+ * Normal return value should be true<br>
+ *
+ * @param element the element that is going to be debugged
+ * @return whether or not to suspend the debugger process for the element
+ */
+ public boolean shallHandle(Object element);
+
+ /**
+ * this method is called from the DebugMonitor after all other suspension activities (e.g. breakpoint check,
+ * subroutine level check)<br>
+ * this provides the opportunity for a last call by the adapter.<br>
+ * Implementations can *avoid* suspension, although it would suspend otherwise, if the return value is set to
+ * false here
+ *
+ * @param lastState the consolidated decisions previously asked
+ * @param element the element that is going to be debugged
+ * @param flag one of the values <code>IProcessHandler.PUSH</code> or <code>IProcessHandler.POP</code>
+ * @return whether or not to suspend the debugger process for the element
+ */
+ public boolean shallSuspend(Object element, int flag);
+
+ /**
+ * computes a SyntaxElementTO for a specific element type<br>
+ * the containerName should be the name of the underlying file name<br>
+ * the element name should be the name of the surrounding element (e.g. in Java we highlight the line to be
+ * debugged, but show the surrounding method name in the Launch view)<br>
+ * start, end and line should point to the text that shall be highlighted for the element
+ *
+ * @param element the element that is going to be debugged
+ * @return a SyntaxElementTO that contains the information to be shown in the debugger views in a common
+ * neutral way
+ */
+ public SyntaxElement createElementTO(Object element);
+
+ /**
+ * returns whether the element has a body and debugger shall stop again at the end of the execution of that
+ * element
+ *
+ * @param element the element that is debugged currently
+ * @return whether the element has a body
+ */
+ public boolean isSurroundingElement(Object element);
+
+ /**
+ * computes a SyntaxElementTO for a surrounding element representing the end position to be highlighted before
+ * returning<br>
+ * the containerName should be the name of the file that holds the element<br>
+ * the element name should be a description of the end element<br>
+ * start, end and line should point to the end text to be highlighted
+ *
+ * @param element the element that is going to be debugged
+ * @return a SyntaxElementTO that contains the information to be shown in the debugger views in a common
+ * neutral way
+ */
+ public SyntaxElement createEndElementTO(Object element);
+
+ /**
+ * find the element that corresponds to the given syntax element information
+ *
+ * @param se the syntax element transfer object
+ * @param flag
+ * @param actual
+ * @return the corresponding element
+ */
+ public Object findElement(SyntaxElement se, Object actual, int flag);
+
+ /**
+ * collect all available variables for a given element. With this method only the variables themselfs are
+ * collected, not their members.<br>
+ * Implementations must consider that <code>element</code>can be both a syntax element or an arbitrary java
+ * element to collect the member variables from!!
+ *
+ * @param element the current element
+ * @return a name/value list that contains the variables
+ */
+ public List<NameValuePair> getVariables(Object element);
+
+ /**
+ * compute the string representation of the element ready to display in the variables detail view.
+ *
+ * @param element the element to be considered
+ * @return the String representation of this element
+ */
+ public String getVariableDetailRep(Object element);
+
+ /**
+ * compute a shorter string representation of the element ready to display in the variables view.
+ *
+ * @param element the element to be considered
+ * @return a string representation of this element
+ */
+ public String getVariableSimpleRep(Object element);
+
+ /**
+ * check if the variable representation of this element shall show members
+ *
+ * @param element the element to be considered
+ * @return the decision
+ */
+ public boolean checkVariableHasMembers(Object element);
+
+ /**
+ * set the current execution context<br>
+ * the context should be cached and can be used to collect information about elements
+ *
+ * @param context the context
+ */
+ public void setContext(Object context);
+
+ public Object getContext();
+
+ /**
+ * a unique type must be provided for each implementation
+ *
+ * @return the adapterType
+ */
+ public String getAdapterType();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/Issues.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/Issues.java
new file mode 100644
index 0000000..95db473
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/Issues.java
@@ -0,0 +1,176 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.issues;
+
+import java.util.List;
+
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+
+/**
+ * Collects information about workflow configuration.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+ * @author Bernd Kolb
+ *
+ */
+public interface Issues {
+
+ /**
+ * Adds a {@link Diagnostic}. Only {@link Diagnostic} with a severity of
+ * {@link Diagnostic#INFO}, {@link Diagnostic#WARNING} and
+ * {@link Diagnostic#ERROR} are allowed
+ *
+ * @param issue
+ */
+ public void add(Diagnostic issue);
+
+ /**
+ * Adds a info message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addInfo(String msg);
+
+ /**
+ * Adds a info message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addInfo(String msg, Object obj);
+
+ /**
+ * Adds a info message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addInfo(WorkflowComponent ctx, String msg, Object obj, Throwable t, List<Object> additionalData);
+
+ /**
+ * Adds a info message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addInfo(WorkflowComponent ctx, String msg);
+
+ /**
+ * @return
+ */
+ public boolean hasInfos();
+
+ /**
+ * @return all infos in this container
+ */
+ public Diagnostic[] getInfos();
+
+ /**
+ * Adds a warn message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addWarning(String msg);
+
+ /**
+ * Adds a warn message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addWarning(String msg, Object obj);
+
+ /**
+ * Adds a warn message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addWarning(WorkflowComponent ctx, String msg, Object obj, Throwable t, List<Object> additionalData);
+
+ /**
+ * Adds a warn message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addWarning(WorkflowComponent ctx, String msg);
+
+ /**
+ * @return
+ */
+ public boolean hasWarnings();
+
+ /**
+ * @return all warning in this container
+ */
+ public Diagnostic[] getWarnings();
+
+ /**
+ * Adds an error message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addError(String msg);
+
+ /**
+ * Adds an error message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addError(String msg, Object obj);
+
+ /**
+ * Adds an error message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addError(WorkflowComponent ctx, String msg, Object obj, Throwable t, List<Object> additionalData);
+
+ /**
+ * Adds an error message.
+ *
+ * @param msg
+ * Message text.
+ */
+ public void addError(WorkflowComponent ctx, String msg);
+
+ /**
+ * @return all errors in this container
+ */
+ public Diagnostic[] getErrors();
+
+ /**
+ * @return
+ */
+ public boolean hasErrors();
+
+ /**
+ * removes all warnings and errors
+ */
+ public void clear();
+
+ /**
+ * @return all {@link Diagnostic}s reported here
+ */
+ public Diagnostic[] getIssues();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/IssuesImpl.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/IssuesImpl.java
new file mode 100644
index 0000000..55c4df7
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/IssuesImpl.java
@@ -0,0 +1,187 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.issues;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+
+public class IssuesImpl implements Issues {
+ private final List<Diagnostic> issues = new ArrayList<Diagnostic>();
+
+ public void add(final Diagnostic issue) {
+ issues.add(issue);
+ }
+
+ public void addError(final WorkflowComponent ctx, final String msg,
+ final Object element, Throwable t, List<Object> additionalData) {
+ add(createError(ctx, msg, element, t, additionalData));
+ }
+
+ public void addError(final WorkflowComponent ctx, final String msg) {
+ addError(ctx, msg, null, null, Collections.EMPTY_LIST);
+ }
+
+ public void addError(final String msg, final Object element) {
+ add(createError(msg, element));
+ }
+
+ public void addError(final String msg) {
+ addError(msg, (Object) null);
+ }
+
+ public boolean hasErrors() {
+ return getErrors().length!=0;
+ }
+
+ public Diagnostic[] getErrors() {
+ return filterIssues(Diagnostic.ERROR);
+ }
+
+ public void addWarning(final WorkflowComponent ctx, final String msg) {
+ addWarning(ctx, msg, null, null, Collections.EMPTY_LIST);
+ }
+
+ public void addWarning(final String msg, final Object element) {
+ add(createWarning(msg, element));
+ }
+
+ public void addWarning(final WorkflowComponent ctx, final String msg,
+ final Object element, Throwable t, List<Object> additionalData) {
+ add(createWarning(ctx, msg, element, t, additionalData));
+ }
+
+ public void addWarning(final String msg) {
+ addWarning(msg, null);
+ }
+
+ public Diagnostic[] getWarnings() {
+ return filterIssues(Diagnostic.WARNING);
+ }
+
+ public boolean hasWarnings() {
+ return getWarnings().length!=0;
+ }
+
+ public void addInfo(final WorkflowComponent ctx, final String msg) {
+ addInfo(ctx, msg, null, null, Collections.EMPTY_LIST);
+ }
+
+ public void addInfo(final String msg, final Object element) {
+ add(createInfo(msg, element));
+ }
+
+ public void addInfo(final WorkflowComponent ctx, final String msg,
+ final Object element, Throwable t, List<Object> additionalData) {
+ add(createInfo(ctx, msg, element, t, additionalData));
+ }
+
+ public void addInfo(final String msg) {
+ addInfo(msg, null);
+ }
+
+ public Diagnostic[] getInfos() {
+ return filterIssues(Diagnostic.INFO);
+ }
+
+ public boolean hasInfos() {
+ return getInfos().length!=0;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer buff = new StringBuffer();
+ Diagnostic[] issues = getInfos();
+ for (int i = 0; i < issues.length; i++) {
+ final Diagnostic issue = issues[i];
+ buff.append("\n" + issue.toString());
+ }
+ issues = getWarnings();
+ for (int i = 0; i < issues.length; i++) {
+ final Diagnostic issue = issues[i];
+ buff.append("\n" + issue.toString());
+ }
+ issues = getErrors();
+ for (int i = 0; i < issues.length; i++) {
+ final Diagnostic issue = issues[i];
+ buff.append("\n" + issue.toString());
+ }
+ return buff.toString();
+ }
+
+ public void clear() {
+ issues.clear();
+ }
+
+ private static MWEDiagnostic createDiagnostic(int severity,
+ WorkflowComponent ctx, String msg, Object element, Throwable t,
+ List<Object> additionalData) {
+ MWEDiagnostic diagnostic = new MWEDiagnostic(severity, msg, element, t,
+ additionalData, ctx);
+ return diagnostic;
+ }
+
+ private static MWEDiagnostic createInfo(WorkflowComponent ctx, String msg,
+ Object element, Throwable t, List<Object> additionalData) {
+ MWEDiagnostic diagnostic = createDiagnostic(Diagnostic.INFO, ctx, msg,
+ element, t, additionalData);
+ return diagnostic;
+ }
+
+ private static MWEDiagnostic createInfo(String msg, Object element) {
+ return createWarning(null, msg, element, null, Collections.EMPTY_LIST);
+ }
+
+ private static MWEDiagnostic createWarning(WorkflowComponent ctx,
+ String msg, Object element, Throwable t, List<Object> additionalData) {
+ MWEDiagnostic diagnostic = createDiagnostic(Diagnostic.WARNING, ctx,
+ msg, element, t, additionalData);
+ ;
+ return diagnostic;
+ }
+
+ private static MWEDiagnostic createWarning(String msg, Object element) {
+ return createWarning(null, msg, element, null, Collections.EMPTY_LIST);
+ }
+
+ private static MWEDiagnostic createError(WorkflowComponent ctx, String msg,
+ Object element, Throwable t, List<Object> additionalData) {
+ MWEDiagnostic diagnostic = createDiagnostic(Diagnostic.ERROR, ctx, msg,
+ element, t, additionalData);
+ return diagnostic;
+ }
+
+ private static MWEDiagnostic createError(String msg, Object element) {
+ return createWarning(null, msg, element, null, Collections.EMPTY_LIST);
+ }
+
+ private Diagnostic[] filterIssues(int severity) {
+ List<Diagnostic>result = new ArrayList<Diagnostic>();
+ for (Diagnostic diagnostic : issues) {
+ if ( diagnostic.getSeverity()==severity){
+ result.add(diagnostic);
+ }
+ }
+ return result.toArray(new Diagnostic[result.size()]);
+ }
+
+ public Diagnostic[] getIssues() {
+ return issues.toArray(new Diagnostic[issues.size()]);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/MWEDiagnostic.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/MWEDiagnostic.java
new file mode 100644
index 0000000..cf44a4c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/issues/MWEDiagnostic.java
@@ -0,0 +1,255 @@
+package org.eclipse.emf.mwe.core.issues;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.util.BasicDiagnostic;
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.common.util.DiagnosticChain;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.internal.core.util.ComponentPrinter;
+
+public class MWEDiagnostic implements Diagnostic, DiagnosticChain {
+
+ private static final String ID = "org.eclipse.emf.mwe.core";
+
+ /**
+ * The severity.
+ *
+ * @see #getSeverity
+ */
+ protected int severity;
+
+ /**
+ * The message.
+ *
+ * @see #getMessage
+ */
+ protected String message;
+
+ /**
+ * The message.
+ *
+ * @see #getMessage
+ */
+ protected List<Diagnostic> children;
+
+ /**
+ * The data.
+ *
+ * @see #getData
+ */
+ protected List<Object> data = new ArrayList<Object>();
+
+ /**
+ * The source.
+ *
+ * @see #getSource
+ */
+ protected String source = ID;
+
+ /**
+ * The code.
+ *
+ * @see #getCode
+ */
+ protected int code = Diagnostic.OK;
+
+ private final Object element;
+ private final WorkflowComponent ctx;
+
+ private final Throwable throwable;
+
+ public MWEDiagnostic(int severity, String msg, Object element, Throwable t,
+ List<Object> additionalData, WorkflowComponent ctx) {
+ throwable = t;
+ message = msg;
+ setSeverity(severity);
+ this.element = element;
+ this.ctx = ctx;
+ if (getElement() != null) {
+ data.add(element);
+ }
+ if (getException() != null) {
+ data.add(getException());
+ }
+ if (getContext() != null) {
+ data.add(getContext());
+ }
+ if (additionalData != null) {
+ data.addAll(additionalData);
+ }
+ }
+
+ protected void setSeverity(int severity) {
+ this.severity = severity;
+ }
+
+ public int getSeverity() {
+ return severity;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public List<?> getData() {
+ return data;
+ }
+
+ public List<Diagnostic> getChildren() {
+ if (children == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(children);
+ }
+
+ protected void setSource(String source) {
+ this.source = source;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ protected void setCode(int code) {
+ this.code = code;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public void add(Diagnostic diagnostic) {
+ if (children == null) {
+ children = new BasicEList<Diagnostic>();
+ }
+
+ children.add(diagnostic);
+ int childSeverity = diagnostic.getSeverity();
+ if (childSeverity > getSeverity()) {
+ severity = childSeverity;
+ }
+ }
+
+ public void addAll(Diagnostic diagnostic) {
+ for (Diagnostic child : diagnostic.getChildren()) {
+ add(child);
+ }
+ }
+
+ public void merge(Diagnostic diagnostic) {
+ if (diagnostic.getChildren().isEmpty()) {
+ add(diagnostic);
+ } else {
+ addAll(diagnostic);
+ }
+ }
+
+ public int recomputeSeverity() {
+ if (children != null) {
+ severity = OK;
+ for (Diagnostic child : children) {
+ int childSeverity = child instanceof BasicDiagnostic ? ((BasicDiagnostic) child)
+ .recomputeSeverity()
+ : child.getSeverity();
+ if (childSeverity > severity) {
+ severity = childSeverity;
+ }
+ }
+ }
+
+ return severity;
+ }
+
+ public Throwable getException() {
+ return throwable;
+ }
+
+ public Object getElement() {
+ return element;
+ }
+
+ public WorkflowComponent getContext() {
+ return ctx;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+ buff.append("[");
+ switch (severity) {
+ case WARNING: {
+ buff.append("WARNING");
+ break;
+ }
+ case ERROR: {
+ buff.append("ERROR");
+ break;
+ }
+ default:
+ buff.append("INFO");
+ break;
+ }
+ buff.append("]");
+ if (getMessage() != null) {
+ buff.append(": " + getMessage());
+ }
+ buff.append("(Element: ");
+ if (getElement() != null) {
+ buff.append(getElementStringRep());
+ } else {
+ buff.append("-UNKNOWN-");
+ }
+ buff.append("; Reported by: ");
+ if (getContext() != null) {
+ buff.append(ComponentPrinter.getString(getContext()));
+ } else {
+ buff.append("-UNKNOWN-");
+ }
+ buff.append(")");
+ if (getException() != null) {
+ Throwable t = getException();
+ StringWriter stringWriter = new StringWriter();
+ t.printStackTrace(new PrintWriter(stringWriter));
+ buff.append("\n\t " + stringWriter.toString());
+ }
+
+ return buff.toString();
+ }
+
+ private String getElementStringRep() {
+ Object element = getElement();
+ if (element instanceof EObject) {
+ EObject eo = (EObject) element;
+ String name = getEName(eo);
+ if (name == null)
+ return eo.toString();
+ StringBuffer qfn = new StringBuffer();
+ qfn.append(name);
+ while (eo.eContainer() != null) {
+ eo = eo.eContainer();
+ name = getEName(eo);
+ if (name != null) {
+ qfn.insert(0, name + ".");
+ }
+ }
+ return qfn.toString();
+ }
+ return element.toString();
+ }
+
+ private String getEName(EObject eo) {
+ EStructuralFeature f = eo.eClass().getEStructuralFeature("name");
+ if (f == null)
+ return null;
+ return (String) eo.eGet(f);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/AbstractWorkflowComponent.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/AbstractWorkflowComponent.java
new file mode 100644
index 0000000..391dbc5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/AbstractWorkflowComponent.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.lib;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.WorkflowComponentWithID;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.container.CompositeComponent;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+/**
+ * Base class useful for implementing custom WorkflowComponents.
+ *
+ * @author Markus Voelter (impl)
+ * @author Karsten Thoms (doc)
+
+ */
+public abstract class AbstractWorkflowComponent implements WorkflowComponentWithID {
+
+ private static final Log log = LogFactory.getLog(AbstractWorkflowComponent.class);
+
+ /** The component's id */
+ private String componentID;
+
+ private boolean skipOnErrors = false;
+
+ /** Container component */
+ private CompositeComponent container;
+
+ private Location location;
+
+ /**
+ * @return The component's id
+ */
+ public String getId() {
+ return componentID;
+ }
+
+ /**
+ * @param id
+ * The component's id
+ */
+ public void setId(final String id) {
+ componentID = id;
+ }
+
+ public void setSkipOnErrors(final boolean b) {
+ skipOnErrors = b;
+ }
+
+ /**
+ * @return The containing component if any
+ */
+ public CompositeComponent getContainer() {
+ return container;
+ }
+
+ /**
+ * @param container
+ * The containing component
+ */
+ public void setContainer(CompositeComponent container) {
+ this.container = container;
+ }
+
+ public String getLogMessage() {
+ return null;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(final Location location) {
+ this.location = location;
+ }
+
+ public final void invoke(final WorkflowContext ctx, final ProgressMonitor monitor, final Issues issues) {
+ if (skipOnErrors && issues.hasErrors()) {
+ log.info("execution skipped, since there are errors and skipOnErrors is set.");
+ return;
+ }
+ invokeInternal(ctx, monitor, issues);
+ }
+
+ protected abstract void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, Issues issues);
+
+ /**
+ * Utility method that can be used in method <code>checkConfiguration</code>
+ * to check required properties. If <code>configPropertyValue</code> is
+ * <code>null</code> or a blank string then this method will add an error
+ * issue.
+ *
+ * @param configPropertyName
+ * Name of the checked config property.
+ * @param configPropertyValue
+ * The config property value.
+ * @param issues
+ * The Issues instance.
+ */
+ public void checkRequiredConfigProperty(String configPropertyName, Object configPropertyValue, Issues issues) {
+ boolean isError = false;
+ if (configPropertyValue == null) {
+ isError = true;
+ } else if ((configPropertyValue instanceof String) && isBlank(configPropertyValue.toString())) {
+ isError = true;
+ }
+
+ if (isError)
+ issues.addError("'" + configPropertyName + "' not specified.");
+ }
+
+ private boolean isBlank(String string) {
+ if (string == null || string.trim().equals("")) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/WorkflowComponentWithModelSlot.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/WorkflowComponentWithModelSlot.java
new file mode 100644
index 0000000..e49ac0b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/lib/WorkflowComponentWithModelSlot.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.lib;
+
+import org.eclipse.emf.mwe.core.issues.Issues;
+
+public abstract class WorkflowComponentWithModelSlot extends AbstractWorkflowComponent {
+
+ private String modelSlot;
+
+ public void setModelSlot(final String ms) {
+ modelSlot = ms;
+ }
+
+ protected String getModelSlot() {
+ return modelSlot;
+ }
+
+ public void checkConfiguration(final Issues issues) {
+ if (modelSlot == null)
+ issues.addError(this, "modelSlot not specified.");
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/NullProgressMonitor.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/NullProgressMonitor.java
new file mode 100644
index 0000000..e89909e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/NullProgressMonitor.java
@@ -0,0 +1,112 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.monitor;
+
+import org.eclipse.emf.common.util.Diagnostic;
+
+/**
+ * Empty implementation of {@link ProgressMonitor}.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class NullProgressMonitor implements ProgressMonitor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(final String name, final int totalWork) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#done()
+ */
+ public void done() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#internalWorked(double)
+ */
+ public void internalWorked(final double work) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#isCanceled()
+ */
+ public boolean isCanceled() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#setCanceled(boolean)
+ */
+ public void setCanceled(final boolean value) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#setTaskName(java.lang.String)
+ */
+ public void setTaskName(final String name) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#subTask(java.lang.String)
+ */
+ public void subTask(final String name) {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.workflow.monitor.ProgressMonitor#worked(int)
+ */
+ public void worked(final int work) {
+ }
+
+ public void started(Object element, Object context){
+ }
+
+ public void finished(Object element, Object context){
+
+ }
+
+ public void postTask(Object element, Object context) {
+ }
+
+ public void preTask(Object element, Object context) {
+ }
+
+ public void clearBlocked() {
+ }
+
+ public void setBlocked(Diagnostic reason) {
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/ProgressMonitor.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/ProgressMonitor.java
new file mode 100644
index 0000000..c611fe4
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/monitor/ProgressMonitor.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * copied from Eclipse (org.eclipse.core.runtime.IProgressMonitor)
+ * adaptions by Clemens Kadura
+ *******************************************************************************/
+package org.eclipse.emf.mwe.core.monitor;
+
+import org.eclipse.emf.common.util.Monitor;
+
+/**
+ * The <code>IProgressMonitor</code> interface is implemented by objects that
+ * monitor the progress of an activity; the methods in this interface are
+ * invoked by code that performs the activity.
+ * <p>
+ * All activity is broken down into a linear sequence of tasks against which
+ * progress is reported. When a task begins, a <code>beginTask(String, int)
+ * </code>
+ * notification is reported, followed by any number and mixture of progress
+ * reports (<code>worked()</code>) and subtask notifications (<code>subTask(String)</code>).
+ * When the task is eventually completed, a <code>done()</code> notification
+ * is reported. After the <code>done()</code> notification, the progress
+ * monitor cannot be reused; i.e., <code>
+ * beginTask(String, int)</code> cannot
+ * be called again after the call to <code>done()</code>.
+ * </p>
+ * <p>
+ * A request to cancel an operation can be signaled using the
+ * <code>setCanceled</code> method. Operations taking a progress monitor are
+ * expected to poll the monitor (using <code>isCanceled</code>) periodically
+ * and abort at their earliest convenience. Operation can however choose to
+ * ignore cancelation requests.
+ * </p>
+ * <p>
+ * Since notification is synchronous with the activity itself, the listener
+ * should provide a fast and robust implementation. If the handling of
+ * notifications would involve blocking operations, or operations which might
+ * throw uncaught exceptions, the notifications should be queued, and the actual
+ * processing deferred (or perhaps delegated to a separate thread).
+ * </p>
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ */
+public interface ProgressMonitor extends Monitor{
+
+ /**
+ * Notifies that a task will be started. Must be paired together with one <code>postTask()</code> call.
+ *
+ * @param element The element that fired that notification
+ * @param context the context of execution
+ */
+ public void preTask(Object element, Object context);
+
+ /**
+ * Notifies that a task was finished. Must be paired together with one <code>preTask()</code> call.
+ *
+ * @param element The element that fired that notification
+ * @param context the context of execution
+ */
+ public void postTask(Object element, Object context);
+
+ /**
+ * Notifies that overall process was started.
+ *
+ * @param element The element that fired that notification
+ * @param context the context of execution
+ */
+ public void started(Object element, Object context);
+
+ /**
+ * Notifies that overall process was finished.
+ *
+ * @param element The element that fired that notification
+ * @param context the context of execution
+ */
+ public void finished(Object element, Object context);
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoader.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoader.java
new file mode 100644
index 0000000..0846dc5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoader.java
@@ -0,0 +1,47 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.resources;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+
+/**
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public interface ResourceLoader {
+
+ /**
+ *
+ * @param uri
+ * Identifier for a resource
+ * @return InputStream for the specified resource.
+ */
+ public InputStream getResourceAsStream(String uri);
+
+ /**
+ *
+ * @param clazzName
+ * The class name
+ * @return The class instance or null if no such class could be found
+ */
+ public Class<?> loadClass(String clazzName);
+
+ public URL getResource(String uri);
+
+ public Enumeration<URL> getResources(String uri);
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoaderFactory.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoaderFactory.java
new file mode 100644
index 0000000..1b2bfec
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/core/resources/ResourceLoaderFactory.java
@@ -0,0 +1,75 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.core.resources;
+
+import org.eclipse.emf.mwe.internal.core.resources.ResourceLoaderDefaultImpl;
+
+/**
+ * Factory for
+ * {@link org.eclipse.emf.mwe.core.resources.ResourceLoader ResourceLoaders}.
+ * By default this factory creates instances of
+ * {@link org.eclipse.emf.mwe.internal.core.resources.ResourceLoaderDefaultImpl ResourceLoaderDefaultImpl}.
+ * <p>
+ * The factory evaluates the <tt>org.eclipse.emf.mwe.core.resources.ResourceLoader</tt>
+ * system property to get the <tt>ResourceLoader</tt> implementation class
+ * name. Set this property to specify an alternative implementation.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class ResourceLoaderFactory {
+ public final static String PARAM_RESOURCELOADER_CLASS = "org.eclipse.emf.mwe.core.resources.ResourceLoader";
+
+ private static Class<?> resourceLoaderImpl;
+
+ private static final ThreadLocal<ResourceLoader> current = new ThreadLocal<ResourceLoader>();
+
+ public static void setCurrentThreadResourceLoader(final ResourceLoader rl) {
+ current.set(rl);
+ }
+
+ private static void initResourceLoaderClass() {
+ final String name = System.getProperty(PARAM_RESOURCELOADER_CLASS, ResourceLoaderDefaultImpl.class.getName());
+ // enable changing implementations at runtime.
+ // preliminary implemented for the unittest of this class
+ if (resourceLoaderImpl == null || (name != null && !name.equals(resourceLoaderImpl.getName()))) {
+ try {
+ resourceLoaderImpl = Class.forName(name);
+ } catch (final ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Creates an instance of ResourceLoader.
+ *
+ * @return The newly created object
+ * @throws RuntimeException
+ * In any case that an instance could not be created.
+ */
+ public static ResourceLoader createResourceLoader() throws RuntimeException {
+ if (current.get() != null)
+ return current.get();
+ initResourceLoaderClass();
+ try {
+ return (ResourceLoader) resourceLoaderImpl.newInstance();
+ } catch (final InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (final IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/Workflow.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/Workflow.java
new file mode 100644
index 0000000..0f52710
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/Workflow.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core;
+
+import org.eclipse.emf.mwe.core.container.CompositeComponent;
+
+public class Workflow extends CompositeComponent {
+
+ private boolean isAbstract;
+
+ public Workflow() {
+ super("workflow");
+ }
+
+ public void setAbstract( boolean b ) {
+ isAbstract = b;
+ }
+
+ public boolean isAbstract() {
+ return isAbstract;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkflowContextDefaultImpl.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkflowContextDefaultImpl.java
new file mode 100644
index 0000000..75ed3c3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkflowContextDefaultImpl.java
@@ -0,0 +1,56 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.internal.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.emf.mwe.core.WorkflowContext;
+
+/**
+ * Default {@link WorkflowContext} implementation.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class WorkflowContextDefaultImpl implements WorkflowContext {
+
+ private final Map<String, Object> models = new HashMap<String, Object>();
+
+ /**
+ * @see WorkflowContext#get(String)
+ */
+ public Object get(final String modelName) {
+ return models.get(modelName);
+ }
+
+ /**
+ * @see WorkflowContext#set(String, Object)
+ */
+ public void set(final String slotName, final Object model) {
+ if (slotName == null)
+ throw new IllegalArgumentException("slotName must not be null!");
+ if (!slotName.matches("[\\w_]+"))
+ throw new IllegalArgumentException("slotName '" + slotName + "' contains invalid characters!");
+ if (model == null) {
+ models.remove(slotName);
+ }
+ models.put(slotName, model);
+ }
+
+ public String[] getSlotNames() {
+ return models.keySet().toArray(new String[models.keySet().size()]);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkfowComponentHelper.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkfowComponentHelper.java
new file mode 100644
index 0000000..ac711c9
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/WorkfowComponentHelper.java
@@ -0,0 +1,164 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.internal.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+
+public class WorkfowComponentHelper {
+
+ /**
+ * Proves if the filename points to a existent file (not directory!).
+ *
+ * @param filename
+ * Path to a file
+ * @return <tt>true</tt> if the path points to a file, <tt>false</tt> if
+ * the file does not exist or is a directory.
+ */
+ public static boolean isLegalFile(final String filename) {
+ final File f = new File(filename);
+ if (!f.exists())
+ return false;
+ if (f.isDirectory())
+ return false;
+ return true;
+ }
+
+ /**
+ * Proves if the argument points to a existent directory (not file!).
+ *
+ * @param dirname
+ * Path to a directory
+ * @return <tt>true</tt> if the path points to a directory, <tt>false</tt>
+ * if the directory does not exist or is a file.
+ */
+ public static boolean isLegalDir(final String dirname) {
+ final File f = new File(dirname);
+ if (!f.exists())
+ return false;
+ if (f.isFile())
+ return false;
+ return true;
+ }
+
+ /**
+ * Proves if the given string is a valid URL. This method tries to open the
+ * URL to check its validity.
+ *
+ * @param url
+ * An URL as String
+ * @return <tt>true</tt> if the string is a valid URL, otherwise
+ * <tt>false</tt>.
+ */
+ public static boolean isLegalURL(final String url) {
+ if (url == null || url.trim().length() == 0)
+ return false;
+
+ try {
+ final URL u = new URL(url);
+ u.openConnection();
+ return true;
+ } catch (final MalformedURLException e) {
+ return false;
+ } catch (final IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Proves if the given name is a valid resource. This method tries to open a
+ * URL connection to the resource. The resource is located via the Thread
+ * Context ClassLoader.
+ *
+ * @param uri
+ * A resource identifier
+ * @return <tt>true</tt> if the given URI points to a valid resource,
+ * otherwise <tt>false</tt>.
+ */
+ public static boolean isResource(final String uri) {
+ try {
+ final URL u = ResourceLoaderFactory.createResourceLoader().getResource(uri);
+ if (u == null) {
+ return false;
+ }
+ u.openConnection();
+ return true;
+ } catch (final MalformedURLException e) {
+ return false;
+ } catch (final IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Proves if the given name is a valid resource. This method tries to open a
+ * URL connection to the resource. The resource is located as a class
+ * resource.
+ *
+ * @param uri
+ * A resource identifier
+ * @param contextClassName
+ * The class whose resource is tested
+ * @return <tt>true</tt> if the given URI points to a valid resource,
+ * otherwise <tt>false</tt>.
+ */
+ public static boolean isResource(final String uri,
+ final String contextClassName) {
+ if (!isLoadableClass(contextClassName))
+ return false;
+ try {
+ final Class<?> context = Class.forName(contextClassName);
+ final URL u = context.getResource(uri);
+ if (u == null) {
+ return false;
+ }
+ u.openConnection();
+ return true;
+ } catch (final Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Convenience method that proves if a parameter is set.
+ *
+ * @param param
+ * The parameter
+ * @return <tt>true</tt> if the given parameter string is not null.
+ */
+ public static boolean isParamSet(final String param) {
+ return param != null;
+ }
+
+ /**
+ * Proves that a class could be loaded.
+ *
+ * @param classname
+ * The classname to check
+ * @return <code>true</code> if the class was successfully loaded
+ */
+ public static boolean isLoadableClass(final String classname) {
+ try {
+ Class.forName(classname);
+ return true;
+ } catch (final Exception exc) {
+ return false;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/AbstractASTBase.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/AbstractASTBase.java
new file mode 100644
index 0000000..d68ebe3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/AbstractASTBase.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.ast.util.VisitorBase;
+
+public abstract class AbstractASTBase {
+ private Location location = null;
+
+ public AbstractASTBase(final Location location) {
+ this.location = location;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(Location location) {
+ this.location = location;
+ }
+
+ public int getColumnNumber() {
+ return location.getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ return location.getLineNumber();
+ }
+
+ public String getResource() {
+ return location.getResource();
+ }
+
+ public final Object accept(final VisitorBase visitor) {
+ return visitor.visit(this);
+ }
+
+ public int getLength() {
+ return location.getNameEnd();
+ }
+
+ public int getOffset() {
+ return location.getNameStart();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ComponentAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ComponentAST.java
new file mode 100644
index 0000000..a046396
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ComponentAST.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+public class ComponentAST extends AbstractASTBase implements NamedAST {
+
+ private String clazz = null;
+
+ private String id = null;
+
+ public void setId(final String id) {
+ this.id = id;
+ }
+
+ private final List<AbstractASTBase> children = new ArrayList<AbstractASTBase>();
+
+ private String name = null;
+
+ public String getName() {
+ return name;
+ }
+
+ public List<AbstractASTBase> getChildren() {
+ return children;
+ }
+
+ public ComponentAST(final Location location, final String name, final String clazz, final String id) {
+ super(location);
+ this.name = name;
+ this.clazz = clazz;
+ this.id = id;
+ }
+
+ protected ComponentAST(final Location location, final String string) {
+ super(location);
+ name = string;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getClazz() {
+ return clazz;
+ }
+
+ public void addChild(final AbstractASTBase ele) {
+ children.add(ele);
+ }
+
+ @Override
+ public String toString() {
+ return "bean " + name + (clazz != null ? " class='" + clazz + "'" : "")
+ + (id != null ? " id='" + id + "'" : "") + " " + getLocation();
+ }
+
+ public void setClazz(final String string) {
+ clazz = string;
+ }
+
+ private Object analyzedType = null;
+
+ public void setAnalyzedType(final Object analyzedType) {
+ this.analyzedType = analyzedType;
+ }
+
+ public Object getAnalyzedType() {
+ return analyzedType;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyAST.java
new file mode 100644
index 0000000..faad711
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyAST.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.ast.parser.WorkflowParser;
+
+public class DeclaredPropertyAST extends AbstractASTBase {
+
+ private String name;
+
+ private String value;
+
+ public DeclaredPropertyAST(final Location location, final String name) {
+ super(location);
+ this.name = name;
+ }
+
+ public DeclaredPropertyAST(final Location location, final String name, final String value) {
+ this(location, name);
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public boolean isAbstract() {
+ return value == null;
+ }
+
+ @Override
+ public String toString() {
+ return "<" + WorkflowParser.PROPERTY + " name='" + name + "'" + (!isAbstract() ? " value='" + value + "'" : "")
+ + "/>";
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyFileAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyFileAST.java
new file mode 100644
index 0000000..a8e2e86
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/DeclaredPropertyFileAST.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.ast.parser.WorkflowParser;
+
+public class DeclaredPropertyFileAST extends AbstractASTBase {
+ private static final Log log = LogFactory.getLog(DeclaredPropertyAST.class);
+
+ private String file;
+
+ public DeclaredPropertyFileAST(final Location location, final String file) {
+ super(location);
+ this.file = file;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ @Override
+ public String toString() {
+ return "<" + WorkflowParser.PROPERTY + " file='" + file + "'/>";
+ }
+
+ private Properties properties = null;
+
+ public Properties getProperties(final ResourceLoader loader) {
+ if (properties == null) {
+ final InputStream in = loader.getResourceAsStream(getFile());
+ if (in == null)
+ return null;
+ try {
+ properties = new Properties();
+ properties.load(in);
+ loadPropertyNames(loader.getResourceAsStream(getFile()));
+
+ } catch (final IOException e) {
+ log.error(e.getMessage(), e);
+ } finally {
+ try {
+ in.close();
+ } catch (final IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+ }
+ return properties;
+ }
+
+ private List<String> propertyNames = null;
+
+ public List<String> getPropertyNames(final ResourceLoader loader) {
+ getProperties(loader);
+ return propertyNames;
+ }
+
+ public void setFile(final String string) {
+ file = string;
+ }
+
+ private synchronized void loadPropertyNames(final InputStream inStream)
+ throws IOException {
+ propertyNames = new ArrayList<String>();
+ final BufferedReader in = new BufferedReader(new InputStreamReader(
+ inStream, "8859_1"));
+ while (true) {
+ final String line = in.readLine();
+ if (line == null)
+ return;
+
+ if (line.length() > 0) {
+ final int sep = line.indexOf('=');
+ if (sep != -1) {
+ final String key = line.substring(0, sep).trim();
+ if (key.length() > 0 && key.indexOf(' ') == -1
+ && key.indexOf('#') == -1 && key.indexOf('!') == -1) {
+ propertyNames.add(key);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/InclusionAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/InclusionAST.java
new file mode 100644
index 0000000..db19f55
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/InclusionAST.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import java.util.Map;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+public class InclusionAST extends ComponentAST {
+
+ private String file;
+ private boolean inheritAll = false;
+
+ private InclusionAST(final Location location, final String name, final String file, final String id) {
+ super(location, name);
+ setId(id);
+ this.file = file;
+ }
+ public InclusionAST(final Location location, final String name, final String file, final String id, final boolean inheritAll) {
+ this(location, name, file,id);
+ this.inheritAll = inheritAll;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public boolean isInheritAll() {
+ return inheritAll;
+ }
+
+ private AbstractASTBase referenced = null;
+
+ public AbstractASTBase getImportedElement() {
+ return referenced;
+ }
+
+ public void setImportedElement(final AbstractASTBase referenced) {
+ this.referenced = referenced;
+ }
+
+ public void setFile(final String string) {
+ file = string;
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " file='" + file + "'" + (getId() != null ? " id='" + getId() + "'" : "") + " "
+ + getLocation();
+ }
+
+ private Map<String, String> passedProperties = null;
+
+ private Map<String, ComponentAST> passedBeans = null;
+
+ public Map<String, ComponentAST> getPassedBeans() {
+ return passedBeans;
+ }
+
+ public void setPassedBeans(final Map<String, ComponentAST> passedBeans) {
+ this.passedBeans = passedBeans;
+ }
+
+ public Map<String, String> getPassedProperties() {
+ return passedProperties;
+ }
+
+ public void setPassedProperties(final Map<String, String> passedProperties) {
+ this.passedProperties = passedProperties;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/NamedAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/NamedAST.java
new file mode 100644
index 0000000..b9913be
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/NamedAST.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+public interface NamedAST {
+ public String getName();
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ReferenceAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ReferenceAST.java
new file mode 100644
index 0000000..3554eb2
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/ReferenceAST.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+public class ReferenceAST extends AbstractASTBase {
+
+ private String name;
+
+ private String idRef;
+
+ public ReferenceAST(final Location location, final String name, final String idRef) {
+ super(location);
+ this.name = name;
+ this.idRef = idRef;
+ }
+
+ public String getIdRef() {
+ return idRef;
+ }
+
+ public void setIdRef(final String idRef) {
+ this.idRef = idRef;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return "<" + name + " idRef='" + idRef + "'/> " + getLocation();
+ }
+
+ private ComponentAST reference = null;
+
+ public void setReference(final ComponentAST reference) {
+ this.reference = reference;
+ }
+
+ public ComponentAST getReference() {
+ return reference;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/SimpleParamAST.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/SimpleParamAST.java
new file mode 100644
index 0000000..6666070
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/SimpleParamAST.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast;
+
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+
+public class SimpleParamAST extends AbstractASTBase implements NamedAST {
+
+ private String name;
+
+ private String value;
+
+ public SimpleParamAST(final Location location, final String name, final String value) {
+ super(location);
+ this.name = name;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return name + "='" + value + "' " + getLocation().toString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String string) {
+ value = string;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/Location.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/Location.java
new file mode 100644
index 0000000..3c0e455
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/Location.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.parser;
+
+public class Location {
+ private int lineNumber;
+
+ private int columnNumber;
+
+ private int nameStart;
+
+ private int nameEnd;
+
+ private String resource;
+
+ public Location(final int line, final int column, final String resource) {
+ lineNumber = line;
+ columnNumber = column;
+ this.resource = resource;
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ public int getRawLineNumber() {
+ return lineNumber;
+ }
+
+ public void setLineNumber(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
+ public int getColumnNumber() {
+ return columnNumber;
+ }
+
+ public void setColumnNumber(int columnNumber) {
+ this.columnNumber = columnNumber;
+ }
+
+ public int getNameStart() {
+ return nameStart;
+ }
+
+ public void setNameStart(int nameStart) {
+ this.nameStart = nameStart;
+ }
+
+ public int getNameEnd() {
+ return nameEnd;
+ }
+
+ public void setNameEnd(int nameEnd) {
+ this.nameEnd = nameEnd;
+ }
+
+ public String getResource() {
+ return resource;
+ }
+
+ @Override
+ public String toString() {
+ return "in " + resource + ":" + lineNumber;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/ParseException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/ParseException.java
new file mode 100644
index 0000000..02e12ef
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/ParseException.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.parser;
+
+public class ParseException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1943730836608506785L;
+ private Location location;
+
+ public ParseException(final String string, final Location location) {
+ super(string);
+ this.location = location;
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/WorkflowParser.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/WorkflowParser.java
new file mode 100644
index 0000000..41ca50b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/WorkflowParser.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.parser;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Stack;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyFileAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.ReferenceAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class WorkflowParser extends DefaultHandler implements ContentHandler {
+ private static final Log log = LogFactory.getLog(WorkflowParser.class);
+
+ // reserved element names
+ public final static String PROPERTY = "property";
+
+ // reserver attribute names
+ public final static String CLASS = "class"; // components
+
+ public final static String FILE = "file"; // include
+
+ public final static String ID = "id"; // components
+
+ public final static String IDREF = "idRef"; // references
+
+ public final static String VALUE = "value"; // property, simple params
+
+ public final static String NAME = "name"; // property
+
+ private static final String INHERITALL = "inheritAll";
+
+ private final Stack<Object> eleStack = new Stack<Object>();
+
+ private AbstractASTBase root = null;
+
+ private org.xml.sax.Locator locator = null;
+
+ private String resource = "unknown";
+
+ private Issues issues = null;
+
+ public WorkflowParser() {
+ }
+
+ public AbstractASTBase parse(final InputStream in, final String resourceName, final Issues issues) {
+ resource = resourceName;
+ this.issues = issues;
+
+ try {
+ final SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ parser.parse(in, this);
+ } catch (final Exception e) {
+ root= null;
+ log.error(e.getMessage(), e);
+ issues.addError(e.getMessage(), resourceName);
+ }
+
+ return root;
+ }
+
+ @Override
+ public void setDocumentLocator (Locator locator){
+ this.locator = locator;
+ }
+
+ @Override
+ public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
+ if (PROPERTY.equals(qName)) {
+ final AbstractASTBase prop = handleProperty(qName, attributes);
+ connectAndPush(prop);
+ } else {
+ final AbstractASTBase ele = handleComp(qName, attributes);
+ connectAndPush(ele);
+ }
+ }
+
+ private void connectAndPush(final AbstractASTBase prop) {
+ if (eleStack.isEmpty()) {
+ eleStack.push(prop);
+ } else if (eleStack.peek() instanceof ComponentAST) {
+ ((ComponentAST) eleStack.peek()).getChildren().add(prop);
+ eleStack.push(prop);
+ } else {
+ issues.addError("The element " + eleStack.peek() + " cannot contain any child elements!", prop);
+ eleStack.push("DUMMY");
+ }
+ }
+
+ protected AbstractASTBase handleComp(final String name, final Attributes attributes) {
+ if (attributes.getValue(FILE) != null) {
+ boolean inheritAll = attributes.getValue(INHERITALL) != null;
+ final InclusionAST c = new InclusionAST(getLocation(), name, attributes.getValue(FILE), attributes
+ .getValue(ID),inheritAll);
+ if (attributes.getValue(CLASS) != null) {
+ issues.addError("Attribute 'class' not allowed for inclusions : " + PROPERTY, c);
+ }
+ for (int i = 0; i < attributes.getLength(); i++) {
+ final String temp = attributes.getQName(i);
+ if (!"".equals(temp) && !(FILE.equals(temp) || ID.equals(temp))) {
+ c.addChild(new SimpleParamAST(getLocation(), temp, attributes.getValue(temp)));
+ }
+ }
+ return c;
+ } else if (attributes.getValue(IDREF) != null) {
+ validateAttributes("reference " + name, attributes, new String[] { IDREF }, new String[0]);
+ return new ReferenceAST(getLocation(), name, attributes.getValue(IDREF));
+ } else if (attributes.getValue(VALUE) != null && attributes.getValue(NAME) == null) {
+ validateAttributes("simpleparam " + name, attributes, new String[] { VALUE }, new String[] {});
+ return new SimpleParamAST(getLocation(), name, attributes.getValue(VALUE));
+ } else {
+ final ComponentAST result = new ComponentAST(getLocation(), name, attributes.getValue(CLASS), attributes
+ .getValue(ID));
+ for (int i = 0; i < attributes.getLength(); i++) {
+ final String temp = attributes.getQName(i);
+ if (!"".equals(temp) && !(CLASS.equals(temp) || ID.equals(temp))) {
+ result.addChild(new SimpleParamAST(getLocation(), temp, attributes.getValue(temp)));
+ }
+ }
+ return result;
+ }
+ }
+
+ protected AbstractASTBase handleProperty(final String localName, final Attributes attributes) {
+ if (attributes.getValue(NAME) != null) {
+ validateAttributes(localName, attributes, new String[] { NAME }, new String[] { VALUE });
+ return new DeclaredPropertyAST(getLocation(), attributes.getValue(NAME), attributes.getValue(VALUE));
+ } else if (attributes.getValue(FILE) != null) {
+ validateAttributes(localName, attributes, new String[] { FILE }, new String[0]);
+ return new DeclaredPropertyFileAST(getLocation(), attributes.getValue(FILE));
+ } else {
+ issues.addError("Either 'name' or 'file' attribute is mandatory for element " + PROPERTY, getLocation());
+ return new DeclaredPropertyAST(getLocation(), "__UNKOWN__");
+ }
+ }
+
+ private void validateAttributes(final String eleName, final Attributes attributes, final String[] mandatory,
+ final String[] optional) {
+ final Set<String> mandatorySet = new HashSet<String>(Arrays.asList(mandatory));
+ final Set<String> optionalSet = new HashSet<String>(Arrays.asList(optional));
+ final Set<String> mandatoryFound = new HashSet<String>();
+ for (int i = 0; i < attributes.getLength(); i++) {
+ final String name = attributes.getQName(i);
+ if (name != null && !name.trim().equals("")) {
+ if (!(mandatorySet.contains(name) || optionalSet.contains(name))) {
+ issues.addError("Unkown attribute " + name + " for element " + eleName, getLocation());
+ }
+ }
+ if (mandatorySet.contains(name))
+ mandatoryFound.add(name);
+ }
+ mandatorySet.removeAll(mandatoryFound);
+ if (!mandatorySet.isEmpty()) {
+ for (final Iterator<String> iter = mandatorySet.iterator(); iter.hasNext();) {
+ final String name = iter.next();
+ issues.addError("Attribute " + name + " is mandatory for element " + eleName, getLocation());
+ }
+ }
+ }
+
+ private Location getLocation() {
+ return new Location(locator.getLineNumber(), locator.getColumnNumber(), resource);
+ }
+
+ @Override
+ public void endElement(final String uri, final String name, final String qName) {
+ root = (AbstractASTBase) eleStack.pop();
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/XmlLocationAnalyser.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/XmlLocationAnalyser.java
new file mode 100644
index 0000000..47f3571
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/parser/XmlLocationAnalyser.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.parser;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+
+public class XmlLocationAnalyser {
+ private Map<String, XmlFileEvaluator> repository = new HashMap<String, XmlFileEvaluator>();
+
+ protected ResourceLoader loader;
+
+ /**
+ * the SAX parser has no exact location handling. The offset and length information are updated here. <br>
+ * TODO: ER: add location of attributes (e.g. for error handling of not existing cartridge file)
+ *
+ * @param loc the (raw) location to be adapted
+ */
+ public Location adapt(Location loc) {
+ String resource = loc.getResource();
+ XmlFileEvaluator evaluator = evaluateResource(resource);
+ return evaluator.adapt(loc);
+ }
+
+ public Location adaptEnd(Location loc) {
+ String resource = loc.getResource();
+ XmlFileEvaluator evaluator = evaluateResource(resource);
+ return evaluator.adaptEnd(loc);
+ }
+
+ public int findFirstLineOfTag(String resource, int lineNumber) {
+ if (!repository.containsKey(resource)) {
+ evaluateResource(resource);
+ }
+ return repository.get(resource).findFirstLineOfTag(lineNumber);
+ }
+
+ private XmlFileEvaluator evaluateResource(String resource) {
+ if (loader == null)
+ loader = ResourceLoaderFactory.createResourceLoader();
+ InputStream is = loader.getResourceAsStream(resource);
+ XmlFileEvaluator evaluator = new XmlFileEvaluator();
+ evaluator.evaluate(is);
+ repository.put(resource, evaluator);
+ return evaluator;
+ }
+
+ protected XmlFileEvaluator newEvaluator() {
+ return new XmlFileEvaluator();
+ }
+
+ /**
+ * FOR TEST ONLY
+ */
+ public XmlFileEvaluator newEvaluator__TEST() {
+ return newEvaluator();
+ }
+
+ public class XmlFileEvaluator {
+
+ private List<XmlTagValues> values = new ArrayList<XmlTagValues>();
+
+ // for test only
+ private List<Object[]> result;
+
+ protected StringBuffer otherText, name, specChar;
+
+ protected boolean inTag, isClosingTag, inName, inInstruction, inComment = false;
+
+ public void evaluate(final InputStream is) {
+ if (is == null)
+ return;
+ int c;
+ result = new ArrayList<Object[]>();
+ int offset = 0, column = 0, nameStart = 0, nameEnd = 0, line = 0, tagLine = 0, firstColumn = 0;
+ reset();
+ try {
+ while ((c = is.read()) != -1) {
+ switch (c) {
+ case '<':
+ if (!(inTag || inInstruction || inComment)) {
+ inTag = true;
+ tagLine = line;
+ } else {
+ consume(c);
+ }
+ break;
+ case '>':
+ if (inTag) {
+ if (nameEnd == 0)
+ nameEnd = offset - specChar.length();
+ if (line != tagLine)
+ firstColumn = 0;
+ XmlTagValues value = new XmlTagValues();
+ value.firstLineOfTag = tagLine + 1;
+ value.lastLineOfTag = line + 1;
+ value.nameStart = nameStart;
+ value.nameEnd = nameEnd;
+ value.firstColumn = firstColumn - (isClosingTag ? 1 : 0);
+ value.endColumn = column + 1;
+ value.name = name.toString();
+ value.isClosingTag = isClosingTag;
+ values.add(value);
+
+ result.add(new Object[] { new String[] { name.toString(), otherText.toString() }, value });
+ reset();
+ nameEnd = 0;
+ } else if (inInstruction && specChar.toString().endsWith("?")) {
+ reset();
+ } else if (inComment && specChar.toString().endsWith("--")) {
+ reset();
+ } else {
+ consume(c);
+ }
+ break;
+ case '/':
+ if (inTag && !inInstruction && name.length() == 0)
+ isClosingTag = true;
+ specChar.append((char) c);
+ break;
+ case '!':
+ if (inTag && !inInstruction && name.length() == 0) {
+ specChar.append((char) c);
+ } else
+ consume(c);
+ break;
+ case '-':
+ if (inTag && name.length() == 0 || inComment) {
+ specChar.append((char) c);
+ } else
+ consume(c);
+ if (specChar.toString().endsWith("!--")) {
+ inTag = false;
+ inInstruction = false;
+ inComment = true;
+
+ }
+ break;
+ case '?':
+ if (inTag && !inInstruction && name.length() == 0) {
+ inTag = false;
+ inInstruction = true;
+ } else if (inInstruction) {
+ specChar.append((char) c);
+ } else
+ consume(c);
+ break;
+ case ' ':
+ case '\t':
+ if (inName) {
+ inName = false;
+ nameEnd = offset - specChar.length();
+ }
+ consume(c);
+ break;
+ case '\r':
+ specChar.append((char) c);
+ line++;
+ column = -1;
+ break;
+ case '\n':
+ if (!specChar.toString().endsWith("\r")) {
+ line++;
+ column = -1;
+ }
+ if (inName) {
+ inName = false;
+ nameEnd = offset - specChar.length();
+ }
+ consume(c);
+ break;
+ default:
+ if (inTag && !inName && name.length() == 0) {
+ specChar = new StringBuffer();
+ inName = true;
+ nameStart = offset;
+ firstColumn = column;
+ }
+ consume(c);
+ break;
+ }
+ offset++;
+ column++;
+ }
+ } catch (IOException e) {
+ //
+ }
+ }
+
+ private void consume(int c) {
+ if (inName)
+ name.append(specChar.toString() + (char) c);
+ else if (name.length() > 0)
+ otherText.append(specChar.toString() + (char) c);
+ if (specChar.length() > 0)
+ specChar = new StringBuffer();
+ }
+
+ private void reset() {
+ otherText = new StringBuffer();
+ name = new StringBuffer();
+ specChar = new StringBuffer();
+ inTag = false;
+ isClosingTag = false;
+ inName = false;
+ inInstruction = false;
+ inComment = false;
+ }
+
+ protected int findFirstLineOfTag(int lineNumber) {
+ for (XmlTagValues value : values) {
+ if (lineNumber >= value.firstLineOfTag && lineNumber <= value.lastLineOfTag)
+ return value.firstLineOfTag;
+ }
+ return -1;
+ }
+
+ public Location adapt(Location rawLoc) {
+ XmlTagValues value = findLine(rawLoc);
+ if (value == null) // should not occur
+ return null;
+ Location loc = new Location(value.firstLineOfTag, 0, rawLoc.getResource());
+ loc.setNameStart(value.nameStart);
+ loc.setNameEnd(value.nameEnd);
+ return loc;
+ }
+
+ protected Location adaptEnd(Location rawLoc) {
+ int line = rawLoc.getLineNumber();
+ int col = rawLoc.getColumnNumber();
+ String name1 = null;
+ XmlTagValues potentialValue = null;
+ for (XmlTagValues value : values) {
+ if (name1 == null && line == value.firstLineOfTag && col >= value.firstColumn && col <= value.endColumn)
+ name1 = value.name;
+ if (name1 == null && line < value.firstLineOfTag)
+ name1 = potentialValue.name;
+ else if (value.name.equals(name1) && value.isClosingTag) {
+ Location loc = new Location(value.firstLineOfTag, 0, rawLoc.getResource());
+ loc.setNameStart(value.nameStart);
+ loc.setNameEnd(value.nameEnd);
+ return loc;
+ }
+ potentialValue = value;
+ }
+ return null; // no end tag found; can that occur?
+ }
+
+ @SuppressWarnings("null")
+ protected XmlTagValues findLine(Location loc) {
+ if (values.isEmpty())
+ return null;
+ int line = loc.getRawLineNumber();
+ int col = loc.getColumnNumber();
+ List<XmlTagValues> potentialValues = new ArrayList<XmlTagValues>();
+ XmlTagValues value = null;
+ for (XmlTagValues nextValue : values) {
+ if (value == null) {
+ value = nextValue;
+ if (line < value.firstLineOfTag) {
+ potentialValues.add(value);
+ break;
+ }
+ continue;
+ }
+ if (line >= value.firstLineOfTag && line < nextValue.firstLineOfTag || value.firstLineOfTag == nextValue.firstLineOfTag)
+ potentialValues.add(value);
+ value = nextValue; // TODO: CK: low: check when we can break
+ }
+ // last tag
+ if (potentialValues.isEmpty() || line == value.firstLineOfTag)
+ potentialValues.add(value);
+ value = handleColumns(col, potentialValues);
+ return value;
+ }
+
+ protected XmlTagValues handleColumns(int col, List<XmlTagValues> values) {
+ if (values.size() == 1)
+ return values.get(0);
+ XmlTagValues value = null;
+ for (XmlTagValues nextValue : values) {
+ if (value == null) {
+ value = nextValue;
+ if (col < value.firstColumn)
+ return value;
+ continue;
+ }
+ if (col >= value.firstColumn && col < nextValue.firstColumn)
+ return value;
+ value = nextValue;
+ }
+ return value;
+ }
+
+ public List<Object[]> getResult() {
+ return result;
+
+ }
+ }
+
+ protected class XmlTagValues {
+ public int firstLineOfTag;
+
+ int lastLineOfTag;
+
+ public int nameStart;
+
+ public int nameEnd;
+
+ int firstColumn;
+
+ int endColumn;
+
+ boolean isClosingTag;
+
+ String name;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/Injector.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/Injector.java
new file mode 100644
index 0000000..c8d7c9d
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/Injector.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+public interface Injector {
+
+ public String getName();
+
+ public void setValue(Object target, Object val);
+
+ public Class<?> getRequiredType();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorFactory.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorFactory.java
new file mode 100644
index 0000000..0771559
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorFactory.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+
+public class InjectorFactory {
+
+ public final static Injector getInjector(final Class<?> c, final String name) {
+ Injector inj = getInjector1(c, name);
+ inj = inj == null ? getInjector2(c, name) : inj;
+ inj = inj == null ? getInjector3(c, name) : inj;
+ inj = inj == null ? getInjector4(c, name) : inj;
+ inj = inj == null ? getInjector5(c, name) : inj;
+ return inj;
+ }
+
+ private final static Injector getInjector1(final Class<?> c, final String name) {
+ final String adderName = "add" + firstUpper(name);
+ final Method[] ms = c.getMethods();
+ for (int i = 0; i < ms.length; i++) {
+ final Method method = ms[i];
+ final int mod = method.getModifiers();
+ if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getParameterTypes().length == 1) {
+ final String mn = method.getName();
+ if (mn.equals(adderName))
+ return new InjectorSimple(method, name);
+ }
+ }
+ return null;
+ }
+
+ private final static Injector getInjector2(final Class<?> c, final String name) {
+ final String getterName = "get" + firstUpper(name);
+ final Method[] ms = c.getMethods();
+ for (int i = 0; i < ms.length; i++) {
+ final Method method = ms[i];
+ final int mod = method.getModifiers();
+ if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getParameterTypes().length == 0) {
+ final String mn = method.getName();
+ if (mn.equals(getterName) && List.class.isAssignableFrom(method.getReturnType()))
+ return new InjectorList(method, name);
+ }
+ }
+ return null;
+ }
+
+ private final static Injector getInjector3(final Class<?> c, final String name) {
+ final String setterName = "set" + firstUpper(name);
+ final Method[] ms = c.getMethods();
+ for (int i = 0; i < ms.length; i++) {
+ final Method method = ms[i];
+ final int mod = method.getModifiers();
+ if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getParameterTypes().length == 1) {
+ final String mn = method.getName();
+ if (mn.equals(setterName) && !List.class.isAssignableFrom(method.getParameterTypes()[0]))
+ return new InjectorSimple(method, name);
+ }
+ }
+ return null;
+ }
+
+ private final static Injector getInjector4(final Class<?> c, final String name) {
+ final Method[] ms = c.getMethods();
+ for (int i = 0; i < ms.length; i++) {
+ final Method method = ms[i];
+ final int mod = method.getModifiers();
+ if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getParameterTypes().length == 2) {
+ final String mn = method.getName();
+ if (mn.equals("put") && method.getParameterTypes()[0].isAssignableFrom(String.class))
+ return new InjectorPut(method, name);
+ }
+ }
+ return null;
+ }
+
+ private final static Injector getInjector5(final Class<?> c, final String name) {
+ final String setterName = "addComponent";
+ final Method[] ms = c.getMethods();
+ for (int i = 0; i < ms.length; i++) {
+ final Method method = ms[i];
+ final int mod = method.getModifiers();
+ if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getParameterTypes().length == 1) {
+ final String mn = method.getName();
+ if (mn.equals(setterName) && !WorkflowComponent.class.isAssignableFrom(method.getParameterTypes()[0]))
+ return new InjectorSimple(method, name);
+ }
+ }
+ return null;
+ }
+
+ public static String firstUpper(String str) {
+ return str.substring(0, 1).toUpperCase().concat(str.substring(1));
+ }
+
+
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorList.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorList.java
new file mode 100644
index 0000000..2b7cd24
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorList.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class InjectorList implements Injector {
+ public Method getter;
+
+ public String name = null;
+
+ public InjectorList(final Method m, final String n) {
+ getter = m;
+ name = n;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setValue(final Object target, final Object val) {
+ try {
+ ((List<Object>) getter.invoke(target, new Object[0])).add(val);
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException());
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Class<?> getRequiredType() {
+ return Object.class;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorPut.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorPut.java
new file mode 100644
index 0000000..25877ed
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorPut.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.eclipse.emf.mwe.core.customizer.WorkflowCustomization;
+
+public class InjectorPut implements Injector {
+ public Method putMethod;
+
+ public String name = null;
+
+ public InjectorPut(final Method m, final String n) {
+ putMethod = m;
+ name = n;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setValue(final Object target, final Object val) {
+ try {
+ putMethod.invoke(target, new Object[] { name, val });
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException());
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Class<?> getRequiredType() {
+ Class<?> defaultClass = putMethod.getParameterTypes()[1];
+ Class<?> overriddenClass = WorkflowCustomization
+ .getKeywordMapping(getName());
+ if (overriddenClass != null) {
+ if (!defaultClass.isAssignableFrom(overriddenClass)) {
+ throw new RuntimeException("the customized class '"
+ + overriddenClass.getName() + "' for the keyword '"
+ + getName()
+ + "' is not a subtype of the default class '"
+ + defaultClass.getName()
+ + "'; falling back to default.");
+ }
+ return overriddenClass;
+ }
+ return defaultClass;
+
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorSimple.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorSimple.java
new file mode 100644
index 0000000..a7d7e35
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/InjectorSimple.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class InjectorSimple implements Injector {
+
+ private Method m = null;
+
+ private String name = null;
+
+ public InjectorSimple(final Method m, final String name) {
+ this.m = m;
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setValue(final Object target, final Object val) {
+ try {
+ m.invoke(target, new Object[] { val });
+ } catch (final InvocationTargetException e) {
+ throw new RuntimeException(e.getTargetException());
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Class<?> getRequiredType() {
+ return m.getParameterTypes()[0];
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorAnalyzer.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorAnalyzer.java
new file mode 100644
index 0000000..ade31e5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorAnalyzer.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.emf.mwe.core.customizer.CustomizationException;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.issues.IssuesImpl;
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.ReferenceAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.Converter;
+
+public class VisitorAnalyzer extends VisitorBase {
+
+ private VisitorAnalyzer cloneWithCurrentClass(final Class<?> c) {
+ final VisitorAnalyzer ana = new VisitorAnalyzer(issues, converter, c);
+ return ana;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<Class<?>, Converter> converter = new HashMap<Class<?>, Converter>(); // <Class,
+ // Converter>
+
+ private Class<?> currentComponentClass = null;
+
+ private Issues issues = new IssuesImpl();
+
+ private final ResourceLoader loader = ResourceLoaderFactory
+ .createResourceLoader();
+
+ @SuppressWarnings("unchecked")
+ public VisitorAnalyzer(final Issues issues,
+ final Map<Class<?>, Converter> converter,
+ final Class<?> currentComponentClass) {
+ if (currentComponentClass == null)
+ throw new NullPointerException("currentComponentClass");
+ this.issues = issues;
+ this.converter = converter;
+ this.currentComponentClass = currentComponentClass;
+ }
+
+ @Override
+ public Object visitComponentAST(final ComponentAST componentAST) {
+ String elementName = componentAST.getName();
+ Class<?> expected = null;
+ try {
+ expected = getTypeForProperty(elementName);
+ } catch (CustomizationException ex) {
+ issues.addError(ex.getMessage(), componentAST);
+ return null;
+ }
+ if (expected == null) {
+ issues.addError("No getter or adder method for property '"
+ + elementName + "' in clazz '"
+ + currentComponentClass.getName()
+ + "' found. Forgot to customize?", componentAST);
+ } else {
+ if (componentAST.getClazz() != null) {
+ final Class<?> actual = loader.loadClass(componentAST
+ .getClazz());
+ if (actual == null) {
+ issues.addError("Class not found: '"
+ + componentAST.getClazz() + "'", componentAST);
+ } else if (!expected.isAssignableFrom(actual)) {
+ issues.addError("Incompatible Classes: "
+ + componentAST.getClazz()
+ + " is not a subclass of the expected class "
+ + expected.getName(), componentAST);
+ } else {
+ expected = actual;
+ }
+ }
+ componentAST.setAnalyzedType(expected);
+ final VisitorAnalyzer v = cloneWithCurrentClass(expected);
+ for (final Iterator<?> iter = componentAST.getChildren().iterator(); iter
+ .hasNext();) {
+ ((AbstractASTBase) iter.next()).accept(v);
+ }
+ }
+ return expected;
+ }
+
+ @Override
+ public Object visitReferenceAST(final ReferenceAST ele) {
+ Class<?> expected = null;
+ try {
+ expected = getTypeForProperty(ele.getName());
+ } catch (CustomizationException ex) {
+ issues.addError(ex.getMessage(), ele);
+ return null;
+ }
+ if (expected == null) {
+ issues.addError("No setter or adder method for property '"
+ + ele.getName() + "' in clazz '"
+ + currentComponentClass.getName() + "' found", ele);
+ return ele;
+ }
+
+ if (ele.getReference() == null) {
+ issues.addError("Reference to bean with id " + ele.getIdRef()
+ + " not resolved!", ele);
+ } else {
+ final Class<?> c = (Class<?>) ele.getReference().getAnalyzedType();
+ if (c != null && !expected.isAssignableFrom(c)) {
+ issues.addWarning("The type of the refered bean ("
+ + c.getName() + ") is nat assignable to "
+ + expected.getName());
+ }
+ return c;
+ }
+ return expected;
+ }
+
+ @Override
+ public Object visitSimpleParamAST(final SimpleParamAST ele) {
+ Class<?> expected = null;
+ try {
+ expected = getTypeForProperty(ele.getName());
+ } catch (CustomizationException ex) {
+ issues.addError(ex.getMessage(), ele);
+ return null;
+ }
+ if (expected == null) {
+ issues.addError("No getter or adder method for property '"
+ + ele.getName() + " in clazz '" + getCurrClassName()
+ + "' found", ele);
+ } else if (!converter.containsKey(expected)) {
+ issues.addError("Cannot convert from String to "
+ + expected.getName()
+ + ". You need to register a corresponding Converter.", ele);
+ }
+ return expected;
+ }
+
+ private String getCurrClassName() {
+ return currentComponentClass != null ? currentComponentClass.getName()
+ : "unknown";
+ }
+
+ private Class<?> getTypeForProperty(final String name) {
+ if (currentComponentClass != null) {
+ final Injector inj = InjectorFactory.getInjector(
+ currentComponentClass, name);
+ if (inj != null)
+ return inj.getRequiredType();
+ }
+ return null;
+ }
+
+ @Override
+ public Object visitInclusionAST(final InclusionAST ele) {
+ if (ele.getImportedElement() != null) {
+ return ele.getImportedElement().accept(
+ cloneWithCurrentClass(WorkflowContainer.class));
+ }
+ issues.addError("Cartridge " + ele.getFile() + " not resolved!", ele);
+ return Object.class;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorBase.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorBase.java
new file mode 100644
index 0000000..7df8905
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorBase.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyFileAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.ReferenceAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+
+public abstract class VisitorBase {
+
+ protected static final Log log = LogFactory.getLog(VisitorBase.class);
+
+ protected ResourceLoader loader = ResourceLoaderFactory
+ .createResourceLoader();
+
+ public final Object visit(final AbstractASTBase ele) {
+ Object result = visitAbstractASTBase(ele);
+ if (result == null && ele instanceof InclusionAST) {
+ result = visitInclusionAST((InclusionAST) ele);
+ }
+ if (result == null && ele instanceof ComponentAST) {
+ result = visitComponentAST((ComponentAST) ele);
+ }
+ if (result == null && ele instanceof DeclaredPropertyAST) {
+ result = visitDeclaredPropertyAST((DeclaredPropertyAST) ele);
+ }
+ if (result == null && ele instanceof DeclaredPropertyFileAST) {
+ result = visitDeclaredPropertyFileAST((DeclaredPropertyFileAST) ele);
+ }
+ if (result == null && ele instanceof ReferenceAST) {
+ result = visitReferenceAST((ReferenceAST) ele);
+ }
+ if (result == null && ele instanceof SimpleParamAST) {
+ result = visitSimpleParamAST((SimpleParamAST) ele);
+ }
+ return result;
+ }
+
+ public Object visitAbstractASTBase(@SuppressWarnings("unused")
+ final AbstractASTBase ele) {
+ return null;
+ }
+
+ public Object visitComponentAST(@SuppressWarnings("unused")
+ final ComponentAST ele) {
+ return null;
+ }
+
+ public Object visitInclusionAST(@SuppressWarnings("unused")
+ final InclusionAST ele) {
+ return null;
+ }
+
+ public Object visitDeclaredPropertyAST(@SuppressWarnings("unused")
+ final DeclaredPropertyAST ele) {
+ return null;
+ }
+
+ public Object visitDeclaredPropertyFileAST(@SuppressWarnings("unused")
+ final DeclaredPropertyFileAST ele) {
+ return null;
+ }
+
+ public Object visitReferenceAST(@SuppressWarnings("unused")
+ final ReferenceAST ele) {
+ return null;
+ }
+
+ public Object visitSimpleParamAST(@SuppressWarnings("unused")
+ final SimpleParamAST ele) {
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorCreator.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorCreator.java
new file mode 100644
index 0000000..d3457c3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorCreator.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.emf.mwe.core.ConfigurationException;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.issues.IssuesImpl;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.ReferenceAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.Converter;
+
+public class VisitorCreator extends VisitorBase {
+
+ private VisitorCreator cloneWithBean(final Object newBean) {
+ final VisitorCreator newInst = new VisitorCreator(issues, converter, newBean);
+ newInst.beans = beans;
+ return newInst;
+ }
+
+ private Map<String, Object> beans = new HashMap<String, Object>();
+
+ @SuppressWarnings("unchecked")
+ private Map<Class<?>, Converter> converter = new HashMap<Class<?>, Converter>(); // <Class, Converter>
+
+ private Object currentBean = null;
+
+ private Issues issues = new IssuesImpl();
+
+ @SuppressWarnings("unchecked")
+ public VisitorCreator(final Issues issues, final Map<Class<?>, Converter> converter, final Object rootBean) {
+ this.issues = issues;
+ this.converter = converter;
+ currentBean = rootBean;
+ }
+
+ @Override
+ public Object visitInclusionAST(final InclusionAST cart) {
+ if (cart.getImportedElement() == null) {
+ issues.addError("referenced element not resolved! ", cart);
+ }
+ final Class<?> type = currentBean.getClass();
+ final Injector inj = InjectorFactory.getInjector(type, cart.getName());
+ if (inj == null) {
+ issues.addError("no injector could be found in class " + type.getName() + " for property '"
+ + cart.getName() + "'!", cart);
+ return cart;
+ }
+ final Map<String, Object> beansToPass = new HashMap<String, Object>();
+ if (cart.isInheritAll()) {
+ beansToPass.putAll(this.beans);
+ }
+ for (final Iterator<?> iter = cart.getChildren().iterator(); iter.hasNext();) {
+ final Object o = iter.next();
+ if (o instanceof InclusionAST)
+ throw new ConfigurationException("Nested inclusions are not supported!");
+ else if (o instanceof ComponentAST) {
+ final ComponentAST p = (ComponentAST) o;
+ final Object bean = createBean(p, null);
+ beansToPass.put(p.getName(), bean);
+ } else if (o instanceof ReferenceAST) {
+ final ReferenceAST ref = (ReferenceAST) o;
+ if (beans.containsKey(ref.getIdRef())) {
+ beansToPass.put(ref.getName(), beans.get(ref.getIdRef()));
+ } else {
+ issues.addError("No bean with id " + ref.getIdRef() + " found!", ref);
+ }
+ }
+ }
+ final WorkflowContainer wc = new WorkflowContainer();
+ final VisitorCreator vis = cloneWithBean(wc);
+ vis.beans = beansToPass;
+ final Object importedElement = cart.getImportedElement().accept(vis);
+ setValue(importedElement, cart.getName(), cart);
+
+ final Injector inj1 = InjectorFactory.getInjector(importedElement.getClass(), "location");
+ if (inj1 != null) {
+ inj1.setValue(importedElement, cart.getLocation());
+ }
+ final Injector inj2 = InjectorFactory.getInjector(importedElement.getClass(), "ownLocation");
+ if (inj2 != null) {
+ inj2.setValue(importedElement, cart.getImportedElement().getLocation());
+ }
+
+
+ if (cart.getId() != null) {
+ beans.put(cart.getId(), importedElement);
+ }
+ return importedElement;
+ }
+
+ @Override
+ public Object visitComponentAST(final ComponentAST comp) {
+ final Class<?> type = currentBean.getClass();
+ final Injector inj = InjectorFactory.getInjector(type, comp.getName());
+ if (inj == null) {
+ issues.addError("no injector could be found in class " + type.getName() + " for property '"
+ + comp.getName() + "'!", comp);
+ return comp;
+ }
+ final Class<?> toLoad = inj.getRequiredType();
+ final Object bean = createBean(comp, toLoad);
+
+ if (bean != null) {
+ inj.setValue(currentBean, bean);
+ }
+ return bean;
+ }
+
+ private Object createBean(final ComponentAST comp, Class<?> toLoad) {
+ Object bean = null;
+ if (comp.getClazz() != null) {
+ toLoad = loader.loadClass(comp.getClazz());
+ if (toLoad == null) {
+ issues.addError("Class not found: '" + comp.getClazz() + "'", comp);
+ return comp;
+ }
+ }
+ try {
+ bean = toLoad.newInstance();
+ if (comp.getId() != null) {
+ beans.put(comp.getId(), bean);
+ final Injector inj = InjectorFactory.getInjector(bean.getClass(), "id");
+ if (inj != null) {
+ inj.setValue(bean, comp.getId());
+ }
+ }
+ if (comp.getLocation() != null) {
+ final Injector inj = InjectorFactory.getInjector(bean.getClass(), "resource");
+ if (inj != null) {
+ inj.setValue(bean, comp.getLocation().getResource());
+ }
+ final Injector inj1 = InjectorFactory.getInjector(bean.getClass(), "location");
+ if (inj1 != null) {
+ inj1.setValue(bean, comp.getLocation());
+ }
+ }
+ final VisitorBase vis = cloneWithBean(bean);
+ for (final Iterator<?> iter = comp.getChildren().iterator(); iter.hasNext();) {
+ ((AbstractASTBase) iter.next()).accept(vis);
+ }
+ } catch (final Exception e) {
+ log.error(e);
+ issues.addError("Error creating instance of type '" + comp.getClazz() + "' : " + e.getMessage(), comp);
+ }
+ return bean;
+ }
+
+ private void setValue(final Object value, final String name, final AbstractASTBase ele) {
+ final Injector inj = InjectorFactory.getInjector(currentBean.getClass(), name);
+ if (inj == null) {
+ issues.addError("no setter or adder could be found in class " + currentBean.getClass().getName() + " for '"
+ + name + "'!", ele);
+ } else {
+ inj.setValue(currentBean, value);
+ }
+ }
+
+ @Override
+ public Object visitReferenceAST(final ReferenceAST ref) {
+ if (beans.containsKey(ref.getIdRef())) {
+ setValue(beans.get(ref.getIdRef()), ref.getName(), ref);
+ return beans.get(ref.getIdRef());
+ }
+ issues.addError("Couldn't find bean with id " + ref.getIdRef() + " : ", ref);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object visitSimpleParamAST(final SimpleParamAST param) {
+ final Injector inj = InjectorFactory.getInjector(currentBean.getClass(), param.getName());
+ if (inj == null) {
+ issues.addError("no setter or adder could be found in class " + currentBean.getClass().getName() + " for '"
+ + param.getName() + "'!", param);
+ return null;
+ }
+ final Converter conv = converter.get(inj.getRequiredType());
+ if (conv == null) {
+ issues.addError("No converter found for " + param + " converting to " + inj.getRequiredType(), param);
+ return null;
+ }
+ final Object val = conv.convert(param.getValue());
+ inj.setValue(currentBean, val);
+ return val;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorInitializer.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorInitializer.java
new file mode 100644
index 0000000..bda9f29
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/VisitorInitializer.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyAST;
+import org.eclipse.emf.mwe.internal.core.ast.DeclaredPropertyFileAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.ReferenceAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+import org.eclipse.emf.mwe.internal.core.ast.parser.WorkflowParser;
+
+public class VisitorInitializer extends VisitorBase {
+
+ private VisitorInitializer cloneThis() {
+ final VisitorInitializer newOne = new VisitorInitializer(issues, props,
+ beans);
+ newOne.beans = beans;
+ newOne.props = props;
+ newOne.declaredPropertyNames = declaredPropertyNames;
+ return newOne;
+ }
+
+ public VisitorInitializer(final Issues issues,
+ final Map<String, String> initialProperties,
+ final Map<String, ComponentAST> initialBeans) {
+ this.issues = issues;
+ props = new HashMap<String, String>(initialProperties);
+ beans = new HashMap<String, ComponentAST>(initialBeans);
+ }
+
+ private Set<String> declaredPropertyNames = new HashSet<String>();
+
+ private Issues issues = null;
+
+ private Map<String, ComponentAST> beans = null;
+
+ private Map<String, String> props = null;
+
+ private void traverseChildren(final ComponentAST c) {
+ for (final Iterator<?> iter = c.getChildren().iterator(); iter
+ .hasNext();) {
+ final AbstractASTBase element = (AbstractASTBase) iter.next();
+ element.accept(cloneThis());
+ }
+ }
+
+ @Override
+ public Object visitComponentAST(final ComponentAST comp) {
+
+ comp.setClazz(replaceProperties(comp.getClazz(), comp));
+ handleIdentifiedAST(comp);
+ traverseChildren(comp);
+ return comp;
+ }
+
+ private void handleIdentifiedAST(final ComponentAST comp) {
+ if (comp.getId() != null) {
+ comp.setId(replaceProperties(comp.getId(), comp));
+ beans.put(comp.getId(), comp);
+ }
+ }
+
+ @Override
+ public Object visitInclusionAST(final InclusionAST comp) {
+ comp.setFile(replaceProperties(comp.getFile(), comp));
+ handleIdentifiedAST(comp);
+ traverseChildren(comp);
+ final Map<String, String> params = new HashMap<String, String>();
+ final Map<String, ComponentAST> paramBeans = new HashMap<String, ComponentAST>();
+
+ if (comp.isInheritAll()) {
+ params.putAll(this.props);
+ paramBeans.putAll(this.beans);
+ }
+ for (final Iterator<?> iter = comp.getChildren().iterator(); iter
+ .hasNext();) {
+ final Object o = iter.next();
+ if (o instanceof SimpleParamAST) {
+ final SimpleParamAST p = (SimpleParamAST) o;
+ params.put(p.getName(), p.getValue());
+ } else if (o instanceof ComponentAST) {
+ final ComponentAST p = (ComponentAST) o;
+ paramBeans.put(p.getName(), p);
+ } else if (o instanceof ReferenceAST) {
+ final ReferenceAST ref = (ReferenceAST) o;
+ paramBeans.put(ref.getName(), ref.getReference());
+ }
+ }
+ comp.setPassedBeans(paramBeans);
+ comp.setPassedProperties(params);
+ if (comp.getFile() != null) {
+ final WorkflowParser p = new WorkflowParser();
+ InputStream in = loader.getResourceAsStream(translateFileURI(comp
+ .getFile(), "mwe"));
+ if (in == null) {
+ in = loader.getResourceAsStream(translateFileURI(
+ comp.getFile(), "oaw"));
+ if (in == null) {
+ issues.addError("Couldn't load workflow fragment from "
+ + comp.getFile(), comp);
+ return comp;
+ }
+ }
+ final AbstractASTBase ref = p.parse(in, comp.getFile(), issues);
+ comp.setImportedElement(ref);
+ if (ref == null) {
+ issues.addError("Couldn't parse nested workflow file "
+ + comp.getFile(), comp);
+ return comp;
+ }
+ if (comp.getPassedProperties() == null) {
+ issues.addError(
+ "Workflow not initialized! (passedProperties is null)",
+ comp);
+ return comp;
+ }
+ final VisitorInitializer vis = new VisitorInitializer(issues, comp
+ .getPassedProperties(), comp.getPassedBeans());
+ ref.accept(vis);
+ }
+ return comp;
+ }
+
+ private String translateFileURI(String file, String extension) {
+ if (file.indexOf("::") != -1) {
+ file = file.replaceAll("::", "/");
+ }
+ if (!file.endsWith("." + extension)) {
+ file += "." + extension;
+ }
+ return file;
+ }
+
+ @Override
+ public Object visitReferenceAST(final ReferenceAST comp) {
+ comp.setIdRef(replaceProperties(comp.getIdRef(), comp));
+ final ComponentAST ref = beans.get(comp.getIdRef());
+ if (ref == null) {
+ issues.addError("Couldn't find bean with id '" + comp.getIdRef()
+ + "'", comp);
+ } else {
+ comp.setReference(ref);
+ }
+ return comp;
+ }
+
+ @Override
+ public Object visitSimpleParamAST(final SimpleParamAST param) {
+ param.setValue(replaceProperties(param.getValue(), param));
+ return param;
+ }
+
+ @Override
+ public Object visitDeclaredPropertyAST(final DeclaredPropertyAST prop) {
+ if (prop.getValue() != null) {
+ final String n = replaceProperties(prop.getName(), prop);
+ if (!props.containsKey(n)) {
+ props.put(n, replaceProperties(prop.getValue(), prop));
+ } else {
+ if (!declaredPropertyNames.add(n)) {
+ issues.addError("Duplicate property " + n, prop);
+ }
+ }
+ }
+ return props;
+ }
+
+ @Override
+ public Object visitDeclaredPropertyFileAST(
+ final DeclaredPropertyFileAST propFile) {
+ propFile.setFile(replaceProperties(propFile.getFile(), propFile));
+ final Properties properties = propFile.getProperties(loader);
+ if (properties == null) {
+ issues.addError("Couldn't resolve properties file!", propFile);
+ return new HashMap<Object, Object>();
+ }
+ for (final Iterator<String> iter = propFile.getPropertyNames(loader)
+ .iterator(); iter.hasNext();) {
+ final String name = replaceProperties(iter.next(), propFile);
+ final String val = replaceProperties((String) properties.get(name),
+ propFile);
+ if (!props.containsKey(name)) {
+ props.put(name, val);
+ } else {
+ if (!declaredPropertyNames.add(name)) {
+ issues.addError("Duplicate property " + name, propFile);
+ }
+ }
+ }
+ return props;
+ }
+
+ private static final Pattern PROPERTY_PATTERN = Pattern
+ .compile("\\$\\{([\\w_\\.-]+)\\}");
+
+ protected String replaceProperties(final String toResolve,
+ AbstractASTBase ast) {
+ return replaceProperties(toResolve, true, ast);
+ }
+
+ private final Stack<String> currentProp = new Stack<String>();
+
+ protected String replaceProperties(final String toResolve,
+ final boolean logIssues, AbstractASTBase ast) {
+ if (toResolve == null)
+ return null;
+ // if (currentProp.contains(toResolve)) {
+ // issues.addError("property "+toResolve+" not found!");
+ // return null;
+ // }
+ //
+ // try {
+ currentProp.push(toResolve);
+ final Matcher m = PROPERTY_PATTERN.matcher(toResolve);
+ final StringBuffer buff = new StringBuffer();
+ int index = 0;
+ while (m.find()) {
+ final String varName = m.group(1);
+ String propValue = props.get(varName);
+ if (propValue == null) {
+ if (logIssues)
+ issues.addError("property " + varName
+ + " not specified. Dereferenced at "
+ + ast.getLocation().toString());
+
+ return null;
+ }
+ propValue = replaceProperties(propValue, logIssues, ast);
+ final int start = m.start();
+ final int end = m.end();
+ buff.append(toResolve.substring(index, start));
+ buff.append(propValue);
+ index = end;
+ }
+ buff.append(toResolve.substring(index));
+ return buff.toString();
+ // } finally {
+ // currentProp.pop();
+ // }
+
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowContainer.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowContainer.java
new file mode 100644
index 0000000..732bb13
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowContainer.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import org.eclipse.emf.mwe.internal.core.Workflow;
+
+public class WorkflowContainer {
+ private Object root = null;
+
+ public void setWorkflow(final Workflow workflow) {
+ root = workflow;
+ }
+
+ public void put(@SuppressWarnings("unused")
+ final String name, final Object value) {
+ root = value;
+ }
+
+ public Object getRoot() {
+ return root;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowFactory.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowFactory.java
new file mode 100644
index 0000000..5f6fa39
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/WorkflowFactory.java
@@ -0,0 +1,138 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.internal.core.ast.util;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+import org.eclipse.emf.mwe.internal.core.Workflow;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.SimpleParamAST;
+import org.eclipse.emf.mwe.internal.core.ast.parser.WorkflowParser;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.BooleanConverter;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.Converter;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.IntegerConverter;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.StringArrayConverter;
+import org.eclipse.emf.mwe.internal.core.ast.util.converter.StringConverter;
+
+/**
+ * The WorkflowFactory is responsible for creating
+ * {@link org.eclipse.emf.mwe.core.WorkflowComponent WorkflowComponents}
+ * from a workflow configuration.
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+
+ */
+public class WorkflowFactory {
+
+ private final ResourceLoader loader = ResourceLoaderFactory.createResourceLoader();
+
+ @SuppressWarnings("unchecked")
+ public Workflow parseInitAndCreate(final String fileName, final Map<String, String> params, final Map<Class<?>, Converter> converter, final Issues issues) {
+ final InputStream in = loader.getResourceAsStream(fileName);
+ if (in == null)
+ throw new IllegalArgumentException("Couldn't load file " + fileName);
+ return parseInitAndCreate(in, fileName, params, converter, issues);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Workflow parseInitAndCreate(final InputStream in, final String resourceName, final Map<String, String> params,
+ final Map<Class<?>, Converter> converters, final Issues issues) {
+ final AbstractASTBase wfast = parseAndInitialize(in, resourceName, issues, params);
+ if (isAbstract(wfast)) {
+ issues.clear();
+ issues
+ .addError("This workflow file is abstract and cannot be run directly. It must be called from another workflow, passing in the required parameters.");
+ return null;
+ }
+ if (issues.hasErrors())
+ return null;
+ final WorkflowContainer wc = new WorkflowContainer();
+ wfast.accept(new VisitorAnalyzer(issues, converters, wc.getClass()));
+ if (issues.hasErrors())
+ return null;
+ wfast.accept(new VisitorCreator(issues, converters, wc));
+ Workflow wfRoot = (Workflow) wc.getRoot();
+ return wfRoot;
+ }
+
+ private boolean isAbstract(AbstractASTBase wfast) {
+ if (wfast instanceof ComponentAST) {
+ ComponentAST ca = (ComponentAST) wfast;
+ for (Iterator<AbstractASTBase> iter = ca.getChildren().iterator(); iter.hasNext();) {
+ AbstractASTBase child = iter.next();
+ if (child instanceof SimpleParamAST) {
+ SimpleParamAST spa = (SimpleParamAST) child;
+ if (spa.getName().toLowerCase().equals("abstract") && spa.getValue().toLowerCase().equals("true")) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public AbstractASTBase parseAndInitialize(final String uri, final Issues issues, final Map<String, String> properties) {
+ final InputStream in = loader.getResourceAsStream(uri);
+ if (in == null) {
+ issues.addError("Couldn't find resource '" + uri + "'", null);
+ return null;
+ }
+ return parseAndInitialize(in, uri, issues, properties);
+ }
+
+ public AbstractASTBase parseAndInitialize(final InputStream in, final String resourceName, final Issues issues, final Map<String, String> properties) {
+ final WorkflowParser wp = new WorkflowParser();
+ final AbstractASTBase wfast = wp.parse(in, resourceName, issues);
+
+ if (wfast != null) {
+ // resolve properties
+ final VisitorInitializer pr = new VisitorInitializer(issues, properties, new HashMap<String, ComponentAST>());
+ wfast.accept(pr);
+ }
+ return wfast;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Set<?> parseInitAndAnalyze(final InputStream in, final String resourceName, final Issues issues, final Map<String, String> properties,
+ final Map<Class<?>, Converter> converter) {
+ final AbstractASTBase wf = parseAndInitialize(in, resourceName, issues, properties);
+ final Map<Class<?>, Converter> conv = WorkflowFactory.getDefaultConverter();
+ conv.putAll(converter);
+ final VisitorAnalyzer visitor = new VisitorAnalyzer(issues, conv, WorkflowContainer.class);
+ return (Set<?>) wf.accept(visitor);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<Class<?>, Converter> getDefaultConverter() {
+ final Map<Class<?>, Converter> m = new HashMap<Class<?>, Converter>();
+ m.put(Object.class, new StringConverter());
+ m.put(String.class, new StringConverter());
+ m.put(Boolean.class, new BooleanConverter());
+ m.put(Boolean.TYPE, new BooleanConverter());
+ m.put(Integer.class, new IntegerConverter());
+ m.put(Integer.TYPE, new IntegerConverter());
+ m.put(String[].class, new StringArrayConverter());
+ return m;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/BooleanConverter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/BooleanConverter.java
new file mode 100644
index 0000000..5d165ac
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/BooleanConverter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util.converter;
+
+public class BooleanConverter implements Converter<Boolean> {
+
+ public Boolean convert(final String s) {
+ return Boolean.valueOf(s);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/Converter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/Converter.java
new file mode 100644
index 0000000..85cef2f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/Converter.java
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util.converter;
+
+public interface Converter<T> {
+ public T convert(String s);
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/IntegerConverter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/IntegerConverter.java
new file mode 100644
index 0000000..453a953
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/IntegerConverter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util.converter;
+
+public class IntegerConverter implements Converter<Integer> {
+
+ public Integer convert(final String s) {
+ return Integer.valueOf(s);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringArrayConverter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringArrayConverter.java
new file mode 100644
index 0000000..0bda252
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringArrayConverter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util.converter;
+
+public class StringArrayConverter implements Converter<String[]> {
+
+ public String[] convert(final String s) {
+ return s.split(",");
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringConverter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringConverter.java
new file mode 100644
index 0000000..53b515e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/ast/util/converter/StringConverter.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.ast.util.converter;
+
+public class StringConverter implements Converter<String> {
+
+ public String convert(final String s) {
+ return s;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/Connection.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/Connection.java
new file mode 100644
index 0000000..b3c8af8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/Connection.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.AbstractPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.HandshakePacket;
+
+/**
+ * This class implements a socket connection model. "Packets" (units of information) can be transfered between two
+ * different virtual machines. During the initialisation of a socket connection a reader and a writer thread are
+ * established. This class can be used both on the sender and receiver side.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class Connection {
+
+ private ServerSocket ssocket;
+
+ private Socket socket;
+
+ private DataOutputStream out;
+
+ private DataInputStream in;
+
+ private PacketSender sender;
+
+ private PacketReceiver receiver;
+
+ // -------------------------------------------------------------------------
+ // *the* main operation methods
+
+ public AbstractPacket listenForPacket(Class<? extends AbstractPacket> type) throws InterruptedIOException {
+ return receiver.getPacket(type, -1);
+ }
+
+ public AbstractPacket listenForPacket(Class<? extends AbstractPacket> type, int refId) throws InterruptedIOException {
+ return receiver.getPacket(type, refId, -1);
+ }
+
+ public int sendPacket(AbstractPacket packet) throws IOException {
+ if (sender == null)
+ return -1;
+ return sender.sendPacket(packet);
+ }
+
+ // -------------------------------------------------------------------------
+ // socket communication handling
+
+ /**
+ * create a new <code>ServerSocket</code>.
+ *
+ * @param port the communication port
+ * @throws IOException
+ */
+ public void startListeningSocket(int port) throws IOException {
+ ssocket = new ServerSocket(port);
+ }
+
+ /**
+ * the server listens for a client to connect, creates new reader and writer threads and sends a first
+ * handshake packet to test the communication
+ *
+ * @param timeout
+ * @throws IOException
+ */
+ public void accept(int timeout) throws IOException {
+ ssocket.setSoTimeout(timeout);
+ // will throw SocketTimeoutException, if nobody connects
+ socket = ssocket.accept();
+ establishReaderAndWriter();
+ if (!writeHandshake())
+ throw new IOException("handshake failed");
+ }
+
+ /**
+ * the client establishes the connection here, creates new reader and writer threads and waits for a handshake
+ * packet to be received from the server
+ *
+ * @param port
+ * @throws IOException
+ */
+ public void connect(int port) throws IOException {
+ socket = new Socket("localhost", port);
+ establishReaderAndWriter();
+ replyHandshake();
+ }
+
+ /**
+ * @return if the socket connection is still active
+ */
+ public boolean isConnected() {
+ return socket != null && !socket.isClosed();
+ }
+
+ /**
+ * close and dispose the socket and the (possibly waiting) sender thread
+ */
+ public void close() {
+ try {
+ if (sender != null)
+ sender.close();
+ if (socket != null) {
+ out.close();
+ in.close();
+ socket.close();
+ out = null;
+ in = null;
+ }
+ sender = null;
+ socket = null;
+ ssocket.close();
+ ssocket = null;
+ } catch (Exception e) {
+ // IOExceptions and NullPointerExceptions may occur
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // the real sending and receiving of packets to be called from PacketReceiver and PacketSender only
+
+ protected AbstractPacket readPacket() throws IOException {
+ String className = in.readUTF();
+ AbstractPacket packet = instantiatePacket(className);
+ packet.readContent(in);
+ // System.out.println(Thread.currentThread().getName() + "-RECEIVED-: " + packet);
+ return packet;
+ }
+
+ @SuppressWarnings("unchecked")
+ private AbstractPacket instantiatePacket(String className) throws IOException {
+ Class<? extends AbstractPacket> packetClass = null;
+ AbstractPacket packet = null;
+ String msg = null;
+ try {
+ packetClass = (Class<? extends AbstractPacket>) Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ msg = "Couldn't find " + className + " in the classpath.";
+ }
+
+ if (msg == null) {
+ Constructor c = packetClass.getConstructors()[0];
+ Class[] parmTypes = c.getParameterTypes();
+ Object[] initargs = new Object[parmTypes.length];
+ for (int i = 0; i < parmTypes.length; i++)
+ if (parmTypes[i] == int.class)
+ initargs[i] = 0;
+ try {
+ packet = (AbstractPacket) c.newInstance(initargs);
+ } catch (IllegalArgumentException e) {
+ msg = "Couldn't instantiate " + c + " : " + e;
+ } catch (InstantiationException e) {
+ msg = "Couldn't instantiate " + c + " : " + e;
+ } catch (IllegalAccessException e) {
+ msg = "Couldn't instantiate " + c + " : " + e;
+ } catch (InvocationTargetException e) {
+ msg = "Problem during instantiation of " + c + " : " + e.getTargetException();
+ }
+ }
+
+ if (msg != null) {
+ System.err.println(msg);
+ throw new IOException(msg);
+ }
+ return packet;
+ }
+
+ protected void writePacket(AbstractPacket packet) throws IOException {
+ out.writeUTF(packet.getClass().getName());
+ packet.writeContent(out);
+ // System.out.println(Thread.currentThread().getName() + "-SENT-----: " + packet);
+ }
+
+ // ********************************************************* private methods
+
+ private void establishReaderAndWriter() throws IOException {
+ out = new DataOutputStream(socket.getOutputStream());
+ in = new DataInputStream(socket.getInputStream());
+
+ // start receiver and sender in extra threads
+ receiver = PacketReceiver.newPacketReceiver(this);
+ sender = PacketSender.newPacketSender(this);
+
+ }
+
+ private boolean writeHandshake() throws IOException {
+ AbstractPacket packet = new HandshakePacket();
+ sendPacket(packet);
+ return listenForPacket(HandshakePacket.class).getClass().equals(HandshakePacket.class);
+ }
+
+ private void replyHandshake() throws IOException {
+ if (listenForPacket(HandshakePacket.class).getClass().equals(HandshakePacket.class))
+ sendPacket(new HandshakePacket());
+ else
+ throw new IOException("handshake failed");
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketReceiver.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketReceiver.java
new file mode 100644
index 0000000..e47c6b0
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketReceiver.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.ArrayList;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.AbstractPacket;
+
+/**
+ * This Runnable listens for incoming packets asynchroniously and keeps them, until they are required by
+ * customers.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class PacketReceiver implements Runnable {
+ private ArrayList<AbstractPacket> receivedPackets;
+
+ private static final Log logger = LogFactory.getLog(PacketReceiver.class);
+
+ private Connection connection;
+
+ private boolean interrupt = false;
+
+ private Exception exception;
+
+ /**
+ * create a new instance and starts the runnable in a new thread
+ *
+ * @param connection the <code>Connection</code> that controls this data receiver.
+ * @return the instance
+ */
+ public static PacketReceiver newPacketReceiver(Connection connection) {
+ PacketReceiver receiver = new PacketReceiver(connection);
+ Thread thread = new Thread(receiver, "PacketReceiver");
+ thread.setDaemon(true);
+ thread.start();
+ return receiver;
+ }
+
+ private PacketReceiver(Connection connection) {
+ this.connection = connection;
+ receivedPackets = new ArrayList<AbstractPacket>();
+ }
+
+ /**
+ * Get a packet of the requested type, wait the specified time until it arrives, if time is negative, wait
+ * until socket will be closed
+ *
+ * @param type the packet type
+ * @param timeToWait until timeout
+ * @return the received packet
+ * @throws InterruptedIOException
+ */
+ public AbstractPacket getPacket(Class<? extends AbstractPacket> type, long timeToWait) throws InterruptedIOException {
+ return getPacket(type, 0, timeToWait);
+ }
+
+ /**
+ * Get a packet of the requested type with a specific id, wait the specified time until it arrives, if time is
+ * negative, wait until socket will be closed
+ *
+ * @param type the packet type
+ * @param refId the id the receiving packet must have
+ * @param timeToWait until timeout
+ * @return the received packet
+ * @throws InterruptedIOException
+ * @throws InterruptedIOException
+ */
+ public AbstractPacket getPacket(Class<? extends AbstractPacket> type, int refId, long timeToWait) throws InterruptedIOException {
+ AbstractPacket packet = null;
+
+ //sync to be able to wait
+ synchronized (receivedPackets) {
+ long remainingTime = timeToWait;
+ long timeBeforeWait;
+
+ // Wait until type is available.
+ while ((packet = popReceivedPacket(type, refId)) == null && connection.isConnected() && !interrupt
+ && (timeToWait < 0 || remainingTime > 0)) {
+ timeBeforeWait = System.currentTimeMillis();
+ try {
+ waitForPacketAvailable(remainingTime);
+ } catch (InterruptedException e) {
+ }
+ if (timeToWait >= 0) {
+ remainingTime -= System.currentTimeMillis() - timeBeforeWait;
+ }
+ }
+ }
+ checkForException(packet);
+ return packet;
+ }
+
+ private void close() {
+ interrupt = true;
+ synchronized (receivedPackets) {
+ receivedPackets.notifyAll();
+ }
+ }
+
+ private void waitForPacketAvailable(long timeToWait) throws InterruptedException {
+ if (timeToWait == 0)
+ return;
+ else if (timeToWait < 0) {
+ receivedPackets.wait();
+ } else {
+ receivedPackets.wait(timeToWait);
+ }
+ }
+
+ /**
+ * Returns the first packet of the specified type and removes from the packet list.
+ */
+ private synchronized AbstractPacket popReceivedPacket(Class<? extends AbstractPacket> type, int refId) {
+ for (AbstractPacket packet : receivedPackets) {
+ if (!type.isInstance(packet) || (refId != 0 && packet.refId != refId))
+ continue;
+ receivedPackets.remove(packet);
+ return packet;
+ }
+ return null;
+ }
+
+ private void checkForException(AbstractPacket packet) throws InterruptedIOException {
+ if (packet != null)
+ return;
+ if (exception != null && !(exception instanceof IOException))
+ // print stack trace if it is not an IOException
+ logger.error(exception.getMessage(), exception);
+ if (interrupt)
+ throw new InterruptedIOException("packet receiver is going to close");
+ if (exception != null)
+ throw new InterruptedIOException(exception.getMessage());
+ throw new InterruptedIOException("timeout reading a packet");
+ }
+
+ // ******************************************************** runnable methods
+
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ try {
+ while (!interrupt && connection.isConnected()) {
+ readAvailablePacket();
+ }
+ } catch (Exception e) {
+ exception = e;
+ close();
+ }
+ }
+
+ private void readAvailablePacket() throws IOException {
+ addPacketToList(connection.readPacket());
+ }
+
+ private void addPacketToList(AbstractPacket packet) {
+ synchronized (receivedPackets) {
+ receivedPackets.add(packet);
+ receivedPackets.notifyAll();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketSender.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketSender.java
new file mode 100644
index 0000000..397b823
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/PacketSender.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.ArrayList;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.AbstractPacket;
+
+/**
+ * This Runnable sends packets out asynchroniously as they arrive from customers.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class PacketSender implements Runnable {
+
+ private ArrayList<AbstractPacket> outgoingPackets;
+
+ private static final Log logger = LogFactory.getLog(PacketSender.class);
+
+ private Connection connection;
+
+ private boolean interrupt = false;
+
+ /**
+ * create a new instance and starts the runnable in a new thread
+ *
+ * @param connection the <code>Connection</code> that controls this data receiver.
+ * @return the instance
+ */
+ public static PacketSender newPacketSender(Connection connection) {
+ PacketSender sender = new PacketSender(connection);
+ Thread thread = new Thread(sender, "PacketSender");
+ thread.setDaemon(true);
+ thread.start();
+ return sender;
+ }
+
+ private PacketSender(Connection connection) {
+ this.connection = connection;
+ outgoingPackets = new ArrayList<AbstractPacket>();
+ }
+
+ /**
+ * Add a packet to be sent to the other side.
+ *
+ * @param packet the packet
+ * @return the packet id after it was sent
+ * @throws InterruptedIOException
+ */
+ public int sendPacket(AbstractPacket packet) throws InterruptedIOException {
+ if (!connection.isConnected())
+ throw new InterruptedIOException();
+ // log.debug("send: " + packet);
+
+ synchronized (outgoingPackets) {
+ outgoingPackets.add(packet);
+ outgoingPackets.notifyAll();
+ }
+ return packet.getId();
+ }
+
+ /**
+ * stop the sender thread.
+ */
+ public void close() {
+ interrupt = true;
+ synchronized (outgoingPackets) {
+ outgoingPackets.notifyAll();
+ }
+ }
+
+ // ******************************************************** runnable methods
+
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ while (!interrupt && connection.isConnected())
+ try {
+ sendAvailablePackets();
+ } catch (Exception e) {
+ if (!(e instanceof IOException))
+ logger.error(e.getMessage(), e);
+ interrupt = true;
+ }
+ connection.close();
+ }
+
+ private void sendAvailablePackets() throws IOException {
+ ArrayList<AbstractPacket> packetsToSend = new ArrayList<AbstractPacket>();
+ synchronized (outgoingPackets) {
+ while (!interrupt && outgoingPackets.isEmpty()) {
+ try {
+ outgoingPackets.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ packetsToSend.addAll(outgoingPackets);
+ outgoingPackets.clear();
+ }
+
+ for (AbstractPacket packet : packetsToSend) {
+ connection.writePacket(packet);
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/AbstractPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/AbstractPacket.java
new file mode 100644
index 0000000..a09e94d
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/AbstractPacket.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * The base class for all types of packets. It has the id and refId. Inheriting classes must call setNextId to get
+ * a valid id.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public abstract class AbstractPacket {
+ protected int id;
+
+ public int refId;
+
+ private static int nextId = 0;
+
+ // -------------------------------------------------------------------------
+
+ public int getId() {
+ return id;
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * fill the packet fields from the <code>DataInputStream</code>. Implementors have to make sure that the
+ * data content matches with the writeContent(out) method!!
+ *
+ * @param in the DataInputStream
+ * @throws IOException
+ */
+ public abstract void readContent(DataInputStream in) throws IOException;
+
+ /**
+ * write the packet fields content to the <code>DataOutputStream</code>. Implementors have to make sure
+ * that the data content matches with the readContent(out) method!!
+ *
+ * @param out the DataOutputStream
+ * @throws IOException
+ */
+ public abstract void writeContent(DataOutputStream out) throws IOException;
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(getClass().getSimpleName() + " ");
+ if (id != 0)
+ sb.append(" id=" + id);
+ if (refId != 0)
+ sb.append(" refId=" + refId);
+ return sb.toString();
+ }
+
+ // -------------------------------------------------------------------------
+
+ protected void setNextId() {
+ if (nextId == Integer.MAX_VALUE)
+ nextId = 1;
+ else
+ id = ++nextId;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/BreakpointPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/BreakpointPacket.java
new file mode 100644
index 0000000..c5ff12c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/BreakpointPacket.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+
+/**
+ * The packet to communicate set and delete of breakpoints.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class BreakpointPacket extends AbstractPacket {
+
+ public int type;
+
+ public SyntaxElement se;
+
+ // -------------------------------------------------------------------------
+
+ public BreakpointPacket(int type, SyntaxElement se) {
+ super();
+ this.type = type;
+ this.se = se;
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ type = in.readInt();
+ se = new SyntaxElement();
+ se.readContent(in);
+
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(type);
+ se.writeContent(out);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " type=" + type + " resource=" + se.resource + " line=" + se.line;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/CommandPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/CommandPacket.java
new file mode 100644
index 0000000..679dfc3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/CommandPacket.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * The packet to communicate a process or direct command to the runtime process.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class CommandPacket extends AbstractPacket {
+
+ public int command;
+
+ // -------------------------------------------------------------------------
+
+ public CommandPacket(int command) {
+ this.command = command;
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ command = in.readInt();
+
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(command);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " type=" + command;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/ConfirmationPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/ConfirmationPacket.java
new file mode 100644
index 0000000..15d314b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/ConfirmationPacket.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * The packet to communicate the confirmation of a specific packet reference id.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class ConfirmationPacket extends AbstractPacket {
+
+ // -------------------------------------------------------------------------
+
+ public ConfirmationPacket(int packId) {
+ refId = packId;
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ refId = in.readInt();
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(refId);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacket.java
new file mode 100644
index 0000000..f50bc55
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacket.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * The packet to communicate an event from the runtime process.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class EventPacket extends AbstractPacket {
+
+ public int event;
+
+ // -------------------------------------------------------------------------
+
+ public EventPacket(int event) {
+ this.event = event;
+ setNextId();
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ id = in.readInt();
+ event = in.readInt();
+
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(id);
+ out.writeInt(event);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " event=" + event;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacketWithFrames.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacketWithFrames.java
new file mode 100644
index 0000000..394d34f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/EventPacketWithFrames.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+
+/**
+ * The packet to communicate an event from the runtime process together with the current stack frame information.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class EventPacketWithFrames extends EventPacket {
+
+ public int cleanStackLevel;
+
+ public List<SyntaxElement> frames = new ArrayList<SyntaxElement>();
+
+ // -------------------------------------------------------------------------
+
+ public EventPacketWithFrames(int event) {
+ super(event);
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ super.readContent(in);
+ cleanStackLevel = in.readInt();
+ int noOfFrames = in.readInt();
+ for (int i = 0; i < noOfFrames; i++) {
+ SyntaxElement frame = new SyntaxElement();
+ frame.readContent(in);
+ frames.add(frame);
+ }
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ super.writeContent(out);
+ out.writeInt(cleanStackLevel);
+ out.writeInt(frames.size());
+ for (SyntaxElement frame : frames)
+ frame.writeContent(out);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(super.toString() + " ");
+ sb.append(" clean=" + cleanStackLevel);
+ sb.append(" " + frames.size() + " frames");
+ return sb.toString();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/HandshakePacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/HandshakePacket.java
new file mode 100644
index 0000000..4250a98
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/HandshakePacket.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * The packet to communicate a first handshake. There are no data to be communicated.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class HandshakePacket extends AbstractPacket {
+
+ @Override
+ public void readContent(DataInputStream in) {
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) {
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RegisterPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RegisterPacket.java
new file mode 100644
index 0000000..6871c08
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RegisterPacket.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The packet to communicate handlers or adapter class names to be registered in the runtime process.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class RegisterPacket extends AbstractPacket {
+
+ public static final int HANDLERS = 1;
+
+ public static final int ADAPTERS = 2;
+
+ public int type;
+
+ public List<String> classNames = new ArrayList<String>();
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ type = in.readInt();
+ int noOfHandlers = in.readInt();
+ for (int i = 0; i < noOfHandlers; i++)
+ classNames.add(in.readUTF());
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(type);
+ out.writeInt(classNames.size());
+ for (String name : classNames)
+ out.writeUTF(name);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " type=" + type + " " + classNames;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RequireVarPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RequireVarPacket.java
new file mode 100644
index 0000000..21920e6
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/RequireVarPacket.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * The packet to communicate a request for variable from a specific frame and variable id.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class RequireVarPacket extends AbstractPacket {
+
+ public int frameId;
+
+ public int varId;
+
+ // -------------------------------------------------------------------------
+
+ public RequireVarPacket(int frameId, int varId) {
+ setNextId();
+ this.frameId = frameId;
+ this.varId = varId;
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ id = in.readInt();
+ frameId = in.readInt();
+ varId = in.readInt();
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(id);
+ out.writeInt(frameId);
+ out.writeInt(varId);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " frameId=" + frameId + (varId != 0 ? " varId=" + varId : "");
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/VarDataPacket.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/VarDataPacket.java
new file mode 100644
index 0000000..1b9e487
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/communication/packets/VarDataPacket.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.communication.packets;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+
+/**
+ * The packet to communicate variable values for a specific reference id. Corresponds with
+ * <code>RequireVarPacket</code>.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class VarDataPacket extends AbstractPacket {
+
+ public List<VarValueTO> valueList = new ArrayList<VarValueTO>();
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void readContent(DataInputStream in) throws IOException {
+ refId = in.readInt();
+ int noOfValues = in.readInt();
+ for (int i = 0; i < noOfValues; i++) {
+ VarValueTO var = new VarValueTO();
+ var.readContent(in);
+ valueList.add(var);
+ }
+ }
+
+ @Override
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeInt(refId);
+ out.writeInt(valueList.size());
+ for (VarValueTO var : valueList)
+ var.writeContent(out);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(super.toString() + " [");
+ for (VarValueTO var : valueList)
+ sb.append(var.name + " ");
+ sb.append("]");
+ return sb.toString();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/NameValuePair.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/NameValuePair.java
new file mode 100644
index 0000000..ee46588
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/NameValuePair.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.model;
+
+/**
+ * name / value utility class
+ */
+public class NameValuePair {
+ public String name;
+
+ public Object value;
+
+ public NameValuePair(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return name + " = " + value.toString();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValue.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValue.java
new file mode 100644
index 0000000..dd7aa4a
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValue.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A wrapper class for caching of variable values together with a specific id and remember where this value is
+ * used and which member valuess it has.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class VarValue {
+
+ public int id;
+
+ public Object element;
+
+ public Set<VarValue> usedIn = new HashSet<VarValue>();
+
+ public Set<VarValue> members = new HashSet<VarValue>();
+
+ // -------------------------------------------------------------------------
+
+ public VarValue(Object element, int id) {
+ this.element = element;
+ this.id = id;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValueTO.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValueTO.java
new file mode 100644
index 0000000..e6c7c2e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/model/VarValueTO.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.model;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Transfer object class for variable description in a normalized form.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class VarValueTO {
+
+ public String name;
+
+ public int valueId;
+
+ public String stringRep;
+
+ public String simpleRep;
+
+ public boolean hasMembers;
+
+ // -------------------------------------------------------------------------
+
+ public VarValueTO() {
+ }
+
+ public VarValueTO(String name) {
+ this.name = name;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void writeContent(DataOutputStream out) throws IOException {
+ out.writeUTF(name);
+ out.writeInt(valueId);
+ out.writeUTF(stringRep);
+ if (simpleRep == null) {
+ System.out.println("simpleRep of " + stringRep + " is null.");
+// simpleRep = "null";
+ }
+ out.writeUTF(simpleRep);
+ out.writeBoolean(hasMembers);
+ }
+
+ public void readContent(DataInputStream in) throws IOException {
+ name = in.readUTF();
+ valueId = in.readInt();
+ stringRep = in.readUTF();
+ simpleRep = in.readUTF();
+ hasMembers = in.readBoolean();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/ReflectionUtil.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/ReflectionUtil.java
new file mode 100644
index 0000000..436f826
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/ReflectionUtil.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.mwe;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Provides static helper methods to deal with element fields using reflection.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class ReflectionUtil {
+
+ private static final Map<String, Map<String, Field>> fieldDictionary = new HashMap<String, Map<String, Field>>();
+
+ // -------------------------------------------------------------------------
+
+ private ReflectionUtil() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * return a String representation of the element. It is "null", the content of a String or the simple class
+ * name for all other types.<br>
+ * Hint: Primitives wrapper classes are not handled specially, so the result is not the primitive value but
+ * the class name. But since getFieldValue(..) returns a String representation of primitives, this should not
+ * be a problem here.
+ *
+ * @param element the element
+ * @return the string representation
+ */
+ public static String getSimpleName(Object element) {
+ return (element == null ? "null" : (element instanceof String) ? (String) element : getSimpleClassName(element));
+ }
+
+ /**
+ * Null save toString
+ * @param element the element
+ * @return the string representation
+ */
+ public static String getNameToString(Object element) {
+ return (element == null ? "null" : element.toString());
+ }
+
+ /**
+ * check if the element has member fields. For an array it checks if it is not empty.
+ *
+ * @param element the element
+ * @return yes or no
+ */
+ public static boolean checkFields(Object element) {
+ if (element == null || element instanceof String)
+ return false;
+ if (Object[].class.isAssignableFrom(element.getClass()))
+ return ((Object[]) element).length > 0;
+ Map<String, Field> fields = getFieldMap(element.getClass());
+ return !fields.isEmpty();
+ }
+
+ /**
+ * returns a list of names of the fields. For an array it returns "[i]" as name where i is the position in the
+ * array.
+ *
+ * @param element
+ * @return
+ */
+ public static List<String> getFieldNames(Object element) {
+ List<String> result = new ArrayList<String>();
+ if (element instanceof Object[])
+ for (int i = 0; i < ((Object[]) element).length; i++)
+ result.add("[" + i + "]");
+ else
+ result.addAll(getFieldMap(element.getClass()).keySet());
+ return result;
+ }
+
+ /**
+ * Returns the value of a field of an object.<br>
+ * For primitives it returns a string representation.<br>
+ * It returns null in case of any exceptions.
+ *
+ * @param object the questioned object
+ * @param name the name of the field
+ * @return the value
+ */
+ public static Object getFieldValue(Object object, String name) {
+ try {
+ Field field = getField(object, name);
+ Class<?> type = field.getType();
+ if (type.isPrimitive() || (type == String.class))
+ return field.get(object).toString();
+ return field.get(object);
+ } catch (Exception e) {
+ // IllegalAccessException and NullPointerException
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+
+ // similar to getClass().getSimpleName(), but handles arrays differently
+ private static String getSimpleClassName(Object element) {
+ String fqn = element.getClass().getName();
+ int index = fqn.lastIndexOf('.');
+ if (element instanceof Object[])
+ return fqn.substring(index + 1, fqn.length() - 1) + "[" + ((Object[]) element).length + "]";
+ return fqn.substring(index + 1);
+ }
+
+ private static Field getField(Object object, String name) {
+ try {
+ return getFieldMap(object.getClass()).get(name);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ // collect all declared fields (also private and static) of a class and it's super classes
+ // cache the map by class for multiple use.
+ private static synchronized Map<String, Field> getFieldMap(final Class<?> cls) {
+ final String clsName = cls.getName();
+ if (!fieldDictionary.containsKey(clsName)) {
+ final Map<String, Field> fieldMap = new HashMap<String, Field>();
+ Class<?> clazz = cls;
+ while (!Object.class.equals(clazz)) {
+ Field[] fields = cls.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ Field field = fields[i];
+ field.setAccessible(true);
+ // super class fields are not considered if the same name was already in an inheriting class
+ if (!fieldMap.containsKey(field.getName()))
+ fieldMap.put(field.getName(), field);
+ }
+ clazz = clazz.getSuperclass();
+ }
+ fieldDictionary.put(clsName, fieldMap);
+ }
+ return fieldDictionary.get(clsName);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/WorkflowElementAdapter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/WorkflowElementAdapter.java
new file mode 100644
index 0000000..c2ea809
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/mwe/WorkflowElementAdapter.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.mwe;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.core.WorkflowContext;
+import org.eclipse.emf.mwe.core.container.CompositeComponent;
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.ast.parser.XmlLocationAnalyser;
+import org.eclipse.emf.mwe.internal.core.debug.model.NameValuePair;
+import org.eclipse.emf.mwe.internal.core.util.ComponentPrinter;
+
+/**
+ * The IElementAdapter implementation for WorkflowComponents.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class WorkflowElementAdapter implements ElementAdapter {
+
+ public static final String TYPE = "workflow";
+
+ private Object context;
+
+ private CompositeComponent root;
+
+ private XmlLocationAnalyser locationAnalyser;
+
+ // -------------------------------------------------------------------------
+
+ public WorkflowElementAdapter() {
+ this.locationAnalyser = new XmlLocationAnalyser();
+ }
+
+ // -------------------------------------------------------------------------
+
+ public Object getContext() {
+ return context;
+ }
+
+ public void setContext(Object context) {
+ this.context = context;
+ }
+
+ public String getAdapterType() {
+ return TYPE;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public boolean canHandle(Object element) {
+ if (element instanceof WorkflowComponent) {
+ if (root == null)
+ root = ((WorkflowComponent) element).getContainer();
+ return true;
+ }
+ if (element instanceof SyntaxElement) {
+ SyntaxElement se = (SyntaxElement) element;
+ String resource = se.resource;
+ return resource.endsWith(".mwe") || resource.endsWith(".oaw");
+ }
+ return false;
+ }
+
+ public boolean shallHandle(Object element) {
+ // no special treatment for workflow components
+ return true;
+ }
+
+ public boolean shallSuspend(Object element, int flag) {
+ // no special treatment for workflow components
+ return true;
+ }
+
+ public boolean isSurroundingElement(Object element) {
+ return CompositeComponent.class.isAssignableFrom(element.getClass());
+ }
+
+ public SyntaxElement createElementTO(Object element) {
+ WorkflowComponent comp = (WorkflowComponent) element;
+ SyntaxElement se = new SyntaxElement();
+ Location loc = comp.getLocation();
+ loc = initialize(loc);
+
+ se.containerName = ComponentPrinter.getContainerName(comp);
+ se.elementName = ComponentPrinter.getElementName(comp);
+ se.resource = loc.getResource();
+ se.start = loc.getNameStart();
+ se.end = loc.getNameEnd();
+ se.line = loc.getLineNumber();
+ return se;
+ }
+
+ public SyntaxElement createEndElementTO(Object element) {
+ CompositeComponent comp = (CompositeComponent) element;
+ SyntaxElement se = new SyntaxElement();
+ Location loc = comp.getOwnLocation();
+ if (loc == null)
+ // for root
+ loc = comp.getLocation();
+ loc = initializeEndLocation(loc);
+ se.containerName = ComponentPrinter.getElementName(comp);
+ se.elementName = "end of cartridge";
+ if (loc != null) {
+ se.resource = loc.getResource();
+ se.start = loc.getNameStart();
+ se.end = loc.getNameEnd();
+ se.line = loc.getLineNumber();
+ }
+ return se;
+ }
+
+ public List<NameValuePair> getVariables(Object element) {
+ List<NameValuePair> list = new ArrayList<NameValuePair>();
+
+ if (element instanceof WorkflowComponent) {
+ // TODO: ER: show Variables, that are workflow properties
+ // Note: only the available slot variables are shown
+ // internal variables of the WfComponent are neither visible before start nor after end of invocation
+ // that's why we don't check the element itself
+ WorkflowContext ctx = (WorkflowContext) context;
+ for (String name : ctx.getSlotNames()) {
+ list.add(new NameValuePair(name, ctx.get(name)));
+ }
+ } else {
+ int i = 0;
+ for (String name : ReflectionUtil.getFieldNames(element)) {
+ Object childElement;
+ // ReflectionUtil returns a name format "[" + i + "]" for arrays, therefore we can't use name here
+ if (element instanceof Object[])
+ childElement = ((Object[]) element)[i++];
+ else
+ childElement = ReflectionUtil.getFieldValue(element, name);
+ list.add(new NameValuePair(name, childElement));
+ }
+ }
+ return list;
+ }
+
+ public String getVariableDetailRep(Object element) {
+ return ReflectionUtil.getNameToString(element);
+ }
+
+ public String getVariableSimpleRep(Object element) {
+ return ReflectionUtil.getSimpleName(element);
+ }
+
+ public boolean checkVariableHasMembers(Object element) {
+ return ReflectionUtil.checkFields(element);
+ }
+
+ public Object findElement(SyntaxElement se, Object actual, int flag) {
+ if (root == null)
+ return null;
+ return findComponent(root, se.resource, se.line);
+ }
+
+ private Object findComponent(CompositeComponent parent, String resource, int lineNo) {
+ Location loc = parent.getOwnLocation();
+ if (loc == null)
+ loc = parent.getLocation();
+ if (resource.endsWith(loc.getResource()))
+ for (WorkflowComponent comp : parent.getComponents())
+ if (comp.getLocation().getLineNumber() == lineNo)
+ return comp;
+ for (WorkflowComponent comp : parent.getComponents())
+ if (comp instanceof CompositeComponent) {
+ CompositeComponent child = (CompositeComponent) comp;
+ Object found = findComponent(child, resource, lineNo);
+ if (found != null)
+ return found;
+ }
+ return null;
+ }
+
+ private Location initialize(Location loc) {
+ if (loc.getResource() == null)
+ return null;
+ return locationAnalyser.adapt(loc);
+ }
+
+ private Location initializeEndLocation(Location loc) {
+ if (loc.getResource() == null)
+ return null;
+ return locationAnalyser.adaptEnd(loc);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/CommandListener.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/CommandListener.java
new file mode 100644
index 0000000..9bacfff
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/CommandListener.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import java.io.IOException;
+
+/**
+ * Interface to listen for regular process commands from the debug server (e.g. eclipse).
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface CommandListener {
+
+ /**
+ * listen for the next regular process command. This method could be a long running one that waits until the
+ * user starts the next debug action.
+ *
+ * @throws IOException
+ */
+ public void listenCommand() throws IOException;
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebugMonitor.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebugMonitor.java
new file mode 100644
index 0000000..775bd9c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebugMonitor.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import static org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler.END_FRAME;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler.NORMAL_FRAME;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler.INTERRUPT;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler.POP;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler.PUSH;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler.SHALL_HANDLE;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler.SUSPEND;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.core.monitor.ProgressMonitor;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+
+/**
+ * The heart of the debug process on the runtime side. It has callback methods that are called by the syntax
+ * element implementations before and after a process step.<br>
+ * It works closely together with handlers and adapters that must be registered at startup.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugMonitor implements ProgressMonitor {
+
+ private static final int STARTED = 1;
+
+ private static final int PRE_TASK = 2;
+
+ private static final int POST_TASK = 3;
+
+ private static final int SUSPENDED = 4;
+
+ private static final int RESUMED = 5;
+
+ private static final int TERMINATED = 6;
+
+ private Connection connection = new Connection();
+
+ private CommandListener commandListener;
+
+ private Set<ProcessHandler> processHandlers = new HashSet<ProcessHandler>();
+
+ private Set<EventHandler> eventHandlers = new HashSet<EventHandler>();
+
+ private Set<ElementAdapter> elementAdapters = new HashSet<ElementAdapter>();
+
+ private boolean missingAdapterReported;
+
+ private Object context;
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * open the connection to a debug server framework (e.g. eclipse) and instantiate and start the
+ * RuntimeHandlerManager listener.
+ *
+ * @param args arg[1] must be the port to be connected with
+ * @throws IOException
+ */
+ public void init(String[] args) throws IOException {
+ // args[0] is the class name
+ int port = new Integer(args[1]);
+ try {
+ connection.connect(port);
+ } catch (ConnectException e) {
+ throw new IOException("Couldn't establish connection to Debugger on port " + port);
+ }
+ try {
+ RuntimeHandlerManager handler = new RuntimeHandlerManager(this);
+ handler.setConnection(connection);
+ handler.startListener();
+ } catch (Exception e) {
+ connection.close();
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ throw (IOException) e;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void setCommandListener(CommandListener commandListener) {
+ this.commandListener = commandListener;
+ }
+
+ public void addProcessHandler(ProcessHandler handler) {
+ processHandlers.add(handler);
+ }
+
+ public void addEventHandler(EventHandler handler) {
+ eventHandlers.add(handler);
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void addAdapter(ElementAdapter adapter) {
+ elementAdapters.add(adapter);
+ }
+
+ public ElementAdapter getAdapter(Object element) {
+ for (ElementAdapter adapter : elementAdapters)
+ if (adapter.canHandle(element))
+ return adapter;
+ if (!missingAdapterReported) {
+ System.out.println("Warning: Element can't be debugged.\nDidn't find an adapter for element of type "
+ + element.getClass().getSimpleName());
+ missingAdapterReported = true;
+ }
+ return null;
+ }
+
+ // ------------------------------------- methods called from the mwe process
+
+ /**
+ * fire the STARTED event to the registered event handlers
+ *
+ * @see org.eclipse.emf.mwe.core.monitor.ProgressMonitor#started(java.lang.Object, java.lang.Object)
+ */
+ public void started(Object element, Object context) {
+ fireEvent(STARTED);
+ }
+
+ /**
+ * the main method to manipulate the runtime process for debugging.<br>
+ * In case a suspension is requested it stops the process and waits for the next user command.
+ *
+ * @see org.eclipse.emf.mwe.core.monitor.ProgressMonitor#preTask(java.lang.Object, java.lang.Object)
+ */
+ public void preTask(Object element, Object context) {
+ this.context = context;
+ ElementAdapter adapter = getAdapter(element);
+ if (adapter == null)
+ return;
+ adapter.setContext(context);
+
+ if (!ask(SHALL_HANDLE, element, PUSH))
+ return;
+
+ fireEvent(PRE_TASK, element, NORMAL_FRAME);
+ checkInterrupt();
+
+ try {
+ if (ask(SUSPEND, element, NORMAL_FRAME)) {
+ fireEvent(SUSPENDED);
+ commandListener.listenCommand();
+ checkInterrupt();
+ fireEvent(RESUMED);
+ }
+ } catch (IOException e) {
+ throw new DebuggerInterruptedException("User interrupt");
+ }
+ }
+
+ /**
+ * inform the handlers about the finalization of a process step.<br>
+ * In case the process may suspend at the end of a syntax element it does so if requested.
+ *
+ * @see org.eclipse.emf.mwe.core.monitor.ProgressMonitor#postTask(java.lang.Object, java.lang.Object)
+ */
+ public void postTask(Object element, Object context) {
+ this.context = context;
+ ElementAdapter adapter = getAdapter(element);
+ if (adapter == null)
+ return;
+ adapter.setContext(context);
+
+ if (!ask(SHALL_HANDLE, element, POP))
+ return;
+
+ try {
+ if (adapter.isSurroundingElement(element))
+ if (ask(SUSPEND, element, END_FRAME)) {
+ // if we are at the end of a "subroutine" and going to stop at the next lower level task
+ // anyway
+ // we add another "frame" here to stop again at the closing syntax element
+ // this enables us to check variable values before closing the frame
+ fireEvent(PRE_TASK, element, END_FRAME);
+ fireEvent(SUSPENDED);
+ commandListener.listenCommand();
+ fireEvent(RESUMED);
+ fireEvent(POST_TASK);
+ }
+ fireEvent(POST_TASK);
+ } catch (IOException e) {
+ throw new DebuggerInterruptedException(e);
+ }
+ }
+
+ /**
+ * fire the finish events to the registered event handlers
+ *
+ * @see org.eclipse.emf.mwe.core.monitor.ProgressMonitor#finished(java.lang.Object, java.lang.Object)
+ */
+ public void finished(Object element, Object context) {
+ getAdapter(element).setContext(context);
+ fireEvent(PRE_TASK, element, END_FRAME);
+ fireEvent(SUSPENDED);
+ fireEvent(POST_TASK);
+ fireEvent(TERMINATED);
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void checkInterrupt() {
+ if (ask(INTERRUPT, null, 0))
+ // we throw an exception since the preTask() method is called
+ // iteratively and we want to come back to the most outer loop
+ throw new DebuggerInterruptedException("User interrupt");
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void fireEvent(int event) {
+ fireEvent(event, null, 0);
+ }
+
+ private void fireEvent(int event, Object element, int state) {
+ for (EventHandler handler : eventHandlers) {
+ try {
+ if (event == PRE_TASK)
+ handler.preTask(element, context, state);
+ else if (event == POST_TASK)
+ handler.postTask(context);
+ else if (event == STARTED)
+ handler.started();
+ else if (event == SUSPENDED)
+ handler.suspended();
+ else if (event == RESUMED)
+ handler.resumed();
+ else if (event == TERMINATED)
+ handler.terminated();
+ } catch (IOException e) {
+ throw new DebuggerInterruptedException(e);
+ }
+ }
+ }
+
+ private boolean ask(int event, Object element, int state) {
+ boolean result = false;
+ ProcessHandler lastHandler = null;
+
+ for (ProcessHandler handler : processHandlers)
+ if (handler.isLastCall())
+ lastHandler = handler;
+ else
+ result = ask(event, element, state, result, handler);
+ if(lastHandler != null)
+ result = ask(event, element, state, result, lastHandler);
+ return result;
+ }
+
+ private boolean ask(int event, Object element, int state, boolean lastState, ProcessHandler handler) {
+ boolean result = lastState;
+ if (event == SHALL_HANDLE)
+ result = handler.shallHandle(result, element, state);
+ else if (event == SUSPEND)
+ result = handler.shallSuspend(result, element, state);
+ else if (event == INTERRUPT)
+ result = handler.shallInterrupt(result);
+ return result;
+ }
+
+ // ************************** unused Progress Monitor implementation methods
+
+ public void beginTask(String name, int totalWork) {
+ //
+ }
+
+ public void done() {
+ //
+ }
+
+ public void internalWorked(double work) {
+ //
+ }
+
+ public boolean isCanceled() {
+ return false;
+ }
+
+ public void setCanceled(boolean value) {
+ //
+ }
+
+ public void setTaskName(String name) {
+ //
+ }
+
+ public void subTask(String name) {
+ //
+ }
+
+ public void worked(int work) {
+ //
+ }
+
+ public void clearBlocked() {
+ //
+ }
+
+ public void setBlocked(Diagnostic reason) {
+ //
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebuggerInterruptedException.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebuggerInterruptedException.java
new file mode 100644
index 0000000..7c60723
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/DebuggerInterruptedException.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import java.io.IOException;
+
+/**
+ * A RuntimeException that is thrown when an exception is thrown during debugging or if the user terminates the
+ * process
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebuggerInterruptedException extends RuntimeException {
+
+ private static final long serialVersionUID = 8297242905634686930L;
+
+ public DebuggerInterruptedException(IOException e) {
+ super(e);
+ }
+
+ public DebuggerInterruptedException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/EventHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/EventHandler.java
new file mode 100644
index 0000000..9472bc5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/EventHandler.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import java.io.IOException;
+
+/**
+ * Interface to handle events from the <code>DebugMonitor</code>.<br>
+ * See DebugMonitor to understand when an event is fired.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface EventHandler {
+
+ public static final int NORMAL_FRAME = 1;
+
+ public static final int END_FRAME = 2;
+
+ public void started() throws IOException;
+
+ public void preTask(Object element, Object context, int state) throws IOException;
+
+ public void postTask(Object context) throws IOException;
+
+ public void suspended() throws IOException;
+
+ public void resumed() throws IOException;
+
+ public void terminated() throws IOException;
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/ProcessHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/ProcessHandler.java
new file mode 100644
index 0000000..2217150
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/ProcessHandler.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+/**
+ * Interface that is used by the DebugMonitor to decide several operational steps.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface ProcessHandler {
+ public static final int SHALL_HANDLE = 1;
+
+ public static final int INTERRUPT = 2;
+
+ public static final int SUSPEND = 3;
+
+ public static final int PUSH = 1;
+
+ public static final int POP = 2;
+
+ /**
+ * define if an element shall be considered or completely ignored for suspension in a debug process.<br>
+ * It should be implemented as a filter. The result shall be AND or OR related with <code>lastState</code>.
+ *
+ * @param lastState the consolidated decisions of previously asked listeners
+ * @param element the element that is questioned
+ * @param flag one of the values <code>IProcessHandler.PUSH</code> or <code>IProcessHandler.POP</code>
+ * @return
+ */
+ public boolean shallHandle(boolean lastState, Object element, int flag);
+
+ /**
+ * define if a debug process shall be suspended for a given element.<br>
+ * It should be implemented as a filter. The result shall be AND or OR related with <code>lastState</code>.
+ *
+ * @param lastState the consolidated decisions of previously asked listeners
+ * @param element the element that is questioned
+ * @param flag one of the values <code>IEventHandler.NORMAL_FRAME</code> or
+ * <code>IEventHandler.END_FRAME</code>
+ * @return if the process shall suspend based on the last state and the evaluation of the current element
+ */
+ public boolean shallSuspend(boolean lastState, Object element, int flag);
+
+ /**
+ * define if the debugger runtime process shall be interrupted
+ *
+ * @param lastState the consolidated decisions of previously asked listeners
+ * @return if the process shall be interrupted based on the last state and the evaluation of the current
+ * element
+ */
+ public boolean shallInterrupt(boolean lastState);
+
+ /**
+ * if true, the handler has the last call and will be processed at the last handler
+ *
+ * @return whether or not
+ */
+ public boolean isLastCall();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandler.java
new file mode 100644
index 0000000..22acc58
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandler.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+
+/**
+ * base interface for handlers that support the debugger runtime process
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface RuntimeHandler {
+
+ /**
+ * initiate the instantiated handler. It gets the <code>DebugMonitor</code> and <code>Connection</code>
+ * instances that may be needed for the handler to do it's work<br>
+ * the handler may be registered at the <code>DebugMonitor</code> dependent on the type of handler.
+ *
+ * @param monitor the DebugMonitor
+ * @param connection the connection to the debugger framework
+ */
+ public void init(DebugMonitor monitor, Connection connection);
+
+ /**
+ * start the listening process in an extra thread, if required
+ */
+ public void startListener();
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandlerManager.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandlerManager.java
new file mode 100644
index 0000000..2bb738c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/RuntimeHandlerManager.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing;
+
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.core.resources.ResourceLoaderFactory;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.RegisterPacket;
+
+/**
+ * This manager class listens for requests from the debug server to instantiate handlers or adapters.<br>
+ * It initiates the handlers and registers adapters at the <code>DebugMonitor</code> instance.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class RuntimeHandlerManager implements Runnable {
+
+ private Connection connection;
+
+ private DebugMonitor monitor;
+
+ private static final Log logger = LogFactory.getLog(RuntimeHandlerManager.class);
+
+ // -------------------------------------------------------------------------
+
+ public RuntimeHandlerManager(DebugMonitor monitor) {
+ this.monitor = monitor;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ /**
+ * start listener thread.
+ */
+ public void startListener() {
+ Thread thread = new Thread(this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ // -------------------------------------------------------------------------
+
+ /* (non-Javadoc)
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ try {
+ while (true) {
+ listenAndRegisterClasses();
+ }
+ } catch (Exception e) {
+ if (!(e instanceof IOException))
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ private void listenAndRegisterClasses() throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException {
+
+ RegisterPacket packet = (RegisterPacket) connection.listenForPacket(RegisterPacket.class);
+
+ String msg = null;
+
+ if (packet.type == RegisterPacket.HANDLERS) {
+ RuntimeHandler handler = null;
+ for (String className : packet.classNames) {
+ final Class<?> clazz = ResourceLoaderFactory.createResourceLoader().loadClass(className);
+ if (clazz == null) {
+ msg = "Couldn't find " + className + " in the class path.";
+ System.err.println(msg);
+ throw new ClassNotFoundException(msg);
+ }
+ handler = (RuntimeHandler) clazz.newInstance();
+ handler.init(monitor, connection);
+ handler.startListener();
+ }
+ } else {
+ ElementAdapter adapter = null;
+ for (String className : packet.classNames) {
+ final Class<?> clazz = ResourceLoaderFactory.createResourceLoader().loadClass(className);
+ if (clazz == null) {
+ msg = "Couldn't find " + className + " in the class path.";
+ System.err.println(msg);
+ throw new ClassNotFoundException(msg);
+ }
+ adapter = (ElementAdapter) clazz.newInstance();
+ monitor.addAdapter(adapter);
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/BreakpointRuntimeHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/BreakpointRuntimeHandler.java
new file mode 100644
index 0000000..62ce486
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/BreakpointRuntimeHandler.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing.handlers;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.BreakpointPacket;
+import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;
+import org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler;
+
+/**
+ * This class handles the communication of Breakpoints on the runtime side. It listens in an extra thread for set
+ * and removal of breakpoints. The <code>DebugMonitor</code> uses this class to suspend the runtime process at
+ * breakpoints.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class BreakpointRuntimeHandler implements RuntimeHandler, ProcessHandler, Runnable {
+
+ public static final int SET = 1;
+
+ public static final int REMOVE = 2;
+
+ protected Connection connection;
+
+ protected DebugMonitor monitor;
+
+ private List<Object> breakpoints = new ArrayList<Object>();
+
+ private List<SyntaxElement> breakpointTOs = new ArrayList<SyntaxElement>();
+
+ private List<SyntaxElement> toBeRemovedTOs = new ArrayList<SyntaxElement>();
+
+ // -------------------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#init(org.openarchitectureware.debug.processing.DebugMonitor,
+ * org.openarchitectureware.debug.communication.Connection)
+ */
+ public void init(DebugMonitor monitor, Connection connection) {
+ this.monitor = monitor;
+ this.connection = connection;
+ if (monitor != null) {
+ monitor.addProcessHandler(this);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#startListener()
+ */
+ public void startListener() {
+ Thread thread = new Thread(this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ try {
+ while (true)
+ listenAndDispatchCommand();
+ } catch (IOException e) {
+ }
+ }
+
+ private void listenAndDispatchCommand() throws IOException {
+ handle((BreakpointPacket) connection.listenForPacket(BreakpointPacket.class));
+ }
+
+ private void handle(BreakpointPacket packet) {
+ switch (packet.type) {
+ case SET:
+ doSet(packet.se, null, 0);
+ break;
+ case REMOVE:
+ doRemove(packet.se, null, 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void doSet(SyntaxElement se, Object actual, int flag) {
+ ElementAdapter adapter = monitor.getAdapter(se);
+ if (adapter == null)
+ return;
+ Object element = adapter.findElement(se, actual, flag);
+ // breakpoints may be set before the syntax element structure is instantiated
+ // in this case we store the SyntaxElementTO and try it again during shallSuspend(...)
+ if (element == null){
+ breakpointTOs.add(se);
+ for (SyntaxElement cand : toBeRemovedTOs)
+ if(se.equalsBP(cand)){
+ toBeRemovedTOs.remove(cand);
+ break;
+ }
+ }else
+ breakpoints.add(element);
+ }
+
+ private void doRemove(SyntaxElement se, Object actual, int flag) {
+ ElementAdapter adapter = monitor.getAdapter(se);
+ if (adapter == null)
+ return;
+ Object element = adapter.findElement(se, actual, flag);
+ if (element == null){
+ toBeRemovedTOs.add(se);
+ for (SyntaxElement cand : breakpointTOs)
+ if(se.equalsBP(cand)){
+ breakpointTOs.remove(cand);
+ break;
+ }
+ }else
+ breakpoints.remove(element);
+ }
+
+ // -------------------------------------------------------------------------
+ // process listener implementation
+
+ public boolean isLastCall() {
+ return false;
+ }
+
+ /**
+ * returns true if a breakpoint is rgeistered for that element
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallSuspend(boolean, java.lang.Object, int)
+ */
+ public boolean shallSuspend(boolean lastState, Object element, int flag) {
+ if (!toBeRemovedTOs.isEmpty()) {
+ List<SyntaxElement> temp = new ArrayList<SyntaxElement>();
+ temp.addAll(toBeRemovedTOs);
+ toBeRemovedTOs.clear();
+ for (SyntaxElement se : temp)
+ doRemove(se, element, flag);
+ }
+ if (!breakpointTOs.isEmpty()) {
+ List<SyntaxElement> temp = new ArrayList<SyntaxElement>();
+ temp.addAll(breakpointTOs);
+ breakpointTOs.clear();
+ for (SyntaxElement se : temp)
+ doSet(se, element, flag);
+ }
+ return lastState || breakpoints.contains(element);
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallHandle(boolean, java.lang.Object, int)
+ */
+ public boolean shallHandle(boolean lastState, Object element, int flag) {
+ return lastState;
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallInterrupt(boolean)
+ */
+ public boolean shallInterrupt(boolean lastState) {
+ return lastState;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/CommandRuntimeHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/CommandRuntimeHandler.java
new file mode 100644
index 0000000..3ce7b9b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/CommandRuntimeHandler.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing.handlers;
+
+import java.io.IOException;
+import java.util.Stack;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.CommandPacket;
+import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;
+import org.eclipse.emf.mwe.internal.core.debug.processing.CommandListener;
+import org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler;
+
+/**
+ * This class handles the communication of debug commands on the runtime side.<br>
+ * It listens in an extra thread for commands and sets state values accordingly.<br>
+ * <br>
+ * The <code>DebugMonitor</code> uses this class to react according to the process state settings when it needs
+ * to.<br>
+ * The <code>ICommandListener</code> and <code>IProcessHandler</code> methods are the active ones that
+ * communicate with the debug server.<br>
+ * The <code>IEventHandler</code> methods react only internally on events.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class CommandRuntimeHandler implements RuntimeHandler, CommandListener, ProcessHandler, EventHandler, Runnable {
+
+ public static final int STEP_INTO = 1;
+
+ public static final int STEP_OVER = 2;
+
+ public static final int STEP_RETURN = 3;
+
+ public static final int RESUME = 4;
+
+ public static final int SUSPEND = 5;
+
+ public static final int TERMINATE = 6;
+
+ private Connection connection;
+
+ private DebugMonitor monitor;
+
+ // -------------------------------------------------------------------------
+
+ private boolean stepping = false;
+
+ private boolean forceSuspend = false;
+
+ private boolean interrupt = false;
+
+ private Stack<Boolean> stackFrames = new Stack<Boolean>();
+
+ private int iterationLevel = 0;
+
+ private int suspendBaseLevel = 1;
+
+ private boolean continueOperation = false;
+
+ private Object[] syncObject = new Object[0];
+
+ // -------------------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#init(org.openarchitectureware.debug.processing.DebugMonitor,
+ * org.openarchitectureware.debug.communication.Connection)
+ */
+ public void init(DebugMonitor monitor, Connection connection) {
+ this.monitor = monitor;
+ this.connection = connection;
+ if (monitor != null) {
+ monitor.setCommandListener(this);
+ monitor.addProcessHandler(this);
+ monitor.addEventHandler(this);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#startListener()
+ */
+ public void startListener() {
+ Thread thread = new Thread(this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ try {
+ while (true) {
+ listenAndDispatchCommand();
+ }
+ } catch (IOException e) {
+ doTerminate();
+ }
+ }
+
+ private void listenAndDispatchCommand() throws IOException {
+ dispatch(((CommandPacket) connection.listenForPacket(CommandPacket.class)).command);
+ }
+
+ private void dispatch(int cmd) {
+ switch (cmd) {
+ case STEP_INTO:
+ case STEP_OVER:
+ case STEP_RETURN:
+ doStep(cmd);
+ break;
+ case RESUME:
+ doResume();
+ break;
+ case TERMINATE:
+ doTerminate();
+ break;
+ case SUSPEND:
+ doSuspend();
+ break;
+ default:
+ break;
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void doStep(int cmd) {
+ stepping = true;
+ switch (cmd) {
+ case STEP_INTO:
+ suspendBaseLevel = iterationLevel + 1;
+ break;
+ case STEP_OVER:
+ suspendBaseLevel = iterationLevel;
+ break;
+ case STEP_RETURN:
+ suspendBaseLevel = iterationLevel - 1;
+ break;
+ }
+ continueDebugger();
+ }
+
+ private void doResume() {
+ stepping = false;
+ continueDebugger();
+ }
+
+ private void doSuspend() {
+ forceSuspend = true;
+ }
+
+ private void doTerminate() {
+ interrupt = true;
+ continueDebugger();
+ }
+
+ // -------------------------------------------------------------------------
+ // IProcessHandler implementation
+
+ /**
+ * the CommandRuntimeHandler shall have the last call
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#isLastCall()
+ */
+ public boolean isLastCall() {
+ return true;
+ }
+
+ /**
+ * ask the suitable element adapter if the element shall be handled. Remember that information for the pop
+ * call.
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallHandle(boolean, java.lang.Object, int)
+ */
+ public boolean shallHandle(boolean lastState, Object element, int flag) {
+ boolean result;
+ if (flag == PUSH) {
+ result = monitor.getAdapter(element).shallHandle(element);
+ stackFrames.push(result);
+ } else
+ // POP
+ result = stackFrames.pop();
+ return lastState || result;
+ }
+
+ /**
+ * return true in case of a user's suspend request or dependend on the current iteration level.
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallSuspend(boolean, java.lang.Object, int)
+ */
+ public boolean shallSuspend(boolean lastState, Object element, int flag) {
+ boolean shallSuspend = lastState || forceSuspend || stepping && (suspendBaseLevel - (flag == NORMAL_FRAME ? 0 : 1) >= iterationLevel);
+ if (!monitor.getAdapter(element).shallSuspend(element, flag) && shallSuspend) {
+ suspendBaseLevel++;
+ return false;
+ }
+ return shallSuspend;
+ }
+
+ /**
+ * return true in case of a user's terminate event or if the socket connection is no longer open
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.ProcessHandler#shallInterrupt(boolean)
+ */
+ public boolean shallInterrupt(boolean lastState) {
+ return lastState || interrupt || !connection.isConnected();
+ }
+
+ // -------------------------------------------------------------------------
+ // IEventHandler implementation
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#started()
+ */
+ public void started() {
+ }
+
+ /**
+ * increment the iteration level
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#preTask(java.lang.Object, int)
+ */
+ public void preTask(Object element, Object context, int state) {
+ iterationLevel++;
+ }
+
+ /**
+ * decrement the iteration level
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#preTask(java.lang.Object, int)
+ */
+ public void postTask(Object context) {
+ iterationLevel--;
+ }
+
+ /**
+ * reset a potential forceSuspend request
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#suspended()
+ */
+ public void suspended() {
+ forceSuspend = false;
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#started()
+ */
+ public void resumed() {
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#started()
+ */
+ public void terminated() {
+ }
+
+ // -------------------------------------------------------------------------
+ // ICommandListener implementation
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.ICommandListener#listenCommand()
+ */
+ public void listenCommand() {
+ if (!continueOperation)
+ synchronized (syncObject) {
+ try {
+ syncObject.wait();
+ } catch (InterruptedException e) {
+ //
+ }
+ }
+ continueOperation = false;
+ }
+
+ // set the continue flag so that the debugMonitor doesn't need to stop if the next command is already there
+ private void continueDebugger() {
+ continueOperation = true;
+ synchronized (syncObject) {
+ syncObject.notifyAll();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/EventRuntimeHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/EventRuntimeHandler.java
new file mode 100644
index 0000000..d7824ff
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/EventRuntimeHandler.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing.handlers;
+
+import java.io.IOException;
+import java.util.Stack;
+
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.ConfirmationPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.EventPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.EventPacketWithFrames;
+import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;
+import org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler;
+
+/**
+ * This class handles the communication of debug events on the runtime side.<br>
+ * It sends them out (together with addition syntax element information, if required).
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class EventRuntimeHandler implements RuntimeHandler, EventHandler {
+ public static final int STARTED = 1;
+
+ public static final int SUSPENDED = 2;
+
+ public static final int RESUMED = 3;
+
+ public static final int TERMINATED = 4;
+
+ private Connection connection;
+
+ private DebugMonitor monitor;
+
+ private Stack<Frame> stackFrames = new Stack<Frame>();
+
+ private int cleanStackLevel = 0;
+
+ // -------------------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#init(org.openarchitectureware.debug.processing.DebugMonitor,
+ * org.openarchitectureware.debug.communication.Connection)
+ */
+ public void init(DebugMonitor monitor, Connection connection) {
+ this.monitor = monitor;
+ this.connection = connection;
+ monitor.addEventHandler(this);
+ }
+
+ /**
+ * no need to listen
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler#startListener()
+ */
+ public void startListener() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Send STARTED event to the debug server
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#started()
+ */
+ public void started() throws IOException {
+ sendEvent(STARTED);
+ }
+
+ /**
+ * Push the element onto the stack
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#preTask(java.lang.Object, int)
+ */
+ public void preTask(Object element, Object context, int state) {
+ stackFrames.push(new Frame(element, context, state));
+ }
+
+ /**
+ * Pop the element from the stack, adjust the cleanStackLevel value if required
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#postTask()
+ */
+ public void postTask(Object context) {
+ if (cleanStackLevel >= stackFrames.size())
+ cleanStackLevel--;
+ stackFrames.pop();
+ }
+
+ /**
+ * Send SUSPENDED event to the debug server together with the number of stack elements that are still the same
+ * (cleanStackLevel) since the last suspend and all new SyntaxElementTOs.<br>
+ * Wait for a confirmation. In the meantime other threads could handle for instance variable requests.
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#suspended()
+ */
+ public void suspended() throws IOException {
+ EventPacketWithFrames event = new EventPacketWithFrames(SUSPENDED);
+ event.cleanStackLevel = cleanStackLevel;
+
+ for (int i = cleanStackLevel; i < stackFrames.size(); i++) {
+ Frame frame = stackFrames.get(i);
+ SyntaxElement to;
+ ElementAdapter adapter = monitor.getAdapter(frame.element);
+ adapter.setContext(frame.context);
+ if (frame.state == NORMAL_FRAME)
+ to = adapter.createElementTO(frame.element);
+ else
+ to = adapter.createEndElementTO(frame.element);
+ to.type = adapter.getAdapterType();
+ to.frameId = i;
+ event.frames.add(to);
+
+ }
+
+ sendAndConfirm(event);
+ cleanStackLevel = stackFrames.size();
+ }
+
+ /**
+ * Send RESUMED event to the debug server
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#resumed()
+ */
+ public void resumed() throws IOException {
+ sendEvent(RESUMED);
+ }
+
+ /**
+ * Send TERMINATED event to the debug server
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#terminated()
+ */
+ public void terminated() throws IOException {
+ sendEvent(TERMINATED);
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void sendEvent(int type) throws IOException {
+ EventPacket event = new EventPacket(type);
+ sendAndConfirm(event);
+ }
+
+ private void sendAndConfirm(EventPacket event) throws IOException {
+ int refId = connection.sendPacket(event);
+ connection.listenForPacket(ConfirmationPacket.class, refId);
+ }
+
+ // -------------------------------------------------------------------------
+ private class Frame {
+ final Object element;
+
+ final int state;
+
+ final Object context;
+
+ private Frame(Object element, Object context, int state) {
+ this.element = element;
+ this.context = context;
+ this.state = state;
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/VariablesRuntimeHandler.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/VariablesRuntimeHandler.java
new file mode 100644
index 0000000..08a7bf7
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/debug/processing/handlers/VariablesRuntimeHandler.java
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.debug.processing.handlers;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+
+import org.eclipse.emf.mwe.core.debug.processing.ElementAdapter;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.RequireVarPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.VarDataPacket;
+import org.eclipse.emf.mwe.internal.core.debug.model.NameValuePair;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValue;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;
+import org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.RuntimeHandler;
+
+/**
+ * This class handles the communication of variable names and values with the debug server.<br>
+ * It caches variable values with it's id and handles also cleanup of this cache if values are no longer used.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class VariablesRuntimeHandler implements RuntimeHandler, EventHandler, Runnable {
+
+ private Connection connection;
+
+ private DebugMonitor monitor;
+
+ private Stack<Frame> stackFrames = new Stack<Frame>();
+
+ private List<VarValue> frameCache = new ArrayList<VarValue>();
+
+ private List<VarValue> varCache = new ArrayList<VarValue>();
+
+ private int nextId = 0;
+
+ // -------------------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#init(org.openarchitectureware.debug.processing.DebugMonitor,
+ * org.openarchitectureware.debug.communication.Connection)
+ */
+ public void init(DebugMonitor monitor, Connection connection) {
+ this.monitor = monitor;
+ this.connection = connection;
+ if (monitor != null)
+ monitor.addEventHandler(this);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.openarchitectureware.debug.processing.IRuntimeHandler#startListener()
+ */
+ public void startListener() {
+ Thread thread = new Thread(this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ try {
+ while (true)
+ handle((RequireVarPacket) connection.listenForPacket(RequireVarPacket.class));
+ } catch (IOException e) {
+ }
+ }
+
+ private void handle(RequireVarPacket packet) throws IOException {
+ List<VarValueTO> values;
+ if (packet.varId == 0)
+ values = getFrameVariables(packet.frameId);
+ else
+ values = getSubVariables(packet.frameId, packet.varId);
+ VarDataPacket varPacket = new VarDataPacket();
+ if (values != null)
+ varPacket.valueList = values;
+ varPacket.refId = packet.getId();
+ connection.sendPacket(varPacket);
+ }
+
+ // In case there is no varId in the request the top level variables will be collected.
+ // It depends on the element adapter, which variables will be reported.
+ // The syntaxElement is also registered in the frameCache to find out later if variable values are still in
+ // use.
+ private List<VarValueTO> getFrameVariables(int frameId) {
+ if (frameId >= stackFrames.size()) {
+ return null;
+ }
+ Frame frame = stackFrames.get(frameId);
+ ElementAdapter adapter = monitor.getAdapter(frame.element);
+ adapter.setContext(frame.context);
+ cleanFramesCache();
+
+ VarValue hostValue = new VarValue(frame.element, 0);
+ frameCache.add(hostValue);
+
+ List<VarValueTO> vars = getVariableTOs(frame.element, hostValue, adapter);
+ return vars;
+ }
+
+ // In case both frameId and varId are delivered the sub variables of to var with the varId will be collected.
+ // The adapter that suits for the element will be used. That means that there can be different variables
+ // delivered because of different adapters for two frames although the underlying java elements are the same.
+ private List<VarValueTO> getSubVariables(int frameId, int varId) {
+ if (stackFrames.size() <= frameId)
+ return null;
+ Frame frame = stackFrames.get(frameId);
+ ElementAdapter adapter = monitor.getAdapter(frame.element);
+ adapter.setContext(frame.context);
+ VarValue value = findVarValueById(varId);
+ if (value == null)
+ return null;
+ return getVariableTOs(value.element, value, adapter);
+ }
+
+ // this method handles both the creation and update of variables
+ // The host element is the syntax element if called from getFrameVariables() or an arbitrary java object when
+ // called from getSubVariables(). It is task of the adapter to handle this correctly.
+ // After all new variable values are collected there is a check for old elements that are no longer members
+ // of the current host element.
+ // If such a "removed" element is no longer used in any other element, it will be also removed from the
+ // cache and can be garbage collected.
+ //
+ private List<VarValueTO> getVariableTOs(Object hostElement, VarValue hostValue, ElementAdapter adapter) {
+ List<VarValueTO> list = new ArrayList<VarValueTO>();
+
+ Set<VarValue> oldMembers = new HashSet<VarValue>();
+ oldMembers.addAll(hostValue.members);
+ hostValue.members.clear();
+
+ for (NameValuePair entry : adapter.getVariables(hostElement)) {
+ String name = entry.name;
+ Object element = entry.value;
+
+ VarValueTO varTO = new VarValueTO(name);
+
+ if (element == null) {
+ varTO.stringRep = "null";
+ varTO.simpleRep = "null";
+ } else if (element instanceof String) {
+ varTO.stringRep = (String) element;
+ varTO.simpleRep = "\"" + element + "\"";
+ } else {
+ VarValue value = findOrCreateVarValue(element);
+ value.usedIn.add(hostValue);
+ hostValue.members.add(value);
+ oldMembers.remove(value);
+ varTO.stringRep = adapter.getVariableDetailRep(element);
+ varTO.simpleRep = adapter.getVariableSimpleRep(element);
+
+ varTO.hasMembers = adapter.checkVariableHasMembers(element);
+ varTO.valueId = value.id;
+ }
+ list.add(varTO);
+ }
+ for (VarValue value : oldMembers) {
+ value.usedIn.remove(hostValue);
+ if (value.usedIn.isEmpty()) {
+ varCache.remove(value);
+ }
+ }
+ return list;
+ }
+
+ private VarValue findOrCreateVarValue(Object element) {
+ VarValue value = findVarValueByElement(element);
+ if (value == null) {
+ value = new VarValue(element, ++nextId);
+ varCache.add(value);
+ }
+ return value;
+ }
+
+ private VarValue findVarValueByElement(Object element) {
+ for (VarValue cacheEntry : varCache)
+ if (element == cacheEntry.element)
+ return cacheEntry;
+ return null;
+ }
+
+ private VarValue findVarValueById(int id) {
+ for (VarValue cacheEntry : varCache)
+ if (id == cacheEntry.id)
+ return cacheEntry;
+ return null;
+ }
+
+ // remove all obsolete syntax elements from the frameCache.
+ // This could be more than one element in case there were many elements on the stack at the last suspend, but
+ // after a RESUME and a later SUSPEND there could be a complete different variable situation on the stack.
+ // Obsolete variable values are also removed from the varCache if they are nowhere else used.
+ private void cleanFramesCache() {
+ Set<VarValue> oldFrameValues = new HashSet<VarValue>();
+ oldFrameValues.addAll(frameCache);
+
+ for (VarValue value : oldFrameValues)
+ if (!stackFrames.contains(value.element)) {
+ frameCache.remove(value);
+ for (VarValue member : value.members) {
+ member.usedIn.remove(value);
+ if (member.usedIn.isEmpty())
+ varCache.remove(member);
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // IEventHandler implementation
+
+ /**
+ * push the syntax element onto the stack
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#preTask(java.lang.Object, int)
+ */
+ public void preTask(Object element, Object context, int state) {
+ stackFrames.push(new Frame(element, context));
+ }
+
+ /**
+ * pop the peek element from the stack
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#postTask()
+ */
+ public void postTask(Object context) {
+ stackFrames.pop();
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#resumed()
+ */
+ public void resumed() {
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#resumed()
+ */
+ public void suspended() {
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#resumed()
+ */
+ public void started() {
+ }
+
+ /**
+ * no contribution here
+ *
+ * @see org.eclipse.emf.mwe.internal.core.debug.processing.EventHandler#resumed()
+ */
+ public void terminated() {
+ }
+
+ // -------------------------------------------------------------------------
+ private class Frame {
+ final Object element;
+
+ final Object context;
+
+ private Frame(Object element, Object context) {
+ this.element = element;
+ this.context = context;
+ }
+ }
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderDefaultImpl.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderDefaultImpl.java
new file mode 100644
index 0000000..2b4fa6e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderDefaultImpl.java
@@ -0,0 +1,118 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.internal.core.resources;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.emf.mwe.core.resources.ResourceLoader;
+
+public class ResourceLoaderDefaultImpl implements ResourceLoader {
+
+ private static final String FILE_PREFIX = "file:";
+
+ private static final Log log = LogFactory
+ .getLog(ResourceLoaderDefaultImpl.class);
+
+ public final InputStream getResourceAsStream(String path) {
+ InputStream in = internalGetResourceAsStream(path);
+ if (in == null) {
+ try {
+ in = new FileInputStream(path);
+ } catch (final FileNotFoundException e) {
+ if (!path.startsWith(FILE_PREFIX)) {
+ path = FILE_PREFIX + path;
+ }
+ try {
+ in = new FileInputStream(path);
+ } catch (final Exception ex) {
+ return null;
+ }
+ }
+ }
+ return in;
+ }
+
+ protected InputStream internalGetResourceAsStream(final String path) {
+ return Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream(path);
+ }
+
+ public final Class<?> loadClass(final String clazzName) {
+ try {
+ return internalLoadClass(clazzName);
+ } catch (final Exception e) {
+ if (clazzName.startsWith("mwe"))
+ return loadClass(clazzName.replaceFirst("mwe",
+ "org.eclipse.emf.mwe"));
+ return null;
+ }
+ }
+
+ protected Class<?> internalLoadClass(final String clazzName)
+ throws ClassNotFoundException {
+ return Class.forName(clazzName, true, Thread.currentThread()
+ .getContextClassLoader());
+ }
+
+ public final URL getResource(String path) {
+ URL url = internalGetResource(path);
+ if (url == null) {
+ try {
+ if (!path.startsWith(FILE_PREFIX)) {
+ path = FILE_PREFIX + path;
+ }
+ url = new URL(path);
+ if (url.getContent() == null)
+ return null;
+ } catch (final MalformedURLException e) {
+ return null;
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+ return url;
+ }
+
+ protected URL internalGetResource(final String path) {
+ return Thread.currentThread().getContextClassLoader().getResource(path);
+ }
+
+ public Enumeration<URL> getResources(String uri) {
+ try {
+ return Thread.currentThread().getContextClassLoader().getResources(
+ uri);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ return new Enumeration<URL>() {
+ public boolean hasMoreElements() {
+ return false;
+ }
+
+ public URL nextElement() {
+ return null;
+ }
+ };
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderImpl.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderImpl.java
new file mode 100644
index 0000000..3d82adc
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/resources/ResourceLoaderImpl.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.resources;
+
+import java.io.InputStream;
+import java.net.URL;
+
+public class ResourceLoaderImpl extends ResourceLoaderDefaultImpl {
+
+ private ClassLoader loader;
+
+ public ResourceLoaderImpl(final ClassLoader l ) {
+ loader = l;
+ }
+
+ @Override
+ protected URL internalGetResource(final String path) {
+ return loader.getResource(path);
+ }
+
+ @Override
+ protected InputStream internalGetResourceAsStream(final String path) {
+ return loader.getResourceAsStream(path);
+ }
+
+ @Override
+ protected Class<?> internalLoadClass(final String clazzName) throws ClassNotFoundException {
+ return loader.loadClass(clazzName);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/util/ComponentPrinter.java b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/util/ComponentPrinter.java
new file mode 100644
index 0000000..6733a8f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.core/src/org/eclipse/emf/mwe/internal/core/util/ComponentPrinter.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.core.util;
+
+import org.eclipse.emf.mwe.core.WorkflowComponent;
+import org.eclipse.emf.mwe.core.WorkflowComponentWithID;
+import org.eclipse.emf.mwe.core.container.CompositeComponent;
+
+public class ComponentPrinter {
+
+ public static String getString(final Object comp) {
+ if (comp instanceof CompositeComponent) {
+ final CompositeComponent cc = (CompositeComponent) comp;
+ String nameAndLocation = getShortName(cc)+": executing ";
+ if (cc.getName() != null && !"".equals(cc.getName()))
+ nameAndLocation += cc.getName();
+ if (cc.getResource() != null)
+ nameAndLocation += " " + cc.getResource();
+ if (cc.getLocation() != null)
+ nameAndLocation += " " + cc.getLocation();
+ if (!"".equals(nameAndLocation))
+ return nameAndLocation;
+ }
+ if (comp instanceof WorkflowComponentWithID) {
+ final WorkflowComponentWithID wid = (WorkflowComponentWithID) comp;
+ String logMessage = wid.getLogMessage();
+ if (wid.getId() != null && !"".equals(wid.getId())) {
+ return getShortName(wid)+"("+wid.getId()+")" + ((logMessage == null) ? "" : ": "+logMessage);
+ }
+ return getShortName(wid) + ((logMessage == null) ? "" : ": "+logMessage) ;
+ }
+ return comp.getClass().getName();
+ }
+
+ private static String getShortName(WorkflowComponentWithID wid) {
+ return wid.getClass().getSimpleName();
+ }
+
+ public static String getShortString(final WorkflowComponent comp) {
+ if(comp == null)
+ return "no Name";
+ if (comp instanceof WorkflowComponentWithID) {
+ final WorkflowComponentWithID wid = (WorkflowComponentWithID) comp;
+ if (wid.getId() != null && !"".equals(wid.getId()))
+ return wid.getId();
+ }
+ if (comp instanceof CompositeComponent) {
+ final CompositeComponent cc = (CompositeComponent) comp;
+ String nameAndLocation = "";
+ if (cc.getName() != null && !"".equals(cc.getName()))
+ nameAndLocation += cc.getName();
+ if (cc.getResource() != null) {
+ int pos = cc.getResource().lastIndexOf("/");
+ nameAndLocation += " " + cc.getResource().substring(pos + 1);
+ }
+ if (!"".equals(nameAndLocation))
+ return nameAndLocation;
+ }
+ return comp.getClass().getName();
+ }
+
+ public static String getContainerName(final WorkflowComponent comp) {
+ final CompositeComponent cc = comp.getContainer();
+ if(cc != null && cc.getResource() != null) {
+ int pos = cc.getResource().lastIndexOf("/");
+ return cc.getResource().substring(pos + 1);
+ }
+ return "no container";
+ }
+
+ public static String getElementName(final WorkflowComponent comp) {
+ if (comp instanceof WorkflowComponentWithID) {
+ final WorkflowComponentWithID wid = (WorkflowComponentWithID) comp;
+ if (wid.getId() != null && !"".equals(wid.getId()))
+ return wid.getId();
+ }
+ if (comp instanceof CompositeComponent) {
+ final CompositeComponent cc = (CompositeComponent) comp;
+ if (cc.getResource() != null) {
+ int pos = cc.getResource().lastIndexOf("/");
+ return cc.getResource().substring(pos + 1);
+ }
+ }
+ return comp.getClass().getSimpleName();
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.classpath b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.project b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.project
new file mode 100644
index 0000000..b89dd64
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.emf.mwe.ui.simpleEditor</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..af368bb
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: SimpleEditor Plug-in
+Bundle-SymbolicName: org.eclipse.emf.mwe.ui.simpleEditor;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Require-Bundle: org.eclipse.emf.mwe.ui,
+ org.eclipse.ui,
+ org.eclipse.ui.editors,
+ org.eclipse.jface.text,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.views
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/build.properties b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/icons/workflowfile.gif b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/icons/workflowfile.gif
new file mode 100644
index 0000000..25bc50e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/icons/workflowfile.gif
Binary files differ
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/plugin.xml b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/plugin.xml
new file mode 100644
index 0000000..085a42f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension
+ point="org.eclipse.ui.editors">
+ <editor
+ class="org.eclipse.emf.mwe.ui.internal.simpleEditor.WorkflowEditor"
+ contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"
+ default="false"
+ extensions="mwe, oaw"
+ icon="icons/workflowfile.gif"
+ id="org.openarchitectureware.workflow.editors.WorkflowEditor"
+ name="MWE Workflow Editor (Simple)"/>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/ColorManager.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/ColorManager.java
new file mode 100644
index 0000000..68227d8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/ColorManager.java
@@ -0,0 +1,43 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class ColorManager {
+
+ protected Map<RGB,Color> fColorTable = new HashMap<RGB,Color>(10);
+
+ public void dispose() {
+ final Iterator<Color> e = fColorTable.values().iterator();
+ while (e.hasNext())
+ (e.next()).dispose();
+ }
+
+ public Color getColor(final RGB rgb) {
+ Color color = fColorTable.get(rgb);
+ if (color == null) {
+ color = new Color(Display.getCurrent(), rgb);
+ fColorTable.put(rgb, color);
+ }
+ return color;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/NonRuleBasedDamagerRepairer.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/NonRuleBasedDamagerRepairer.java
new file mode 100644
index 0000000..6885699
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/NonRuleBasedDamagerRepairer.java
@@ -0,0 +1,136 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.presentation.IPresentationDamager;
+import org.eclipse.jface.text.presentation.IPresentationRepairer;
+import org.eclipse.swt.custom.StyleRange;
+
+public class NonRuleBasedDamagerRepairer implements IPresentationDamager, IPresentationRepairer {
+
+ /** The document this object works on */
+ protected IDocument fDocument;
+
+ /**
+ * The default text attribute if non is returned as data by the current
+ * token
+ */
+ protected TextAttribute fDefaultTextAttribute;
+
+ /**
+ * Constructor for NonRuleBasedDamagerRepairer.
+ */
+ public NonRuleBasedDamagerRepairer(final TextAttribute defaultTextAttribute) {
+ Assert.isNotNull(defaultTextAttribute);
+
+ fDefaultTextAttribute = defaultTextAttribute;
+ }
+
+ /**
+ * @see IPresentationRepairer#setDocument(IDocument)
+ */
+ public void setDocument(final IDocument document) {
+ fDocument = document;
+ }
+
+ /**
+ * Returns the end offset of the line that contains the specified offset or
+ * if the offset is inside a line delimiter, the end offset of the next
+ * line.
+ *
+ * @param offset
+ * the offset whose line end offset must be computed
+ * @return the line end offset for the given offset
+ * @exception BadLocationException
+ * if offset is invalid in the current document
+ */
+ protected int endOfLineOf(final int offset) throws BadLocationException {
+
+ IRegion info = fDocument.getLineInformationOfOffset(offset);
+ if (offset <= info.getOffset() + info.getLength())
+ return info.getOffset() + info.getLength();
+
+ final int line = fDocument.getLineOfOffset(offset);
+ try {
+ info = fDocument.getLineInformation(line + 1);
+ return info.getOffset() + info.getLength();
+ } catch (final BadLocationException x) {
+ return fDocument.getLength();
+ }
+ }
+
+ /**
+ * @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent,
+ * boolean)
+ */
+ public IRegion getDamageRegion(final ITypedRegion partition, final DocumentEvent event, boolean documentPartitioningChanged) {
+ if (!documentPartitioningChanged) {
+ try {
+
+ final IRegion info = fDocument.getLineInformationOfOffset(event.getOffset());
+ final int start = Math.max(partition.getOffset(), info.getOffset());
+
+ int end = event.getOffset() + (event.getText() == null ? event.getLength() : event.getText().length());
+
+ if (info.getOffset() <= end && end <= info.getOffset() + info.getLength()) {
+ // optimize the case of the same line
+ end = info.getOffset() + info.getLength();
+ } else
+ end = endOfLineOf(end);
+
+ end = Math.min(partition.getOffset() + partition.getLength(), end);
+ return new Region(start, end - start);
+
+ } catch (final BadLocationException x) {
+ }
+ }
+
+ return partition;
+ }
+
+ /**
+ * @see IPresentationRepairer#createPresentation(TextPresentation,
+ * ITypedRegion)
+ */
+ public void createPresentation(final TextPresentation presentation, final ITypedRegion region) {
+ addRange(presentation, region.getOffset(), region.getLength(), fDefaultTextAttribute);
+ }
+
+ /**
+ * Adds style information to the given text presentation.
+ *
+ * @param presentation
+ * the text presentation to be extended
+ * @param offset
+ * the offset of the range to be styled
+ * @param length
+ * the length of the range to be styled
+ * @param attr
+ * the attribute describing the style of the range to be styled
+ */
+ protected void addRange(final TextPresentation presentation, final int offset, final int length, final TextAttribute attr) {
+ if (attr != null)
+ presentation.addStyleRange(new StyleRange(offset, length, attr.getForeground(), attr.getBackground(), attr.getStyle()));
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/TagRule.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/TagRule.java
new file mode 100644
index 0000000..dbaa3d1
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/TagRule.java
@@ -0,0 +1,46 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+
+public class TagRule extends MultiLineRule {
+
+ public TagRule(final IToken token) {
+ super("<", ">", token);
+ }
+
+ @Override
+ protected boolean sequenceDetected(final ICharacterScanner scanner, final char[] sequence, final boolean eofAllowed) {
+ final int c = scanner.read();
+ if (sequence[0] == '<') {
+ if (c == '?') {
+ // processing instruction - abort
+ scanner.unread();
+ return false;
+ }
+ if (c == '!') {
+ scanner.unread();
+ // comment - abort
+ return false;
+ }
+ } else if (sequence[0] == '>') {
+ scanner.unread();
+ }
+ return super.sequenceDetected(scanner, sequence, eofAllowed);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/WorkflowEditor.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/WorkflowEditor.java
new file mode 100644
index 0000000..a08cf0b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/WorkflowEditor.java
@@ -0,0 +1,74 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.emf.mwe.internal.ui.debug.breakpoint.actions.BreakpointActionGroup;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.ui.editors.text.TextEditor;
+
+public class WorkflowEditor extends TextEditor {
+
+ private ColorManager colorManager;
+
+ private BreakpointActionGroup actionGroup;
+
+ public WorkflowEditor() {
+ super();
+ colorManager = new ColorManager();
+ setSourceViewerConfiguration(new XMLConfiguration(colorManager));
+ setDocumentProvider(new XMLDocumentProvider());
+ }
+
+ @Override
+ public void dispose() {
+ colorManager.dispose();
+ super.dispose();
+ }
+
+ @Override
+ protected void createActions() {
+ super.createActions();
+ actionGroup = new BreakpointActionGroup(this);
+ }
+
+ @Override
+ protected void editorContextMenuAboutToShow(IMenuManager menu) {
+ menu.add(new Separator("mwe"));
+ super.editorContextMenuAboutToShow(menu);
+
+ actionGroup.fillContextMenu(menu);
+ }
+
+ @Override
+ protected void rulerContextMenuAboutToShow(IMenuManager menu) {
+ menu.add(new Separator("mwe")); //$NON-NLS-1$
+ super.rulerContextMenuAboutToShow(menu);
+
+ actionGroup.fillContextMenu(menu);
+ }
+
+ public ISourceViewer internalGetSourceViewer() {
+ return getSourceViewer();
+ }
+
+ public IVerticalRuler internalGetVerticalRuler() {
+ return getVerticalRuler();
+ }
+
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLColorConstants.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLColorConstants.java
new file mode 100644
index 0000000..8960bc4
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLColorConstants.java
@@ -0,0 +1,29 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.swt.graphics.RGB;
+
+public interface XMLColorConstants {
+ RGB XML_COMMENT = new RGB(128, 0, 0);
+
+ RGB PROC_INSTR = new RGB(128, 128, 128);
+
+ RGB STRING = new RGB(0, 128, 0);
+
+ RGB DEFAULT = new RGB(0, 0, 0);
+
+ RGB TAG = new RGB(0, 0, 128);
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLConfiguration.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLConfiguration.java
new file mode 100644
index 0000000..7c6811b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLConfiguration.java
@@ -0,0 +1,91 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.presentation.IPresentationReconciler;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+
+public class XMLConfiguration extends SourceViewerConfiguration {
+ private XMLDoubleClickStrategy doubleClickStrategy;
+
+ private XMLTagScanner tagScanner;
+
+ private XMLScanner scanner;
+
+ private ColorManager colorManager;
+
+ public XMLConfiguration(final ColorManager colorManager) {
+ this.colorManager = colorManager;
+ }
+
+ @Override
+ public String[] getConfiguredContentTypes(final ISourceViewer sourceViewer) {
+ return new String[] { IDocument.DEFAULT_CONTENT_TYPE, XMLPartitionScanner.XML_COMMENT,
+ XMLPartitionScanner.XML_TAG };
+ }
+
+ @Override
+ public ITextDoubleClickStrategy getDoubleClickStrategy(final ISourceViewer sourceViewer, final String contentType) {
+ if (doubleClickStrategy == null)
+ doubleClickStrategy = new XMLDoubleClickStrategy();
+ return doubleClickStrategy;
+ }
+
+ protected XMLScanner getXMLScanner() {
+ if (scanner == null) {
+ scanner = new XMLScanner(colorManager);
+ scanner.setDefaultReturnToken(new Token(
+ new TextAttribute(colorManager.getColor(XMLColorConstants.DEFAULT))));
+ }
+ return scanner;
+ }
+
+ protected XMLTagScanner getXMLTagScanner() {
+ if (tagScanner == null) {
+ tagScanner = new XMLTagScanner(colorManager);
+ tagScanner
+ .setDefaultReturnToken(new Token(new TextAttribute(colorManager.getColor(XMLColorConstants.TAG))));
+ }
+ return tagScanner;
+ }
+
+ @Override
+ public IPresentationReconciler getPresentationReconciler(final ISourceViewer sourceViewer) {
+ final PresentationReconciler reconciler = new PresentationReconciler();
+
+ DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getXMLTagScanner());
+ reconciler.setDamager(dr, XMLPartitionScanner.XML_TAG);
+ reconciler.setRepairer(dr, XMLPartitionScanner.XML_TAG);
+
+ dr = new DefaultDamagerRepairer(getXMLScanner());
+ reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
+ reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
+
+ final NonRuleBasedDamagerRepairer ndr = new NonRuleBasedDamagerRepairer(new TextAttribute(colorManager
+ .getColor(XMLColorConstants.XML_COMMENT)));
+ reconciler.setDamager(ndr, XMLPartitionScanner.XML_COMMENT);
+ reconciler.setRepairer(ndr, XMLPartitionScanner.XML_COMMENT);
+
+ return reconciler;
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDocumentProvider.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDocumentProvider.java
new file mode 100644
index 0000000..9f2e5b9
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDocumentProvider.java
@@ -0,0 +1,36 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+
+public class XMLDocumentProvider extends FileDocumentProvider {
+
+ @Override
+ protected IDocument createDocument(final Object element) throws CoreException {
+ final IDocument document = super.createDocument(element);
+ if (document != null) {
+ final IDocumentPartitioner partitioner = new FastPartitioner(new XMLPartitionScanner(), new String[] {
+ XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_COMMENT });
+ partitioner.connect(document);
+ document.setDocumentPartitioner(partitioner);
+ }
+ return document;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDoubleClickStrategy.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDoubleClickStrategy.java
new file mode 100644
index 0000000..0ef86eb
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLDoubleClickStrategy.java
@@ -0,0 +1,131 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextDoubleClickStrategy;
+import org.eclipse.jface.text.ITextViewer;
+
+public class XMLDoubleClickStrategy implements ITextDoubleClickStrategy {
+ protected ITextViewer fText;
+
+ public void doubleClicked(final ITextViewer part) {
+ final int pos = part.getSelectedRange().x;
+
+ if (pos < 0)
+ return;
+
+ fText = part;
+
+ if (!selectComment(pos)) {
+ selectWord(pos);
+ }
+ }
+
+ protected boolean selectComment(final int caretPos) {
+ final IDocument doc = fText.getDocument();
+ int startPos, endPos;
+
+ try {
+ int pos = caretPos;
+ char c = ' ';
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (c == '\\') {
+ pos -= 2;
+ continue;
+ }
+ if (c == Character.LINE_SEPARATOR || c == '\"')
+ break;
+ --pos;
+ }
+
+ if (c != '\"')
+ return false;
+
+ startPos = pos;
+
+ pos = caretPos;
+ final int length = doc.getLength();
+ c = ' ';
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (c == Character.LINE_SEPARATOR || c == '\"')
+ break;
+ ++pos;
+ }
+ if (c != '\"')
+ return false;
+
+ endPos = pos;
+
+ final int offset = startPos + 1;
+ final int len = endPos - offset;
+ fText.setSelectedRange(offset, len);
+ return true;
+ } catch (final BadLocationException x) {
+ }
+
+ return false;
+ }
+
+ protected boolean selectWord(final int caretPos) {
+
+ final IDocument doc = fText.getDocument();
+ int startPos, endPos;
+
+ try {
+
+ int pos = caretPos;
+ char c;
+
+ while (pos >= 0) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ --pos;
+ }
+
+ startPos = pos;
+
+ pos = caretPos;
+ final int length = doc.getLength();
+
+ while (pos < length) {
+ c = doc.getChar(pos);
+ if (!Character.isJavaIdentifierPart(c))
+ break;
+ ++pos;
+ }
+
+ endPos = pos;
+ selectRange(startPos, endPos);
+ return true;
+
+ } catch (final BadLocationException x) {
+ }
+
+ return false;
+ }
+
+ private void selectRange(final int startPos, final int stopPos) {
+ final int offset = startPos + 1;
+ final int length = stopPos - offset;
+ fText.setSelectedRange(offset, length);
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLPartitionScanner.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLPartitionScanner.java
new file mode 100644
index 0000000..91038a6
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLPartitionScanner.java
@@ -0,0 +1,42 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
+import org.eclipse.jface.text.rules.Token;
+
+public class XMLPartitionScanner extends RuleBasedPartitionScanner {
+ public final static String XML_DEFAULT = "__xml_default";
+
+ public final static String XML_COMMENT = "__xml_comment";
+
+ public final static String XML_TAG = "__xml_tag";
+
+ public XMLPartitionScanner() {
+
+ final IToken xmlComment = new Token(XML_COMMENT);
+ final IToken tag = new Token(XML_TAG);
+
+ final IPredicateRule[] rules = new IPredicateRule[2];
+
+ rules[0] = new MultiLineRule("<!--", "-->", xmlComment);
+ rules[1] = new TagRule(tag);
+
+ setPredicateRules(rules);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLScanner.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLScanner.java
new file mode 100644
index 0000000..7b7abf8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLScanner.java
@@ -0,0 +1,38 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+
+public class XMLScanner extends RuleBasedScanner {
+
+ public XMLScanner(final ColorManager manager) {
+ final IToken procInstr = new Token(new TextAttribute(manager.getColor(XMLColorConstants.PROC_INSTR)));
+
+ final IRule[] rules = new IRule[2];
+ // Add rule for processing instructions
+ rules[0] = new SingleLineRule("<?", "?>", procInstr);
+ // Add generic whitespace rule.
+ rules[1] = new WhitespaceRule(new XMLWhitespaceDetector());
+
+ setRules(rules);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLTagScanner.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLTagScanner.java
new file mode 100644
index 0000000..dd70985
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLTagScanner.java
@@ -0,0 +1,41 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+
+public class XMLTagScanner extends RuleBasedScanner {
+
+ public XMLTagScanner(final ColorManager manager) {
+ final IToken string = new Token(new TextAttribute(manager.getColor(XMLColorConstants.STRING)));
+
+ final IRule[] rules = new IRule[3];
+
+ // Add rule for double quotes
+ rules[0] = new SingleLineRule("\"", "\"", string, '\\');
+ // Add a rule for single quotes
+ rules[1] = new SingleLineRule("'", "'", string, '\\');
+ // Add generic whitespace rule.
+ rules[2] = new WhitespaceRule(new XMLWhitespaceDetector());
+
+ setRules(rules);
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLWhitespaceDetector.java b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLWhitespaceDetector.java
new file mode 100644
index 0000000..93530c8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui.simpleEditor/src/org/eclipse/emf/mwe/ui/internal/simpleEditor/XMLWhitespaceDetector.java
@@ -0,0 +1,24 @@
+/*
+ * <copyright>
+ *
+ * Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
+ *
+ * </copyright>
+ */
+package org.eclipse.emf.mwe.ui.internal.simpleEditor;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+public class XMLWhitespaceDetector implements IWhitespaceDetector {
+
+ public boolean isWhitespace(final char c) {
+ return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/.classpath b/plugins/org.eclipse.emf.mwe.ui/.classpath
new file mode 100644
index 0000000..304e861
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.emf.mwe.ui/.cvsignore b/plugins/org.eclipse.emf.mwe.ui/.cvsignore
new file mode 100644
index 0000000..861bfcf
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/.cvsignore
@@ -0,0 +1,5 @@
+bin
+temp.folder
+javaCompiler...args
+build.xml
+pspbrwse.jbf
diff --git a/plugins/org.eclipse.emf.mwe.ui/.project b/plugins/org.eclipse.emf.mwe.ui/.project
new file mode 100644
index 0000000..15734b8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.emf.mwe.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.emf.mwe.ui/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.mwe.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..44b0394
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Tue Jun 13 14:37:13 CEST 2006
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/plugins/org.eclipse.emf.mwe.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.mwe.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..bba2624
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,34 @@
+Bundle-SymbolicName: org.eclipse.emf.mwe.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.jdt.debug.ui,
+ org.eclipse.jdt.launching,
+ org.eclipse.ui,
+ org.eclipse.debug.ui,
+ org.eclipse.jdt.core,
+ org.eclipse.jdt.ui,
+ org.eclipse.jface.text,
+ org.eclipse.ui.editors,
+ org.eclipse.emf.mwe.core,
+ org.eclipse.ui.ide
+Provide-Package: org.eclipse.emf.mwe.internal.ui.eclipse.launch
+Bundle-ManifestVersion: 2
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Eclipse-LazyStart: true
+Bundle-Activator: org.eclipse.emf.mwe.internal.ui.workflow.Activator
+Export-Package: org.eclipse.emf.mwe.internal.ui.debug.breakpoint.actions;x-friends:="org.eclipse.emf.mwe.ui.simpleEditor,org.eclipse.emf.mwe.ui.wtpeditor",
+ org.eclipse.emf.mwe.internal.ui.debug.launching.ui;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.debug.model;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.debug.model.ui;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.debug.processing;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.debug.processing.handlers;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.eclipse.launch;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.wizard;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.workflow;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.workflow.debug;x-internal:=true,
+ org.eclipse.emf.mwe.internal.ui.workflow.util;x-internal:=true
+
diff --git a/plugins/org.eclipse.emf.mwe.ui/build.properties b/plugins/org.eclipse.emf.mwe.ui/build.properties
new file mode 100644
index 0000000..31b5d26
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/build.properties
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# committers of openArchitectureWare - initial API and implementation
+###############################################################################
+source.. = src/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties,\
+ icons/,\
+ plugin.xml,\
+ schema/
diff --git a/plugins/org.eclipse.emf.mwe.ui/icons/oawlaunch.gif b/plugins/org.eclipse.emf.mwe.ui/icons/oawlaunch.gif
new file mode 100644
index 0000000..91bb037
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/icons/oawlaunch.gif
Binary files differ
diff --git a/plugins/org.eclipse.emf.mwe.ui/icons/workflowfile.gif b/plugins/org.eclipse.emf.mwe.ui/icons/workflowfile.gif
new file mode 100644
index 0000000..25bc50e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/icons/workflowfile.gif
Binary files differ
diff --git a/plugins/org.eclipse.emf.mwe.ui/plugin.properties b/plugins/org.eclipse.emf.mwe.ui/plugin.properties
new file mode 100644
index 0000000..6f8aa66
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2000, 2006 openArchitectureWare commiters and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# openArchitectureWare commiters - initial API and implementation
+###############################################################################
+pluginName=modeling workflow engine ui
+providerName=eclipse.org
diff --git a/plugins/org.eclipse.emf.mwe.ui/plugin.xml b/plugins/org.eclipse.emf.mwe.ui/plugin.xml
new file mode 100644
index 0000000..f8dabc0
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/plugin.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin >
+ <extension-point id="debugHandlers" name="Debugger Handlers" schema="schema/handlers.exsd"/>
+ <extension-point id="debugAdapters" name="Debugger Adapters" schema="schema/adapters.exsd"/>
+
+ <extension
+ point="org.eclipse.team.core.fileTypes">
+ <fileTypes
+ type="text"
+ extension="oaw">
+ </fileTypes>
+ <fileTypes
+ extension="mwe"
+ type="text">
+ </fileTypes>
+ </extension>
+
+
+<!-- ================================================================================ -->
+<!-- wizard -->
+<!-- ================================================================================ -->
+
+ <extension
+ point = "org.eclipse.ui.newWizards">
+ <category
+ id = "org.eclipse.emf.mwe.ui.newWizards"
+ name="Modeling Workflow Engine">
+ </category>
+ <wizard
+ category="org.eclipse.emf.mwe.ui.newWizards"
+ class="org.eclipse.emf.mwe.internal.ui.wizard.NewWorkflowFileWizard"
+ icon="icons/workflowfile.gif"
+ id="org.eclipse.emf.mwe.internal.ui.wizard.NewWorkflowFileWizard"
+ name="Workflow File"
+ >
+ <description>Create a new MWE Workflow File</description>
+ <selection class="org.eclipse.core.resources.IResource"/>
+ </wizard>
+ </extension>
+
+<!-- ================================================================================ -->
+<!-- debugger -->
+<!-- ================================================================================ -->
+
+ <!-- breakpoint handling -->
+ <extension
+ point="org.eclipse.core.resources.markers"
+ id="breakpointMarker">
+ <super
+ type="org.eclipse.debug.core.lineBreakpointMarker">
+ </super>
+ <persistent
+ value="true">
+ </persistent>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.breakpoints">
+ <breakpoint
+ markerType="org.eclipse.emf.mwe.ui.breakpointMarker"
+ class="org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint"
+ id="breakpoint">
+ </breakpoint>
+ </extension>
+
+ <!-- launchConfiguration -->
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ id="org.eclipse.emf.mwe.ui.MWELaunchConfigType"
+ modes="run, debug"
+ name="MWE Workflow"
+ delegate="org.eclipse.emf.mwe.internal.ui.eclipse.launch.MWELaunchDelegate"
+ sourceLocatorId="org.eclipse.emf.mwe.ui.debug.sourceLookupDirector"
+ sourcePathComputerId="org.eclipse.emf.mwe.ui.debug.sourcePathComputer"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ class="org.eclipse.emf.mwe.internal.ui.debug.launching.ui.MWELaunchConfigTabGroup"
+ id="org.eclipse.emf.mwe.ui.MWELaunchConfigTabGroup"
+ type="org.eclipse.emf.mwe.ui.MWELaunchConfigType"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+ <launchConfigurationTypeImage
+ configTypeID="org.eclipse.emf.mwe.ui.MWELaunchConfigType"
+ icon="icons/oawlaunch.gif"
+ id="org.eclipse.emf.mwe.ui.debug.MWELaunchConfigTypeImage"/>
+ </extension>
+
+ <!-- launch shortcut -->
+ <extension
+ point="org.eclipse.debug.ui.launchShortcuts">
+ <shortcut
+ label="MWE Workflow"
+ icon="icons/oawlaunch.gif"
+ category="org.eclipse.ui.externaltools"
+ class="org.eclipse.emf.mwe.internal.ui.eclipse.launch.MWELaunchShortcut"
+ modes="run, debug"
+ id="org.eclipse.emf.mwe.ui.debug.launching.shortcut">
+ <contextualLaunch>
+ <enablement>
+ <with variable="selection">
+ <count value="1"/>
+ <iterate>
+ <or>
+ <test
+ property="org.eclipse.debug.ui.matchesPattern"
+ value="*.oaw">
+ </test>
+ <test
+ property="org.eclipse.debug.ui.matchesPattern"
+ value="*.mwe">
+ </test>
+ </or>
+ </iterate>
+ </with>
+ </enablement>
+ <contextLabel
+ mode="run"
+ label="MWE Workflow"/>
+ <contextLabel
+ mode="debug"
+ label="MWE Workflow"/>
+ </contextualLaunch>
+ </shortcut>
+ </extension>
+
+ <!-- source lookup -->
+ <extension
+ point="org.eclipse.debug.core.sourceLocators">
+ <sourceLocator
+ id="org.eclipse.emf.mwe.ui.debug.sourceLookupDirector"
+ name="MWE debug Source Lookup Director"
+ class="org.eclipse.emf.mwe.internal.ui.debug.sourcelookup.MWESourceLookupDirector"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.sourcePathComputers">
+ <sourcePathComputer
+ id="org.eclipse.emf.mwe.ui.debug.sourcePathComputer"
+ class="org.eclipse.emf.mwe.internal.ui.debug.sourcelookup.MWESourcePathComputerDelegate"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.debugModelPresentations">
+ <debugModelPresentation
+ class="org.eclipse.emf.mwe.internal.ui.debug.model.ui.DebugModelPresentation"
+ id="org.eclipse.emf.mwe.debug.model">
+ </debugModelPresentation>
+ </extension>
+
+ <extension
+ point="org.eclipse.emf.mwe.ui.debugHandlers">
+ <handler
+ name="Variables Handlers"
+ pluginClass="org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.VariablesPluginHandler"
+ runtimeClass="org.eclipse.emf.mwe.internal.core.debug.processing.handlers.VariablesRuntimeHandler"
+ type="variablesHandler"/>
+ <handler
+ name="Breakpoint Handlers"
+ pluginClass="org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.BreakpointPluginHandler"
+ runtimeClass="org.eclipse.emf.mwe.internal.core.debug.processing.handlers.BreakpointRuntimeHandler"
+ type="breakpointHandler"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.emf.mwe.ui.debugAdapters">
+ <adapter
+ name="Workflow Adapters"
+ pluginClass="org.eclipse.emf.mwe.internal.ui.workflow.debug.MWEPluginAdapter"
+ runtimeClass="org.eclipse.emf.mwe.internal.core.debug.mwe.WorkflowElementAdapter"/>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.emf.mwe.ui/schema/adapters.exsd b/plugins/org.eclipse.emf.mwe.ui/schema/adapters.exsd
new file mode 100644
index 0000000..2657d3e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/schema/adapters.exsd
@@ -0,0 +1,150 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.mwe.ui">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.emf.mwe.ui" id="adapters" name="MWE Debugger Adapters"/>
+ </appInfo>
+ <documentation>
+ A plugin-in implementing an extension for this extension point can provide additional functionality to the openArchitectureWare debugger.&lt;br&gt;
+&lt;br&gt;
+Adapters can translate specific behavior of a syntax element into the neutral common format that is required by the debugger. E.g. variable names and content depend in most cases on the concrete application.&lt;br&gt;
+There are two types of adapters: &lt;code&gt;IElementAdapter&lt;/code&gt; and &lt;code&gt;IPluginAdapter&lt;/code&gt;. Normally there should be always one pair of these for each component with debug behavior.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="adapter" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ the descriptor of the extension
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="adapter">
+ <annotation>
+ <appInfo>
+ <meta.element labelAttribute="name"/>
+ </appInfo>
+ </annotation>
+ <complexType>
+ <attribute name="runtimeClass" type="string" use="required">
+ <annotation>
+ <documentation>
+ The name of an IElementAdapter implementation. This class will be instantiated in the runtime VM and be registered in the debugger monitor.&lt;br&gt;
+It is responsible to provide component specific information in a neutral way. It creates name and sourcefile information of an element (one &quot;step&quot; or &quot;Unit of work&quot;), provides name and string representation of variables, converts a breakpoint&apos;s resource and line information into the corresponding sytax element.&lt;br&gt;
+More functionality can be implemented to support additional user defined handlers.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.emf.mwe.core.debug.processing.IElementAdapter"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="pluginClass" type="string" use="required">
+ <annotation>
+ <documentation>
+ The name of an IPluginAdapter implementation. This class will be instantiated in the eclipse VM. It is responsible to handle component specific issues on the eclipse side.&lt;br&gt;
+It can provide the correct editor Id of an element type for source lookup, breakpoint definition (what is a &quot;Unit of work&quot;) and element type specific image that is shown in the Launch view.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.emf.mwe.internal.ui.debug.processing.IPluginAdapter"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the adapter instance
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ 4.2
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ &lt;pre&gt;&lt;extension
+ point=&quot;org.openarchitectureware.debug.adapters&quot;&gt;
+ &lt;adapter
+ name=&quot;Workflow Adapter&quot;
+ pluginClass=&quot;org.openarchitectureware.debug.model.adapters.WorkflowPluginAdapter&quot;
+ runtimeClass=&quot;org.openarchitectureware.debug.model.adapters.WorkflowElementAdapter&quot;/&gt;
+&lt;/extension&gt;&lt;/pre&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ &lt;br&gt;&lt;b&gt;runtimeClass&lt;/b&gt; must be a fully qualified name of a Java class that implements the &lt;code&gt;IElementAdapter&lt;/code&gt; interface.&lt;br&gt;
+&lt;b&gt;pluginClass&lt;/b&gt; must be a fully qualified name of a Java class that implements the &lt;code&gt;IPluginAdapter&lt;/code&gt;interface.
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ &lt;ul&gt;
+&lt;li&gt;WorkflowRuntimeAdapter, WorkflowPluginAdapter&lt;/li&gt;
+&lt;/ul&gt;
+Other modules of the openArchitecture framework implement more adapters:
+&lt;ul&gt;&lt;li&gt;XpandRuntimeAdapter, XpandPluginAdapter&lt;/li&gt;
+&lt;li&gt;ExpressionRuntimeAdapter, ExpressionPluginAdapter&lt;/li&gt;
+&lt;/ul&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2007 committers of openArchitectureWare and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.emf.mwe.ui/schema/handlers.exsd b/plugins/org.eclipse.emf.mwe.ui/schema/handlers.exsd
new file mode 100644
index 0000000..7da82b1
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/schema/handlers.exsd
@@ -0,0 +1,176 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.emf.mwe.ui">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.emf.mwe.ui" id="handlers" name="Debugger Handlers"/>
+ </appInfo>
+ <documentation>
+ A plugin-in implementing an extension for this extension point can provide additional functionality to the openArchitectureWare debugger.&lt;br&gt;&lt;br&gt;
+An MWE debugger process is started in an extra Virtual Machine as in Java. The communication between the runtime VM and the Eclipse VM happens via a socket of the localHost.&lt;br&gt;
+There are two types of handlers: &lt;code&gt;IRuntimeHandler&lt;/code&gt; and &lt;code&gt;IPluginHandler&lt;/code&gt;. Normally there should be always a pair of these, that communicate with each other.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="handler" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+ the descriptor of the extension
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ an optional identifier of the extension instance
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the extension instance
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="handler">
+ <annotation>
+ <appInfo>
+ <meta.element labelAttribute="name"/>
+ </appInfo>
+ </annotation>
+ <complexType>
+ <attribute name="runtimeClass" type="string">
+ <annotation>
+ <documentation>
+ The name of an IRuntimeHandler implementation. This class will be instantiated in the runtime VM, that has normally no direct access to the Eclipse session.&lt;br&gt;
+In the &lt;code&gt;init(...)&lt;/code&gt; method it can register itself in the &lt;code&gt;DebugMonitor&lt;/code&gt; and can that way send commands or react to events to/from the monitor.&lt;br&gt;
+If the handler must listen for communication events from eclipse it is reasonable to do it in an extra thread. This thread can be started in the &lt;code&gt;startListener()&lt;/code&gt; method.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.emf.mwe.internal.core.debug.processing.IRuntimeHandler"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="pluginClass" type="string">
+ <annotation>
+ <documentation>
+ The name of an IPluginHandler implementation. This class will be instantiated in the eclipse VM. It is responsible to handle commands and events on the eclipse side.&lt;br&gt;
+It can send commands through the socket to the runtime side and assumes a corresponding runtime handler that reacts on these commands there.&lt;br&gt;
+It can also listen for events on the socket that where sent by a corresponding runtime handler and distribute them to the debug element model (through the &lt;code&gt;DebugModelManager&lt;/code&gt;) or to any other class that provides additional functionality to the Eclipse framwork.
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.emf.mwe.internal.ui.debug.processing.IPluginHandler"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="type">
+ <annotation>
+ <documentation>
+ an optional handlerType name of the pluginHandler instance. The handler is registered under that name in the &lt;code&gt;DebugModelManager&lt;/code&gt;.&lt;br&gt;
+&quot;other&quot; handlers will get a reference to the &lt;code&gt;DebugModelManager&lt;/code&gt;, bu are not registered there.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="variablesHandler">
+ </enumeration>
+ <enumeration value="breakpointHandler">
+ </enumeration>
+ <enumeration value="other">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ an optional name of the handler instance
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ 4.2
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ &lt;pre&gt;
+ &lt;extension
+ point=&quot;org.openarchitectureware.workflow.debugHandlers&quot;&gt;
+ &lt;handler
+ name=&quot;Variables Handler&quot;
+ pluginClass=&quot;org.openarchitectureware.debug.processing.handlers.VariablesPluginHandler&quot;
+ runtimeClass=&quot;org.openarchitectureware.debug.processing.handlers.VariablesRuntimeHandler&quot;
+ type=&quot;variablesHandler&quot;/&gt;
+ &lt;/extension&gt;
+&lt;/pre&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ &lt;br&gt;&lt;b&gt;runtimeClass&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface&lt;pre&gt;package org.openarchitectureware.debug.processing;
+public interface IRuntimeHandler {
+ public void init(DebugMonitor monitor, Connection connection);
+ public void startListener();
+}&lt;/pre&gt;
+
+&lt;b&gt;pluginClass&lt;/b&gt; must be a fully qualified name of a Java class that implements the interface&lt;pre&gt;package org.openarchitectureware.debug.processing;
+public interface IPluginHandler {
+ public void setConnection(Connection connection);
+}&lt;/pre&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ &lt;ul&gt;
+&lt;li&gt;VariablesRuntimeHandler, VariablesPluginHandler&lt;/li&gt;
+&lt;li&gt;BreakpointRuntimeHandler, BreakpointPluginHandler&lt;/li&gt;
+&lt;/ul&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/BreakpointActionGroup.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/BreakpointActionGroup.java
new file mode 100644
index 0000000..f0a151e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/BreakpointActionGroup.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.breakpoint.actions;
+
+import java.lang.reflect.Method;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.editors.text.TextEditor;
+
+/**
+ * Action group with 2 actions: "Toggle Breakpoints" and "Enable/Disable Breakpoints".<br>
+ * Despite of usual breakpoint actions these actions can be used not only for vertical ruler context menu (incl.
+ * double click), but also for editor context menu. That way "in line" breakpoints can be handled.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class BreakpointActionGroup extends ActionGroup {
+
+ private EnableDisableBreakpointAction enableAction;
+
+ private ToggleBreakpointAction toggleAction;
+
+ private int lastSelectedLine;
+
+ private int lastSelectedOffset;
+
+ private IVerticalRuler verticalRuler;
+
+ private boolean rulerSelected;
+
+ private StyledText textWidget;
+
+ // -------------------------------------------------------------------------
+
+ public BreakpointActionGroup(final TextEditor editor) {
+ Assert.isNotNull(editor);
+
+ // Note: We don't want to define a new "IOurOwnTextEditor" interface, so we do it via Reflection
+ Object obj = getterMethod("getSourceViewer", editor);
+ if (obj == null)
+ return;
+ textWidget = ((ISourceViewer) obj).getTextWidget();
+
+ obj = getterMethod("getVerticalRuler", editor);
+ if (obj == null)
+ return;
+ verticalRuler = (IVerticalRuler) obj;
+
+ enableAction = new EnableDisableBreakpointAction(editor, this);
+ toggleAction = new ToggleBreakpointAction(editor, this);
+
+ // set lastSelectedLine if RightMouseClick on text
+ textWidget.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if (e.button == 3)
+ updateLastSelectedOffset(e.x, e.y);
+ }
+
+ });
+
+ // set lastSelectedLine if RightMouseClick or DoubleClick on vertical ruler
+ verticalRuler.getControl().addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if (e.button == 3)
+ updateLastSelectedLine(e.y);
+
+ }
+
+ @Override
+ public void mouseDoubleClick(MouseEvent e) {
+ updateLastSelectedLine(e.y);
+ // see note below for why we call it here
+ toggleAction.run();
+ }
+
+ });
+ }
+
+ private void updateLastSelectedLine(int y) {
+ // Note: we use our own "lastSelectedLine mechanism" (not the ruler's one) because of sequencing problems
+ // our action mouseHandler would be called after the ruler mouseHandler, so for doubleClick the
+ // lastSelectedLine value may not be correct
+ // (see AbstractTextEditor.createPartCOntrol(): createVerticalRuler() is before createActions()
+ rulerSelected = true;
+ lastSelectedLine = verticalRuler.toDocumentLineNumber(y);
+ lastSelectedOffset = textWidget.getOffsetAtLocation(new Point(0, y));
+ }
+
+ private void updateLastSelectedOffset(int x, int y) {
+ rulerSelected = false;
+ lastSelectedLine = verticalRuler.toDocumentLineNumber(y);
+ lastSelectedOffset = textWidget.getOffsetAtLocation(new Point(x, y));
+ }
+
+ // -------------------------------------------------------------------------
+
+ public boolean isRulerSelected() {
+ return rulerSelected;
+ }
+
+ public int getLastSelectedLine() {
+ return lastSelectedLine;
+ }
+
+ public int getLastSelectedOffset() {
+ return lastSelectedOffset;
+ }
+
+ public int getOffsetAtLine(int line) {
+ return textWidget.getOffsetAtLine(line);
+ }
+
+ // -------------------------------------------------------------------------
+
+ @Override
+ public void fillContextMenu(IMenuManager manager) {
+ toggleAction.updateText();
+ manager.appendToGroup("mwe", toggleAction);
+ enableAction.updateText();
+ manager.appendToGroup("mwe", enableAction);
+ }
+
+ @Override
+ public void dispose() {
+ enableAction = null;
+ toggleAction = null;
+ super.dispose();
+ }
+
+ private Object getterMethod(String name, Object element) {
+ try {
+ Method m = findMethod(name, element.getClass());
+ if (m != null) {
+ m.setAccessible(true);
+ return m.invoke(element, new Object[] {});
+ }
+ } catch (Exception e) {
+ System.out.println("error");
+ }
+ return null;
+ }
+
+ private Method findMethod(String name, Class<?> clazz) {
+ if (!Object.class.equals(clazz)) {
+ Method[] methods = clazz.getDeclaredMethods();
+ for (Method method : methods)
+ if (method.getName().equals(name))
+ return method;
+ return findMethod(name, clazz.getSuperclass());
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/EnableDisableBreakpointAction.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/EnableDisableBreakpointAction.java
new file mode 100644
index 0000000..38abb8c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/EnableDisableBreakpointAction.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.breakpoint.actions;
+
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.eclipse.ui.texteditor.SimpleMarkerAnnotation;
+
+public class EnableDisableBreakpointAction extends Action {
+
+ private TextEditor editor;
+
+ private final BreakpointActionGroup group;
+
+ /**
+ * Enable/Disable breakpoint action that can be used both at vertical ruler and editor context menu.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+ protected EnableDisableBreakpointAction(TextEditor editor, BreakpointActionGroup group) {
+ this.editor = editor;
+ this.group = group;
+ setToolTipText("enable or disable breakpoint");
+ }
+
+ public void updateText() {
+ fBreakpoint = getBreakpoint();
+ setEnabled(fBreakpoint != null);
+ if (fBreakpoint != null) {
+ try {
+ if (fBreakpoint.isEnabled()) {
+ setText("Disable Breakpoint");
+ } else {
+ setText("Enable Breakpoint");
+ }
+ } catch (CoreException e) {
+ }
+ } else {
+ setText("Disable Breakpoint");
+ }
+ }
+
+ private IBreakpoint fBreakpoint;
+
+ @Override
+ public void run() {
+ if (fBreakpoint != null) {
+ try {
+ fBreakpoint.setEnabled(!fBreakpoint.isEnabled());
+ } catch (CoreException e) {
+ Activator.logError("Failed to toggle breakpoint enablement.", e);
+ }
+ }
+ }
+
+ protected IBreakpoint getBreakpoint() {
+ boolean isRulerSelected = group.isRulerSelected();
+ int selectedLine = group.getLastSelectedLine();
+ int selectedOffset = group.getLastSelectedOffset();
+ IAnnotationModel annotationModel = editor.getDocumentProvider().getAnnotationModel(
+ editor.getEditorInput());
+ IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
+ if (annotationModel != null) {
+ Iterator<?> iterator = annotationModel.getAnnotationIterator();
+ while (iterator.hasNext()) {
+ Object object = iterator.next();
+ if (object instanceof SimpleMarkerAnnotation) {
+ SimpleMarkerAnnotation markerAnnotation = (SimpleMarkerAnnotation) object;
+ IMarker marker = markerAnnotation.getMarker();
+ try {
+ if (marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) {
+ Position position = annotationModel.getPosition(markerAnnotation);
+ int line = document.getLineOfOffset(position.offset);
+ if (isRulerSelected && line == selectedLine || !isRulerSelected
+ && selectedOffset >= position.offset
+ && selectedOffset <= position.offset + position.length) {
+ IBreakpoint breakpoint = DebugPlugin.getDefault().getBreakpointManager()
+ .getBreakpoint(marker);
+ if (breakpoint != null)
+ return breakpoint;
+ }
+ }
+ } catch (CoreException e) {
+ } catch (BadLocationException e) {
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/ToggleBreakpointAction.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/ToggleBreakpointAction.java
new file mode 100644
index 0000000..cfb114f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/breakpoint/actions/ToggleBreakpointAction.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.breakpoint.actions;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginAdapter;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginExtensionManager;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.editors.text.TextEditor;
+
+/**
+ * Toggle breakpoint action that can be used both at vertical ruler and editor context menu.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class ToggleBreakpointAction extends Action {
+
+ private TextEditor editor;
+
+ private final BreakpointActionGroup group;
+
+ public ToggleBreakpointAction(TextEditor editor, BreakpointActionGroup group) {
+ this.editor = editor;
+ this.group = group;
+ setText("Toggle Breakpoint");
+ setToolTipText("set or delete breakpoint");
+ }
+
+ public void updateText() {
+ IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
+
+ PluginAdapter adapter = PluginExtensionManager.getDefault().getAdapterByResourceExtension(resource.getFileExtension());
+ if (adapter == null)
+ return;
+
+ int line = group.getLastSelectedLine() + 1;
+ int start = group.getLastSelectedOffset();
+ int end = group.isRulerSelected() ? group.getOffsetAtLine(line) : start;
+ if (group.isRulerSelected())
+ setEnabled(true);
+ else
+ setEnabled(adapter.isToggleBpEnabled(resource, start, end, line));
+ }
+
+ @Override
+ public void run() {
+ try {
+ toggleBreakpoint();
+ } catch (CoreException e) {
+ }
+ }
+
+ protected void toggleBreakpoint() throws CoreException {
+ IResource resource = (IResource) editor.getEditorInput().getAdapter(IResource.class);
+
+ // Hint: doc line numbers start at 0, but markers at 1, therefore + 1
+ int line = group.getLastSelectedLine() + 1;
+ int start = group.getLastSelectedOffset();
+
+ PluginAdapter adapter = PluginExtensionManager.getDefault().getAdapterByResourceExtension(resource.getFileExtension());
+ if (adapter == null)
+ return;
+
+ // check if a BP already exists on that line and remove it
+ boolean isRulerSelected = group.isRulerSelected();
+ int end = isRulerSelected ? group.getOffsetAtLine(line) /* Hint: offset after selected line */: start;
+ IBreakpointManager breakpointManager = DebugPlugin.getDefault().getBreakpointManager();
+ IBreakpoint[] breakpoints = breakpointManager.getBreakpoints(MWEBreakpoint.DEBUG_MODEL_ID);
+ IBreakpoint bp = adapter.checkBreakpoints(breakpoints,resource,start, end, line);
+ if(bp != null){
+ bp.delete();
+ return;
+ }
+ // else: register it
+ bp = adapter.createBreakpoint(resource, start, end, line);
+ if (bp == null) {
+ return;
+ }
+ breakpointManager.addBreakpoint(bp);
+
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigMainTab.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigMainTab.java
new file mode 100644
index 0000000..db1473b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigMainTab.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.launching.ui;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.emf.mwe.internal.ui.eclipse.launch.MWELaunchConfigurationConstants;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jdt.ui.JavaElementLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.dialogs.ResourceListSelectionDialog;
+
+/**
+ * This class defines the workflow launch config main tab. It is based on the Java one
+ * <code>org.eclipse.jdt.debug.ui.launchConfigurations.JavaMainTab</code>, but shows a workflow file instead of
+ * a Java class.<br>
+ * There is an additional <code>javaDebugCheckbox</code> to be able to select the debug process (MWE debug or
+ * Java debug)
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWELaunchConfigMainTab extends JavaLaunchTab {
+
+ private WidgetListener fListener = new WidgetListener();
+
+ private Text projText;
+
+ private Button projButton;
+
+ private Text wfText;
+
+ private Button wfButton;
+
+ private Button stopInMainCheckbox;
+
+ private Button javaDebugCheckbox;
+
+ private Path wfPath;
+
+ // ********************************************************** create Control
+
+ public String getName() {
+ return "Main";
+ }
+
+ public void createControl(Composite parent) {
+ Font font = parent.getFont();
+
+ Composite comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+ GridLayout topLayout = new GridLayout();
+ topLayout.verticalSpacing = 0;
+ comp.setLayout(topLayout);
+ comp.setFont(font);
+
+ // Project group
+ projButton = createPushButton(parent, "&Browse...", null);
+ projText = createGroup(comp, "&Project:", projButton, null);
+
+ createVerticalSpacer(comp, 1);
+
+ // workflow group
+ wfButton = createPushButton(parent, "&Search...", null);
+ stopInMainCheckbox = createCheckButton(parent, "St&op in main");
+ javaDebugCheckbox = createCheckButton(parent, "Java Debug");
+ wfText = createGroup(comp, "initial Workflow File", wfButton, new Button[] { stopInMainCheckbox,
+ javaDebugCheckbox });
+ }
+
+ private Text createGroup(Composite comp, String title, Button searchButton, Button[] checkButtons) {
+ Font font = comp.getFont();
+ Group group = new Group(comp, SWT.NONE);
+ group.setText(title);
+ group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ group.setLayout(layout);
+ group.setFont(font);
+ Text text = new Text(group, SWT.SINGLE | SWT.BORDER);
+ text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ text.setFont(font);
+ text.addModifyListener(fListener);
+ searchButton.setParent(group);
+ searchButton.addSelectionListener(fListener);
+ if (checkButtons != null)
+ for (Button button : checkButtons) {
+ button.setParent(group);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ button.setLayoutData(gd);
+ button.addSelectionListener(fListener);
+ }
+ return text;
+ }
+
+ // *********************************************************** data handling
+
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ // is called when a new LauchConfig is created
+ // nothing to do
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration config) {
+ super.initializeFrom(config);
+
+ try {
+ projText.setText(config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""));
+ setWfText(config.getAttribute(MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, ""));
+ stopInMainCheckbox.setSelection(config.getAttribute(
+ IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, false));
+ javaDebugCheckbox.setSelection(config.getAttribute(
+ MWELaunchConfigurationConstants.ATTR_MWE_JAVA_DEBUG_MODE, false));
+ } catch (CoreException e) {
+ setErrorMessage(e.getMessage());
+ }
+ }
+
+ private void setWfText(String fullName) {
+ wfPath = new Path(fullName);
+ String projectName = projText.getText().trim();
+ int pos = fullName.indexOf(projectName);
+ if (projectName.length() > 0 && pos >= 0) {
+ wfText.setText(fullName.substring(pos + projectName.length() + 1));
+ } else
+ wfText.setText(fullName);
+ }
+
+ public void performApply(ILaunchConfigurationWorkingCopy config) {
+ config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projText.getText().trim());
+ config.setAttribute(MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, wfPath.toString());
+ config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, stopInMainCheckbox
+ .getSelection());
+ config.setAttribute(MWELaunchConfigurationConstants.ATTR_MWE_JAVA_DEBUG_MODE, javaDebugCheckbox
+ .getSelection());
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ String text = wfText.getText().trim();
+ if (text.length() > 0) {
+ if (getWorkspaceRoot().findMember(wfPath) == null) {
+ setErrorMessage("Specified file does not exist");
+ return false;
+ }
+ } else {
+ setMessage("Specify a workflow file");
+ }
+ return super.isValid(launchConfig);
+ }
+
+ // *********************************************************** event handler
+
+ private class WidgetListener implements ModifyListener, SelectionListener {
+
+ public void modifyText(ModifyEvent e) {
+ updateLaunchConfigurationDialog();
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // do nothing
+ }
+
+ public void widgetSelected(SelectionEvent e) {
+ Object source = e.getSource();
+ if (source == projButton)
+ handleProjectButtonSelected();
+ else if (source == wfButton)
+ handleWfButtonSelected();
+ else
+ updateLaunchConfigurationDialog();
+ }
+ }
+
+ private void handleWfButtonSelected() {
+ ResourceListSelectionDialog dialog = new ResourceListSelectionDialog(getShell(), getWorkspaceRoot(),
+ IResource.FILE);
+ dialog.setTitle("select starting workflow file");
+ dialog.setMessage("select starting workflow file");
+ if (dialog.open() == Window.OK) {
+ Object[] files = dialog.getResult();
+ IFile file = (IFile) files[0];
+ setWfText(file.getFullPath().toString());
+ }
+ }
+
+ private void handleProjectButtonSelected() {
+ IJavaProject project = chooseJavaProject();
+ if (project == null)
+ return;
+ String projectName = project.getElementName();
+ projText.setText(projectName);
+ }
+
+ private IJavaProject chooseJavaProject() {
+ ILabelProvider labelProvider = new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
+ dialog.setTitle("Project Selection");
+ dialog.setMessage("Select a project to constrain your search.");
+ try {
+ dialog.setElements(JavaCore.create(getWorkspaceRoot()).getJavaProjects());
+ } catch (JavaModelException jme) {
+ Activator.logError(jme);
+ }
+ IJavaProject javaProject = getJavaProject();
+ if (javaProject != null) {
+ dialog.setInitialSelections(new Object[] { javaProject });
+ }
+ if (dialog.open() == Window.OK) {
+ return (IJavaProject) dialog.getFirstResult();
+ }
+ return null;
+ }
+
+ private IJavaProject getJavaProject() {
+ String projectName = projText.getText().trim();
+ if (projectName.length() < 1) {
+ return null;
+ }
+ return JavaCore.create(getWorkspaceRoot()).getJavaProject(projectName);
+ }
+
+ private IWorkspaceRoot getWorkspaceRoot() {
+ return ResourcesPlugin.getWorkspace().getRoot();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigTabGroup.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigTabGroup.java
new file mode 100644
index 0000000..7b73e18
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/launching/ui/MWELaunchConfigTabGroup.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.launching.ui;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.jdt.debug.ui.launchConfigurations.JavaArgumentsTab;
+import org.eclipse.jdt.debug.ui.launchConfigurations.JavaClasspathTab;
+
+/**
+ * This class defines the available tabs of a workflow launch config dialog. Compared with the Java launch dialog
+ * there is a special main tab.<br>
+ * Carried over from Java are JavaArgumentsTab, JavaClasspathTab and CommonTab.<br>
+ * There are no JavaJRETab, SourceLookupTab and EnvironmentTab.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWELaunchConfigTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ setTabs(new ILaunchConfigurationTab[] { new MWELaunchConfigMainTab(), new JavaArgumentsTab(), new JavaClasspathTab(), new CommonTab() });
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugElement.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugElement.java
new file mode 100644
index 0000000..37818c5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugElement.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
+
+/**
+ * Common functions for all classes inheriting from this class, that represent the debug model.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public abstract class DebugElement extends PlatformObject implements IDebugElement {
+ protected DebugTarget target;
+
+ public DebugElement(DebugTarget target) {
+ this.target = target;
+ }
+
+ public String getModelIdentifier() {
+ return MWEBreakpoint.DEBUG_MODEL_ID;
+ }
+
+ public IDebugTarget getDebugTarget() {
+ return target;
+ }
+
+ public DebugTarget getDebugTarget0() {
+ return target;
+ }
+
+ public ILaunch getLaunch() {
+ return getDebugTarget().getLaunch();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getAdapter(Class adapter) {
+ if (adapter == IDebugElement.class) {
+ return this;
+ }
+ if (adapter == IDebugTarget.class) {
+ return getDebugTarget();
+ }
+ if (adapter == ILaunch.class) {
+ return getLaunch();
+ }
+ if (adapter == IProcess.class) {
+ return getDebugTarget().getProcess();
+ }
+ if (adapter == ILaunchConfiguration.class) {
+ return getLaunch().getLaunchConfiguration();
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ public DebugModelManager getDebugModelManager() {
+ return target.getDebugModelManager();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugStackFrame.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugStackFrame.java
new file mode 100644
index 0000000..09fce8b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugStackFrame.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IRegisterGroup;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.ui.debug.model.ui.VariableSorter;
+
+/**
+ * MWE Debug StackFrame implementation.<br>
+ * Each debugger step is represented by a stack frame. It holds the variables that belong to that frame. It
+ * provides all information important for the Source code display. <br>
+ * <br>
+ * For Info: In the MWE debug model all processing methods are delegated either to DebugTarget or DebugThread.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugStackFrame extends DebugElement implements IStackFrame {
+
+ private DebugThread thread;
+
+ private SyntaxElement frameValues;
+
+ private List<DebugVariable> variables = new ArrayList<DebugVariable>();
+
+ private boolean variablesChecked;
+
+ // -------------------------------------------------------------------------
+
+ public DebugStackFrame(DebugThread thread, SyntaxElement to) {
+ super(thread.getDebugTarget0());
+ this.thread = thread;
+ this.frameValues = to;
+ }
+
+ // ********************************************** IStackFrame implementation
+
+ public IThread getThread() {
+ return thread;
+ }
+
+ public synchronized IVariable[] getVariables() throws DebugException {
+ if (!variablesChecked) {
+ // Hint: we assume that when clicking a frame or opening the variables view at first this method is
+ // called. Therefore we remember the current stackFrame number in thread and use it when collecting
+ // sub variables.
+ List<VarValueTO> vars = getDebugModelManager().requireVariables(thread.getSetVarFrameId(this));
+ variables.clear();
+ for (VarValueTO varTO : vars) {
+ DebugVariable var = new DebugVariable(getDebugTarget0(), varTO);
+ variables.add(var);
+ }
+ VariableSorter.sort(variables);
+ variablesChecked = true;
+ }
+ return variables.toArray(new IVariable[0]);
+ }
+
+ public boolean hasVariables() throws DebugException {
+ return getVariables().length > 0;
+ }
+
+ public void setVariablesDirty() {
+ variablesChecked = false;
+ }
+
+ public String getName() {
+ return frameValues.containerName + " :: " + frameValues.elementName + " (line: " + frameValues.line + ")";
+ }
+
+ public int getLineNumber() {
+ return frameValues.line;
+ }
+
+ public int getCharStart() {
+ return frameValues.start;
+ }
+
+ public int getCharEnd() {
+ return frameValues.end;
+ }
+
+ public String getResource() {
+ return frameValues.resource;
+ }
+
+ public String getType() {
+ return frameValues.type;
+
+ }
+
+ public int getFrameId() {
+ return frameValues.frameId;
+
+ }
+
+ public boolean isVisible() {
+ return frameValues.visible;
+
+ }
+
+ public IRegisterGroup[] getRegisterGroups() {
+ return null;
+ }
+
+ public boolean hasRegisterGroups() {
+ return false;
+ }
+
+ // ******************************************************** process handling
+
+ public boolean isStepping() {
+ return getThread().isStepping();
+ }
+
+ public boolean canStepInto() {
+ return getThread().canStepInto();
+ }
+
+ public void stepInto() throws DebugException {
+ getThread().stepInto();
+ }
+
+ public boolean canStepOver() {
+ return getThread().canStepOver();
+ }
+
+ public void stepOver() throws DebugException {
+ getThread().stepOver();
+ }
+
+ public boolean canStepReturn() {
+ return getThread().canStepReturn();
+ }
+
+ public void stepReturn() throws DebugException {
+ getThread().stepReturn();
+ }
+
+ public boolean canSuspend() {
+ return getThread().canSuspend();
+ }
+
+ public boolean isSuspended() {
+ return getThread().isSuspended();
+ }
+
+ public void suspend() throws DebugException {
+ getThread().suspend();
+ }
+
+ public boolean canResume() {
+ return getThread().canResume();
+ }
+
+ public void resume() throws DebugException {
+ getThread().resume();
+ }
+
+ public boolean canTerminate() {
+ return getThread().canTerminate();
+ }
+
+ public boolean isTerminated() {
+ return getThread().isTerminated();
+ }
+
+ public void terminate() throws DebugException {
+ getThread().terminate();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugTarget.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugTarget.java
new file mode 100644
index 0000000..79e692e
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugTarget.java
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
+import org.eclipse.emf.mwe.internal.ui.eclipse.launch.MWELaunchConfigurationConstants;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+
+/**
+ * MWE Debug Target implementation<br>
+ * It holds the debug threads. There is only one thread in the MWE debug model.<br>
+ * It holds also a variable values cache.
+ * <br>
+ * For Info: A debug target handles the suspend, resume, terminate commands and the breakpoint handling.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugTarget extends DebugElement implements IDebugTarget {
+
+ private IProcess fProcess;
+
+ private ILaunch fLaunch;
+
+ private DebugThread fThread;
+
+ private DebugModelManager dmm;
+
+ private Map<Integer, DebugValue> valueCache = new HashMap<Integer, DebugValue>();
+
+ protected boolean suspended;
+
+ public static DebugTarget newDebugTarget(final ILaunch launch, final IProcess process, final Connection conn)
+ throws CoreException {
+ final DebugTarget[] target = new DebugTarget[1];
+ IWorkspaceRunnable r = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor m) throws DebugException {
+ target[0] = new DebugTarget(launch, process, conn);
+ }
+ };
+ try {
+ // run as atomic unit of work; fire resource change events only once
+ ResourcesPlugin.getWorkspace().run(r, null, 0, null);
+ } catch (CoreException e) {
+ Activator.logError(e);
+ Activator.showError(e.getStatus());
+ throw e;
+ }
+ launch.addDebugTarget(target[0]);
+ return target[0];
+ }
+
+ private DebugTarget(ILaunch launch, IProcess process, Connection conn) throws DebugException {
+ super(null);
+ fLaunch = launch;
+ target = this;
+ fProcess = process;
+ fThread = new DebugThread(this);
+ dmm = DebugModelManager.newDebugModelManager(this, conn);
+
+ DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
+ }
+
+ // ******************************************** debug model related elements
+ @Override
+ public ILaunch getLaunch() {
+ return fLaunch;
+ }
+
+ public IProcess getProcess() {
+ return fProcess;
+ }
+
+ public IThread[] getThreads() {
+ return new IThread[] { fThread };
+ }
+
+ public DebugThread getThread() {
+ return fThread;
+ }
+
+ public void removeThread() {
+ fThread = null;
+ }
+
+ public boolean hasThreads() {
+ return fThread != null;
+ }
+
+ public String getName() {
+ try {
+ return "Workflow: "
+ + fLaunch.getLaunchConfiguration().getAttribute(
+ MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, "");
+ } catch (CoreException e) {
+ // should not occur
+ }
+ return "";
+ }
+
+ @Override
+ public DebugModelManager getDebugModelManager() {
+ return dmm;
+ }
+
+ public DebugValue getDebugValue(VarValueTO varTO) {
+ DebugValue value = null;
+ int valueId = varTO.valueId;
+
+ if (valueId == 0)
+ // don't cache primitives
+ value = new DebugValue(this, varTO);
+ else {
+ value = valueCache.get(valueId);
+ if (value == null) {
+ value = new DebugValue(this, varTO);
+ valueCache.put(valueId, value);
+ }
+ }
+ return value;
+ }
+
+ public void updateDebugValues(List<VarValueTO> vars) {
+ for (VarValueTO varTO : vars) {
+ DebugValue value = valueCache.get(varTO.valueId);
+ if (value != null && value.isDirty()) {
+ value.setVarTO(varTO);
+ }
+ }
+ }
+
+ // ************************ ISuspendResume implementation and other commands
+
+ public boolean canResume() {
+ return suspended;
+ }
+
+ public boolean canSuspend() {
+ return !getProcess().isTerminated() && !suspended;
+ }
+
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ public void resume() throws DebugException {
+ dmm.requireResume();
+ }
+
+ public void suspend() throws DebugException {
+ dmm.requireSuspend();
+ }
+
+ public void setSuspended(boolean value) {
+ suspended = value;
+ }
+
+ public void setVariablesDirty() {
+ for (DebugValue entry : valueCache.values())
+ if (entry != null)
+ entry.setDirty(true);
+ }
+
+ // ***************** Breakpoint handling, IBreakpointListener implementation
+
+ public void installDeferredBreakpoints() {
+ IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
+ MWEBreakpoint.DEBUG_MODEL_ID);
+ for (int i = 0; i < breakpoints.length; i++) {
+ breakpointAdded(breakpoints[i]);
+ }
+ }
+
+ public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+ return breakpoint.getModelIdentifier().equals(MWEBreakpoint.DEBUG_MODEL_ID);
+ }
+
+ public void breakpointAdded(IBreakpoint breakpoint) {
+ if (supportsBreakpoint(breakpoint))
+ try {
+ if (breakpoint.isEnabled())
+ dmm.requireSetBreakpoint((MWEBreakpoint) breakpoint);
+ } catch (CoreException e) {
+ // in case connection broke
+ }
+ }
+
+ public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (supportsBreakpoint(breakpoint))
+ try {
+ dmm.requireRemoveBreakpoint((MWEBreakpoint) breakpoint);
+ } catch (CoreException e) {
+ // in case connection broke
+ }
+ }
+
+ public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ if (breakpoint.isEnabled()) {
+ breakpointAdded(breakpoint);
+ } else {
+ breakpointRemoved(breakpoint, null);
+ }
+ } catch (CoreException e) {
+ // in case connection broke
+ }
+ }
+ }
+
+ // *********************************************** ITerminate implementation
+
+ public boolean canTerminate() {
+ return getProcess().canTerminate();
+ }
+
+ public boolean isTerminated() {
+ return getProcess().isTerminated();
+ }
+
+ public void terminate() throws DebugException {
+ dmm.requireTerminate();
+ }
+
+ // ********************************************** IDisconnect implementation
+
+ public boolean canDisconnect() {
+ return false;
+ }
+
+ public void disconnect() {
+ // not supported
+ }
+
+ public boolean isDisconnected() {
+ return false;
+ }
+
+ // ************************************ IMemoryBlockRetrieval implementation
+
+ public boolean supportsStorageRetrieval() {
+ return false;
+ }
+
+ public IMemoryBlock getMemoryBlock(long startAddress, long length) {
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugThread.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugThread.java
new file mode 100644
index 0000000..9b2e835
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugThread.java
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+
+/**
+ * MWE Debug Thread implementation<br>
+ * For Info: A debug thread handles the stepping commands and holds the DebugStackFrames
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugThread extends DebugElement implements IThread {
+
+ private Stack<DebugStackFrame> frames = new Stack<DebugStackFrame>();
+
+ private MWEBreakpoint bp;
+
+ private boolean fStepping = false;
+
+ // id of last frame that was used to get variables from
+ private int varFrameId;
+
+ public DebugThread(DebugTarget target) {
+ super(target);
+ }
+
+ // ***************************************************** StackFrame handling
+
+ public boolean hasStackFrames() {
+ return isSuspended();
+ }
+
+ public IStackFrame[] getStackFrames() {
+ if (isSuspended()) {
+ Stack<DebugStackFrame> result = new Stack<DebugStackFrame>();
+ int size = frames.size();
+ for (int i = size - 1; i >= 0; i--) {
+ DebugStackFrame frame = frames.get(i);
+ if (frame.isVisible())
+ result.push(frame);
+ }
+ return result.toArray(new IStackFrame[0]);
+ }
+ return new IStackFrame[0];
+ }
+
+ public IStackFrame getTopStackFrame() {
+ if (isSuspended() && !frames.isEmpty()) {
+ return frames.peek();
+ }
+ return null;
+ }
+
+ public DebugStackFrame getStackFramePeek() {
+ return frames.peek();
+ }
+
+ public int getSetVarFrameId(DebugStackFrame frame) {
+ varFrameId = frame.getFrameId();
+ return varFrameId;
+ }
+
+ public int getVarFrameId() {
+ return varFrameId;
+ }
+
+ public void clearStack(int cleanStackLevel) {
+ for (int i = frames.size(); i > cleanStackLevel; i--)
+ frames.pop();
+ }
+
+ public void pushStackFrames(List<SyntaxElement> list) {
+ for (SyntaxElement se : list)
+ frames.push(new DebugStackFrame(this, se));
+ }
+
+ public void setVariablesDirty() {
+ for (DebugStackFrame frame : frames)
+ frame.setVariablesDirty();
+ }
+
+ // ***************************************************** Breakpoint handling
+
+ // used in Breakpoint view to select the current BP
+ public IBreakpoint[] getBreakpoints() {
+ if (bp == null) {
+ return new IBreakpoint[0];
+ }
+ return new IBreakpoint[] { bp };
+ }
+
+ // a BP will be set by the DebugModelManager, when it is hit
+ public void setBreakpoint(MWEBreakpoint bp) {
+ this.bp = bp;
+ }
+
+ // *************************************************** other IThread methods
+
+ public int getPriority() {
+ return 0;
+ }
+
+ public String getName() {
+ StringBuilder sb = new StringBuilder("State: " + getState());
+ if (bp != null) {
+ sb.append(" (breakpoint " + bp.getName() + ")");
+ }
+ return sb.toString();
+ }
+
+ public String getState() {
+ return isTerminated() ? "terminated" : isSuspended() ? "suspended" : isStepping() ? "stepping" : "running";
+ }
+
+ // ******************************************************** process handling
+
+ public boolean isStepping() {
+ return fStepping;
+ }
+
+ public void setStepping(boolean stepping) {
+ fStepping = stepping;
+ }
+
+ public boolean canStepInto() {
+ return isSuspended();
+ }
+
+ public void stepInto() throws DebugException {
+ getDebugModelManager().requireStepInto();
+ }
+
+ public boolean canStepOver() {
+ return isSuspended();
+ }
+
+ public void stepOver() throws DebugException {
+ getDebugModelManager().requireStepOver();
+ }
+
+ public boolean canStepReturn() {
+ return isSuspended();
+ }
+
+ public void stepReturn() throws DebugException {
+ getDebugModelManager().requireStepReturn();
+ }
+
+ public boolean canSuspend() {
+ return getDebugTarget().canSuspend();
+ }
+
+ public boolean isSuspended() {
+ return getDebugTarget().isSuspended();
+ }
+
+ public void suspend() throws DebugException {
+ getDebugTarget().suspend();
+ }
+
+ public boolean canResume() {
+ return getDebugTarget().canResume();
+ }
+
+ public void resume() throws DebugException {
+ getDebugTarget().resume();
+ }
+
+ public boolean canTerminate() {
+ return getDebugTarget().canTerminate();
+ }
+
+ public boolean isTerminated() {
+ return getDebugTarget().isTerminated();
+ }
+
+ public void terminate() throws DebugException {
+ getDebugTarget().terminate();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugValue.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugValue.java
new file mode 100644
index 0000000..fb719ef
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugValue.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.ui.debug.model.ui.VariableSorter;
+
+/**
+ * MWE Debug Value implementation<br>
+ * A DebugValue has (beside it's own String representation) a list of sub-variables.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugValue extends DebugElement implements IValue {
+
+ private VarValueTO varTO;
+
+ private boolean dirty;
+
+ private List<DebugVariable> variables = new ArrayList<DebugVariable>();
+
+ // -------------------------------------------------------------------------
+
+ public DebugValue(DebugTarget target, VarValueTO varTO) {
+ super(target);
+ this.varTO = varTO;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void setVarTO(VarValueTO varTO) {
+ this.varTO = varTO;
+ }
+
+ public int getVarTOId() {
+ return varTO.valueId;
+ }
+
+ public boolean isDirty() {
+ return dirty;
+ }
+
+ public void setDirty(boolean dirty) {
+ this.dirty = dirty;
+ }
+
+ public String getReferenceTypeName() {
+ // not used in our debug model
+ return "";
+ }
+
+ public String getValueString() {
+ return varTO.simpleRep + (varTO.valueId > 0 ? " (id=" + varTO.valueId + ")" : "");
+ }
+
+ public String getDetailRep() {
+ return varTO.stringRep;
+ }
+
+ public boolean isAllocated() {
+ return true;
+ }
+
+ public boolean hasVariables() {
+ return varTO.hasMembers;
+ }
+
+ public synchronized IVariable[] getVariables() throws DebugException {
+ if (varTO.hasMembers && variables.isEmpty() || dirty) {
+ // require variable value information from runtime process for the first time and after one step
+ List<VarValueTO> vars = getDebugModelManager().requireSubVariables(varTO.valueId);
+ if (dirty) {
+ // it's an update
+ List<DebugVariable> oldVars = new ArrayList<DebugVariable>();
+ oldVars.addAll(variables);
+ for (VarValueTO varTO : vars) {
+ boolean varFound = false;
+ for (DebugVariable var : variables) {
+ if (var.getName().equals(varTO.name)) {
+ varFound = true;
+ if (varTO.valueId == 0)
+ // update value for primitives
+ var.getValue0().setVarTO(varTO);
+ else if (var.getValue0().getVarTOId() != varTO.valueId) {
+ // update value information
+ var.setValue(varTO);
+ } else
+ // still up2date
+ oldVars.remove(var);
+ break;
+ }
+ }
+ if (!varFound) {
+ DebugVariable var = new DebugVariable(getDebugTarget0(), varTO);
+ variables.add(var);
+ }
+ }
+ for (DebugVariable var : oldVars)
+ // remove remaining obsolete vars
+ variables.remove(var);
+ } else
+ // first time: create new variables
+ for (VarValueTO varTO : vars) {
+ DebugVariable var = new DebugVariable(getDebugTarget0(), varTO);
+ variables.add(var);
+ }
+ dirty = false;
+ VariableSorter.sort(variables);
+
+ }
+ return variables.toArray(new IVariable[0]);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugVariable.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugVariable.java
new file mode 100644
index 0000000..10c5982
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/DebugVariable.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+
+/**
+ * MWE Debug Variable implementation<br>
+ * A variable has (beside the name) a <code>DebugValue</code>, that holds potential sub-variables.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugVariable extends DebugElement implements IVariable {
+
+ private String name;
+
+ private DebugValue value;
+
+ public DebugVariable(DebugTarget target, VarValueTO varTO) {
+ super(target);
+ name = varTO.name;
+ setValue(varTO);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public IValue getValue() {
+ return value;
+ }
+
+ public DebugValue getValue0() {
+ return value;
+ }
+
+ public void setValue(VarValueTO varTO) {
+ value = target.getDebugValue(varTO);
+ }
+
+ public void setValue(String expression) {
+ // not used (yet?)
+ // to be implemented if variable modification shall be established
+ }
+
+ public void setValue(IValue value) {
+ if (value instanceof DebugValue)
+ this.value = (DebugValue) value;
+ }
+
+ public String getReferenceTypeName() {
+ return value.getReferenceTypeName();
+ }
+
+ // ********************************** we don't support value modification yet
+
+ public boolean supportsValueModification() {
+ return false;
+ }
+
+ public boolean hasValueChanged() {
+ return false;
+ }
+
+ public boolean verifyValue(String expression) {
+ return true;
+ }
+
+ public boolean verifyValue(IValue test) {
+ return true;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/MWEBreakpoint.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/MWEBreakpoint.java
new file mode 100644
index 0000000..d272224
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/MWEBreakpoint.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.LineBreakpoint;
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.internal.ui.workflow.util.PluginConfigurationElementUtil;
+
+/**
+ * A line- and in-text breakpoint that supports the MWE debug model
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWEBreakpoint extends LineBreakpoint {
+
+ public static final String DEBUG_MODEL_ID = "org.eclipse.emf.mwe.debug.model";
+
+ public static final String RESOURCE = "resource";
+
+ public static final String NAME = "name";
+
+ public static final String ELEMENT_NAME = "element";
+
+ public MWEBreakpoint() {
+ super();
+ }
+
+ public MWEBreakpoint(final IResource resource, final String elementName, final int lineNumber,
+ final int start, final int end) throws CoreException {
+
+ IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker marker = resource.createMarker(getMarkerId());
+ setMarker(marker);
+ marker.setAttribute(IBreakpoint.ENABLED, Boolean.TRUE);
+ marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
+ marker.setAttribute(IMarker.CHAR_START, start);
+ marker.setAttribute(IMarker.CHAR_END, end);
+ marker.setAttribute(IBreakpoint.ID, getModelIdentifier());
+ marker.setAttribute(RESOURCE, resource.getFullPath().toString());
+ marker.setAttribute(NAME, resource.getName());
+ marker.setAttribute(ELEMENT_NAME, elementName);
+ marker.setAttribute(IMarker.MESSAGE, getName());
+
+ }
+
+ };
+ run(getMarkerRule(resource), runnable);
+ }
+
+ public String getModelIdentifier() {
+ return DEBUG_MODEL_ID;
+ }
+
+ public String getName() {
+ return getMarker().getAttribute(NAME, "") + " [line: " + getMarker().getAttribute(IMarker.LINE_NUMBER, 0)
+ + "] - " + getMarker().getAttribute(ELEMENT_NAME, "");
+ }
+
+ public int getLine() {
+ return getMarker().getAttribute(IMarker.LINE_NUMBER, 0);
+ }
+
+ public int getOffset() {
+ return getMarker().getAttribute(IMarker.CHAR_START, 0);
+ }
+
+ public String getResource() {
+ return getMarker().getAttribute(RESOURCE, "");
+ }
+
+ public SyntaxElement createTO() {
+ SyntaxElement se = new SyntaxElement();
+ se.resource = getResource();
+ se.line = getLine();
+ se.start = getOffset();
+ return se;
+ }
+
+ public boolean equals(int start, String resource) {
+ return getOffset() == start && getResource().endsWith(resource);
+ }
+
+ private String getMarkerId() {
+ return PluginConfigurationElementUtil.getConfigAttribute("org.eclipse.debug.core.breakpoints/"
+ + "breakpoint[class=" + getClass().getName() + "]/markerType");
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/DebugModelPresentation.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/DebugModelPresentation.java
new file mode 100644
index 0000000..2d2485d
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/DebugModelPresentation.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model.ui;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.debug.ui.IValueDetailListener;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugStackFrame;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugValue;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginAdapter;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginExtensionManager;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * Renders debug elements for display in several views; compare to
+ * org.eclipse.jdt.internal.debug.ui.JDIModelPresentation
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugModelPresentation extends LabelProvider implements IDebugModelPresentation {
+
+ public void setAttribute(String attribute, Object value) {
+ // we don't set attributes in our debug model
+ }
+
+ // provides the image in the several view for the debug element
+ // if we don't cover it here, the DefaultLabelProvider uses the default debug labels
+ // Hint: for ILaunch and IProcess the method is not called, so we don't have a chance to customize them
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof DebugStackFrame) {
+ DebugStackFrame frame = (DebugStackFrame) element;
+ PluginAdapter adapter = PluginExtensionManager.getDefault().getAdapterByType(frame.getType());
+ if (adapter != null)
+ return adapter.getIcon();
+ }
+ return null;
+ }
+
+ // provides the text in the several debug views
+ // Hint: we return null by intension, so that the DefaultLabelProvider calls getName() on the debug elements
+ // For breakpoints the default is too Java related, so we implement our own presentation.
+ @Override
+ public String getText(Object element) {
+ if (element instanceof MWEBreakpoint)
+ return ((MWEBreakpoint) element).getName();
+ return null;
+ }
+
+ public void computeDetail(IValue value, IValueDetailListener listener) {
+ String detail = ((DebugValue) value).getDetailRep();
+ listener.detailComputed(value, detail);
+ }
+
+ // called to get the right source editor input for a resource
+ public IEditorInput getEditorInput(Object element) {
+ if (element instanceof IFile) {
+ return new FileEditorInput((IFile) element);
+ }
+ if (element instanceof ILineBreakpoint) {
+ return new FileEditorInput((IFile) ((ILineBreakpoint) element).getMarker().getResource());
+ }
+ if (element instanceof IStorage) {
+ return new JarEntryEditorInput((IStorage) element);
+ }
+
+ return null;
+ }
+
+ // called at source editor display to show the source in the right editor type
+ public String getEditorId(IEditorInput input, Object element) {
+ String ext = "";
+ if ((element instanceof IFile || element instanceof ILineBreakpoint) && input instanceof IFileEditorInput) {
+ ext = ((IFileEditorInput) input).getFile().getFileExtension();
+ } else if (element instanceof IStorage && input instanceof JarEntryEditorInput) {
+ ext = ((JarEntryEditorInput) input).getContentType();
+ }
+ PluginAdapter adapter = PluginExtensionManager.getDefault().getAdapterByResourceExtension(ext);
+ if (adapter != null)
+ return adapter.getEditorId();
+ return "org.eclipse.ui.DefaultTextEditor";
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/JarEntryEditorInput.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/JarEntryEditorInput.java
new file mode 100644
index 0000000..8ebd8d2
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/JarEntryEditorInput.java
@@ -0,0 +1,48 @@
+package org.eclipse.emf.mwe.internal.ui.debug.model.ui;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IStorageEditorInput;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * An EditorInput for a JarEntryFile.
+ * copied from org.eclipse.jdt.internal.ui.javaeditor.JarEntryEditorInput
+ */
+public class JarEntryEditorInput extends org.eclipse.jdt.internal.ui.javaeditor.JarEntryEditorInput implements IStorageEditorInput {
+
+ private IStorage fJarEntryFile;
+
+ public JarEntryEditorInput(IStorage jarEntryFile) {
+ super(jarEntryFile);
+ }
+
+ public String getFullPath() {
+ return fJarEntryFile.getFullPath().toString();
+ }
+
+
+ public String getToolTipText() {
+ //TODO: ER: add corresponding plugin to the text
+ // as it is for Files; This would be new, since it is also
+ // not available in Java
+ return fJarEntryFile.getFullPath().makeRelative().toString();
+ }
+
+ public ImageDescriptor getImageDescriptor() {
+ IEditorRegistry registry = PlatformUI.getWorkbench()
+ .getEditorRegistry();
+ return registry.getImageDescriptor(fJarEntryFile.getFullPath()
+ .getFileExtension());
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (adapter == IStorage.class) {
+ return fJarEntryFile;
+ }
+ return fJarEntryFile.getAdapter(adapter);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/VariableSorter.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/VariableSorter.java
new file mode 100644
index 0000000..9078f83
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/model/ui/VariableSorter.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.model.ui;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugVariable;
+
+/**
+ * Sorter for debug variables by it's name. It sorts upper case names at first and lower case afterwards.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class VariableSorter {
+
+ static VarComparator inst;
+
+ public static void sort(List<DebugVariable> variables) {
+ if (inst == null)
+ inst = new VariableSorter().new VarComparator();
+ Collections.sort(variables, inst);
+ }
+
+ class VarComparator implements java.util.Comparator<DebugVariable> {
+
+ // we assume names exist and are not empty, -> is not checked here (Problem?)
+ public int compare(DebugVariable o1, DebugVariable o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/DebugModelManager.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/DebugModelManager.java
new file mode 100644
index 0000000..c7ce301
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/DebugModelManager.java
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.mwe.core.debug.model.SyntaxElement;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugStackFrame;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugTarget;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugThread;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.BreakpointPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.CommandPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.VariablesPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+
+/**
+ * @author Clemens Kadura (zAJKa)
+ */
+public class DebugModelManager implements IDebugEventSetListener {
+ private DebugTarget target;
+
+ private PluginExtensionManager extensionManager;
+
+ private CommandPluginHandler cmdHandler;
+
+ private VariablesPluginHandler varHandler;
+
+ private BreakpointPluginHandler bpHandler;
+
+ public static DebugModelManager newDebugModelManager(DebugTarget target, Connection connection)
+ throws DebugException {
+ DebugModelManager dmm = new DebugModelManager(target);
+ dmm.extensionManager = PluginExtensionManager.getDefault();
+ dmm.extensionManager.init(dmm, connection);
+ return dmm;
+ }
+
+ private DebugModelManager(DebugTarget target) {
+ this.target = target;
+ DebugPlugin.getDefault().addDebugEventListener(this);
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void setCmdHandler(CommandPluginHandler cmdHandler) {
+ this.cmdHandler = cmdHandler;
+ }
+
+ public void setVariablesHandler(VariablesPluginHandler varHandler) {
+ this.varHandler = varHandler;
+ }
+
+ public void setBreakpointHandler(BreakpointPluginHandler bpHandler) {
+ this.bpHandler = bpHandler;
+ }
+
+ public boolean hasRequiredHandlers() {
+ return cmdHandler != null && varHandler != null && bpHandler != null;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public DebugTarget getTarget() {
+ return target;
+ }
+
+ public DebugThread getThread() {
+ return target.getThread();
+ }
+
+ // ********************************************************** event handling
+
+ public void debuggerStarted() throws DebugException {
+ if (shallStopInMain())
+ cmdHandler.sendSuspendCommand();
+ target.setSuspended(false);
+ target.installDeferredBreakpoints();
+ fireCreationEvent();
+ }
+
+ public void adaptStackFrames(int cleanStackLevel, List<SyntaxElement> frames) {
+ getThread().clearStack(cleanStackLevel);
+ getThread().pushStackFrames(frames);
+ target.setVariablesDirty();
+ getThread().setVariablesDirty();
+ }
+
+ public void debuggerSuspended() {
+ target.setSuspended(true);
+ // Hint: we don't set DebugEvent.STEP_END by intention
+ // only CLIENT_REQUEST or BREAKPOINT detail will expand the launch tree
+ int detail = (checkBreakPoint()) ? DebugEvent.BREAKPOINT : DebugEvent.CLIENT_REQUEST;
+ fireSuspendEvent(detail);
+ }
+
+ public void debuggerResumed() {
+ target.setSuspended(false);
+ // Hint: we don't set STEP_IN, STEP_OVER or STEP_RETURN by intention
+ // because the ThreadEventHandler would only update CONTENT, but not STATE
+ fireResumeEvent(DebugEvent.CLIENT_REQUEST);
+ }
+
+ public void debuggerTerminated() {
+ target.setSuspended(true);
+ getThread().setStepping(false);
+ fireSuspendEvent(DebugEvent.CLIENT_REQUEST);
+ // wait until the delayed event handling is finished (>500ms) before returning and sending confirmation
+ // afterwards
+ // this is to make sure that the source view update event will be really thrown
+ // see org.eclipse.debug.internal.ui.viewers.update.EventHandlerModelProxy.dispatchResume(...)
+ try {
+ Thread.sleep(700);
+ } catch (final InterruptedException e) {
+ }
+ }
+
+ /**
+ * This class is registered as IDebugEventSetListener to get TERMINATE information during an unnormal end of
+ * the runtime process (when no terminate communication-event is thrown)<br>
+ * In this case a DebugEvent.TERMINATE is fired with an IProcess source.<br>
+ * Another terminate event must be fired here with the DebugTarget source. This is necessary because some
+ * listeners don't cleanup completely if there is only a terminate event with source = IProcess
+ *
+ * @see org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
+ */
+ public void handleDebugEvents(DebugEvent[] events) {
+ for (int i = 0; i < events.length; i++) {
+ DebugEvent event = events[i];
+ if (event.getKind() == DebugEvent.TERMINATE) {
+ DebugPlugin.getDefault().removeDebugEventListener(this);
+ DebugPlugin.getDefault().getBreakpointManager().removeBreakpointListener(target);
+ getThread().clearStack(0);
+ target.removeThread();
+ fireTerminateEvent();
+ }
+ }
+ }
+
+ private boolean shallStopInMain() {
+ try {
+ return target.getLaunch().getLaunchConfiguration().getAttribute(
+ IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, true);
+ } catch (CoreException e) {
+ return true;
+ }
+ }
+
+ private boolean checkBreakPoint() {
+ IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(
+ MWEBreakpoint.DEBUG_MODEL_ID);
+ DebugStackFrame frame = getThread().getStackFramePeek();
+ for (IBreakpoint bp : breakpoints) {
+ if (((MWEBreakpoint) bp).equals(frame.getCharStart(), frame.getResource())) {
+ getThread().setBreakpoint((MWEBreakpoint) bp);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // ********************************************************* type sending
+
+ public void requireStepInto() throws DebugException {
+ getThread().setStepping(true);
+ cmdHandler.sendStepIntoCommand();
+ }
+
+ public void requireStepOver() throws DebugException {
+ getThread().setStepping(true);
+ cmdHandler.sendStepOverCommand();
+ }
+
+ public void requireStepReturn() throws DebugException {
+ getThread().setStepping(true);
+ cmdHandler.sendStepReturnCommand();
+ }
+
+ public void requireResume() throws DebugException {
+ getThread().setStepping(false);
+ cmdHandler.sendResumeCommand();
+ }
+
+ public void requireSuspend() throws DebugException {
+ cmdHandler.sendSuspendCommand();
+ }
+
+ public void requireTerminate() throws DebugException {
+ cmdHandler.sendTerminateCommand();
+ }
+
+ // -------------------------------------------------------------------------
+
+ public List<VarValueTO> requireVariables(int frameId) throws DebugException {
+ try {
+ List<VarValueTO> vars = varHandler.sendRequireVariables(frameId);
+ target.updateDebugValues(vars);
+ return vars;
+ } catch (IOException e) {
+ handleIOProblem(e);
+ return null; // does not occur, because handleIOProblem throws always an exception
+ }
+ }
+
+ // we send the frame id and the var id; the frame id is used to get the correct adapter
+ // example: an object could occur in a workflow slot (which is handled by the workflow adapter
+ // later in the execution context the string representation may be rendered differently by another adapter
+ public List<VarValueTO> requireSubVariables(int varId) throws DebugException {
+ int frameId = target.getThread().getVarFrameId();
+ try {
+ List<VarValueTO> vars = varHandler.sendRequireSubVariables(frameId, varId);
+ target.updateDebugValues(vars);
+ return vars;
+ } catch (IOException e) {
+ handleIOProblem(e);
+ return null; // does not occur, because handleIOProblem throws always an exception
+ }
+ }
+
+ public void requireSetBreakpoint(MWEBreakpoint bp) throws DebugException {
+ try {
+ bpHandler.sendSetBreakpoint(bp);
+ } catch (IOException e) {
+ handleIOProblem(e);
+ }
+ }
+
+ public void requireRemoveBreakpoint(MWEBreakpoint bp) throws DebugException {
+ try {
+ bpHandler.sendRemoveBreakpoint(bp);
+ } catch (IOException e) {
+ handleIOProblem(e);
+ }
+ }
+
+ public void handleIOProblem(Exception e) throws DebugException {
+ throw new DebugException(Activator.createErrorStatus(
+ "lost connection to debugger runtime process --> aborting", e));
+ }
+
+ // *************************************** forward events to the DebugPlugin
+
+ private void fireCreationEvent() {
+ fireEvent(new DebugEvent(target, DebugEvent.CREATE));
+ }
+
+ private void fireResumeEvent(int detail) {
+ fireEvent(new DebugEvent(getThread(), DebugEvent.RESUME, detail));
+ }
+
+ private void fireSuspendEvent(int detail) {
+ fireEvent(new DebugEvent(getThread(), DebugEvent.SUSPEND, detail));
+ }
+
+ private void fireTerminateEvent() {
+ fireEvent(new DebugEvent(target, DebugEvent.TERMINATE));
+ }
+
+ private void fireEvent(DebugEvent event) {
+ DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { event });
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginAdapter.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginAdapter.java
new file mode 100644
index 0000000..d5d97a3
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginAdapter.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * An adapter to the MWE debug model that handle all element type specific activities on the Eclipse side.<br>
+ * That is breakpoint handling and assignment of the right editor for source lookup.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface PluginAdapter {
+
+ public boolean canHandleResourceExtension(String ext);
+
+ public boolean canHandleType(String type);
+
+ public String getEditorId();
+
+ public Image getIcon();
+
+ public MWEBreakpoint createBreakpoint(IResource resource, int start, int end, int line) throws CoreException;
+
+ public IBreakpoint checkBreakpoints(IBreakpoint[] bps, IResource resource, int start, int end, int line) throws CoreException;
+
+ public boolean isToggleBpEnabled(IResource resource, int start, int end, int line);
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginExtensionManager.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginExtensionManager.java
new file mode 100644
index 0000000..36ce6bd
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginExtensionManager.java
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.RegisterPacket;
+import org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler;
+import org.eclipse.emf.mwe.internal.core.debug.processing.handlers.EventRuntimeHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.BreakpointPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.CommandPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.EventPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.handlers.VariablesPluginHandler;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+
+/**
+ * This class handles all handler and adapter extensions provided by other eclipse plugins.<br>
+ * It is implemented as a singleton, that is instantiated at first usage, what could be breakpoint toggling or
+ * debugger run.<br>
+ * The plugin adapters are collected at instantiation time, all handlers and runtime adapters will be collected
+ * during init, since they depend on the existence of a DebugModelManager.<br>
+ * Since there is a new DebugModelManager for every debugger run, the init method will be called multiple times.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class PluginExtensionManager {
+
+ private static PluginExtensionManager singleton;
+
+ private Set<PluginAdapter> pluginAdapters = new HashSet<PluginAdapter>();
+
+ private boolean missingAdapterReported;
+
+ private Connection connection;
+
+ private DebugModelManager dmm;
+
+ // -------------------------------------------------------------------------
+
+ public static PluginExtensionManager getDefault() {
+ if (singleton == null)
+ singleton = new PluginExtensionManager();
+ return singleton;
+ }
+
+ private PluginExtensionManager() {
+ collectPluginAdaptersFromExtensions();
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void init(DebugModelManager dmm, Connection connection) throws DebugException {
+ this.dmm = dmm;
+ this.connection = connection;
+ try {
+ collectInitialCommunicationHandlers();
+ collectHandlersFromExtensions();
+ collectRuntimeAdaptersFromExtensions();
+ } catch (IOException e) {
+ dmm.handleIOProblem(e);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+
+ public PluginAdapter getAdapterByResourceExtension(String ext) {
+ for (PluginAdapter adapter : pluginAdapters)
+ if (adapter.canHandleResourceExtension(ext))
+ return adapter;
+ if (!missingAdapterReported) {
+ String msg = "Warning: Debug system initialization problem.\nDidn't find a plugin adapter for the file extension: '"
+ + ext + "'";
+ Activator.logError(msg, null);
+ Activator.showError(msg);
+ missingAdapterReported = true;
+ }
+ return null;
+ }
+
+ public PluginAdapter getAdapterByType(String type) {
+ for (PluginAdapter adapter : pluginAdapters)
+ if (adapter.canHandleType(type))
+ return adapter;
+ if (!missingAdapterReported) {
+ String msg = "Warning: Debug system initialization problem.\nDidn't find a plugin adapter for type: '"
+ + type + "'";
+ Activator.logError(msg, null);
+ Activator.showError(msg);
+ missingAdapterReported = true;
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void collectInitialCommunicationHandlers() throws IOException {
+ RegisterPacket packet = new RegisterPacket();
+ packet.type = RegisterPacket.HANDLERS;
+
+ CommandPluginHandler cHandler = new CommandPluginHandler();
+ cHandler.setConnection(connection);
+ dmm.setCmdHandler(cHandler);
+ packet.classNames.add(CommandRuntimeHandler.class.getName());
+
+ EventPluginHandler eHandler = new EventPluginHandler();
+ eHandler.setConnection(connection);
+ eHandler.startListener();
+ eHandler.setDmm(dmm);
+ packet.classNames.add(EventRuntimeHandler.class.getName());
+
+ connection.sendPacket(packet);
+ }
+
+ private void collectHandlersFromExtensions() throws IOException {
+ RegisterPacket packet = new RegisterPacket();
+ packet.type = RegisterPacket.HANDLERS;
+ IExtensionRegistry reg = Platform.getExtensionRegistry();
+ IConfigurationElement[] elems = reg
+ .getConfigurationElementsFor("org.eclipse.emf.mwe.ui.debugHandlers");
+ for (IConfigurationElement elem : elems) {
+ if (elem.getName().equals("handler")) {
+
+ String className = elem.getAttribute("runtimeClass");
+ if (className != null)
+ packet.classNames.add(className);
+
+ PluginHandler handler = null;
+ className = elem.getAttribute("pluginClass");
+ if (className != null)
+ try {
+ handler = (PluginHandler) elem.createExecutableExtension("pluginClass");
+ } catch (CoreException e) {
+ Activator.logError("Internal configuration error.\nCouldn't instantiate "
+ + elem.getAttribute("pluginClass"), e);
+ }
+ if (handler != null) {
+ handler.setConnection(connection);
+ if ("variablesHandler".equals(elem.getAttribute("type")))
+ dmm.setVariablesHandler((VariablesPluginHandler) handler);
+ else if ("breakpointHandler".equals(elem.getAttribute("type")))
+ dmm.setBreakpointHandler((BreakpointPluginHandler) handler);
+ else
+ handler.setDebugModelManager(dmm);
+ }
+ }
+ }
+ if (!dmm.hasRequiredHandlers()) {
+ String msg = "Debug system initialization problem.\nSome required debugger handlers are not assigned.";
+ Activator.showError(msg);
+ Activator.logError(msg, null);
+ }
+ // TODO: CK: test: what happens when a handler is not there? Exception? to be tested and corrected if necessary
+
+ connection.sendPacket(packet);
+ }
+
+ private void collectRuntimeAdaptersFromExtensions() throws IOException {
+ RegisterPacket packet = new RegisterPacket();
+ packet.type = RegisterPacket.ADAPTERS;
+ IExtensionRegistry reg = Platform.getExtensionRegistry();
+ IConfigurationElement[] elems = reg
+ .getConfigurationElementsFor("org.eclipse.emf.mwe.ui.debugAdapters");
+ for (IConfigurationElement elem : elems)
+ if (elem.getName().equals("adapter")) {
+ String className = elem.getAttribute("runtimeClass");
+ if (className != null)
+ packet.classNames.add(className);
+ }
+ connection.sendPacket(packet);
+
+ }
+
+ private void collectPluginAdaptersFromExtensions() {
+ IExtensionRegistry reg = Platform.getExtensionRegistry();
+ IConfigurationElement[] elems = reg
+ .getConfigurationElementsFor("org.eclipse.emf.mwe.ui.debugAdapters");
+ for (IConfigurationElement elem : elems) {
+ if (elem.getName().equals("adapter")) {
+ PluginAdapter adapter = null;
+ String className = elem.getAttribute("pluginClass");
+ if (className != null)
+ try {
+ adapter = (PluginAdapter) elem.createExecutableExtension("pluginClass");
+ } catch (CoreException e) {
+ Activator.logError("Internal configuration error.\nCouldn't instantiate "
+ + elem.getAttribute("pluginClass"), e);
+ }
+ if (adapter != null)
+ pluginAdapters.add(adapter);
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginHandler.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginHandler.java
new file mode 100644
index 0000000..d62565c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/PluginHandler.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+
+/**
+ * base interface for handlers that support the debugger on the eclipse side
+ */
+public interface PluginHandler {
+ public void setConnection(Connection connection);
+
+ public void setDebugModelManager(DebugModelManager dmm);
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/BreakpointPluginHandler.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/BreakpointPluginHandler.java
new file mode 100644
index 0000000..d389ff5
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/BreakpointPluginHandler.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing.handlers;
+
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.BreakpointRuntimeHandler.REMOVE;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.BreakpointRuntimeHandler.SET;
+
+import java.io.IOException;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.BreakpointPacket;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginHandler;
+
+/**
+ * This class handles the communication of breakpoints on the Eclipse side
+ */
+public class BreakpointPluginHandler implements PluginHandler {
+
+ private Connection connection;
+
+ // -------------------------------------------------------------------------
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ public void setDebugModelManager(DebugModelManager dmm) {
+ // don't need it
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void sendSetBreakpoint(MWEBreakpoint bp) throws IOException {
+ connection.sendPacket(new BreakpointPacket(SET, bp.createTO()));
+ }
+
+ public void sendRemoveBreakpoint(MWEBreakpoint bp) throws IOException {
+ connection.sendPacket(new BreakpointPacket(REMOVE, bp.createTO()));
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/CommandPluginHandler.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/CommandPluginHandler.java
new file mode 100644
index 0000000..5bf904f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/CommandPluginHandler.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing.handlers;
+
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.RESUME;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.STEP_INTO;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.STEP_OVER;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.STEP_RETURN;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.SUSPEND;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.CommandRuntimeHandler.TERMINATE;
+
+import java.io.IOException;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.CommandPacket;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+
+/**
+ * This class handles the communication of debug command actions on the Eclipse side
+ */
+public class CommandPluginHandler {
+
+ private Connection connection;
+
+ // -------------------------------------------------------------------------
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void sendStepIntoCommand() throws DebugException {
+ sendCommand(STEP_INTO);
+ }
+
+ public void sendStepOverCommand() throws DebugException {
+ sendCommand(STEP_OVER);
+ }
+
+ public void sendStepReturnCommand() throws DebugException {
+ sendCommand(STEP_RETURN);
+ }
+
+ public void sendResumeCommand() throws DebugException {
+ sendCommand(RESUME);
+ }
+
+ public void sendSuspendCommand() throws DebugException {
+ sendCommand(SUSPEND);
+ }
+
+ public void sendTerminateCommand() throws DebugException {
+ sendCommand(TERMINATE);
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void sendCommand(int type) throws DebugException {
+ try {
+ connection.sendPacket(new CommandPacket(type));
+ } catch (IOException e) {
+ throw new DebugException(Activator
+ .createErrorStatus("lost connection to debugger runtime process", e));
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/EventPluginHandler.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/EventPluginHandler.java
new file mode 100644
index 0000000..c733090
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/EventPluginHandler.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing.handlers;
+
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.EventRuntimeHandler.RESUMED;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.EventRuntimeHandler.STARTED;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.EventRuntimeHandler.SUSPENDED;
+import static org.eclipse.emf.mwe.internal.core.debug.processing.handlers.EventRuntimeHandler.TERMINATED;
+
+import java.io.IOException;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.AbstractPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.ConfirmationPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.EventPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.EventPacketWithFrames;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+
+/**
+ * This class handles the distribution of debug events on the Eclipse side.<br>
+ * It listens in an extra thread for events from the runtime process and forwards them to the
+ * <code>DebugModelManager</code>.
+ */
+public class EventPluginHandler implements Runnable {
+
+ private Connection connection;
+
+ private DebugModelManager dmm;
+
+ private Class<? extends AbstractPacket> typeToListen = EventPacket.class;
+
+ // -------------------------------------------------------------------------
+
+ public EventPluginHandler() {
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void setDmm(DebugModelManager dmm) {
+ this.dmm = dmm;
+ }
+
+ public Class<? extends AbstractPacket> getPacketType() {
+ return typeToListen;
+ }
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ // -------------------------------------------------------------------------
+
+ public void startListener() {
+ Thread thread = new Thread(this, getClass().getSimpleName());
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ public void run() {
+ try {
+ while (true)
+ dispatch((EventPacket) connection.listenForPacket(typeToListen));
+ } catch (Exception e) {
+ connection.close();
+ }
+ }
+
+ private void dispatch(EventPacket packet) throws DebugException {
+ dmm.getThread().setBreakpoint(null);
+
+ switch (packet.event) {
+ case STARTED:
+ dmm.debuggerStarted();
+ break;
+ case SUSPENDED:
+ adaptStackFrames(packet);
+ dmm.debuggerSuspended();
+ break;
+ case RESUMED:
+ dmm.debuggerResumed();
+ break;
+ case TERMINATED:
+ dmm.debuggerTerminated();
+ break;
+ default:
+ Activator.logError("Internal error.\nInvalid event received: " + packet.event, null);
+ return;
+ }
+
+ ConfirmationPacket conf = new ConfirmationPacket(packet.getId());
+ try {
+ connection.sendPacket(conf);
+ } catch (IOException e) {
+ throw new DebugException(Activator.createErrorStatus(
+ "lost connection to debugger runtime process --> aborting", e));
+ }
+ }
+
+ private void adaptStackFrames(EventPacket sp) {
+ EventPacketWithFrames packet = (EventPacketWithFrames) sp;
+ dmm.adaptStackFrames(packet.cleanStackLevel, packet.frames);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/VariablesPluginHandler.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/VariablesPluginHandler.java
new file mode 100644
index 0000000..8a14f13
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/processing/handlers/VariablesPluginHandler.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.processing.handlers;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.RequireVarPacket;
+import org.eclipse.emf.mwe.internal.core.debug.communication.packets.VarDataPacket;
+import org.eclipse.emf.mwe.internal.core.debug.model.VarValueTO;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.DebugModelManager;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginHandler;
+
+/**
+ * This class handles the communication of variable values on the Eclipse side
+ */
+public class VariablesPluginHandler implements PluginHandler {
+
+ private Connection connection;
+
+ // -------------------------------------------------------------------------
+
+ public void setConnection(Connection connection) {
+ this.connection = connection;
+ }
+
+ public void setDebugModelManager(DebugModelManager dmm) {
+ // don't need it
+ }
+
+ // -------------------------------------------------------------------------
+
+ public List<VarValueTO> sendRequireVariables(int frameId) throws IOException {
+ RequireVarPacket packet = new RequireVarPacket(frameId, 0);
+ int refId = connection.sendPacket(packet);
+ return ((VarDataPacket) connection.listenForPacket(VarDataPacket.class, refId)).valueList;
+ }
+
+ public List<VarValueTO> sendRequireSubVariables(int frameId, int varId) throws IOException {
+ RequireVarPacket packet = new RequireVarPacket(frameId, varId);
+ int refId = connection.sendPacket(packet);
+ return ((VarDataPacket) connection.listenForPacket(VarDataPacket.class, refId)).valueList;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupDirector.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupDirector.java
new file mode 100644
index 0000000..df46d75
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupDirector.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
+
+public class MWESourceLookupDirector extends AbstractSourceLookupDirector {
+
+ public void initializeParticipants() {
+ addParticipants(new ISourceLookupParticipant[]{new MWESourceLookupParticipant()});
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupParticipant.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupParticipant.java
new file mode 100644
index 0000000..50c4d99
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourceLookupParticipant.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugStackFrame;
+
+/**
+ * The source lookup participant knows how to translate a stack frame into a source file name
+ */
+public class MWESourceLookupParticipant extends AbstractSourceLookupParticipant {
+
+ public String getSourceName(Object object) throws CoreException {
+ if (object instanceof DebugStackFrame) {
+ return ((DebugStackFrame) object).getResource();
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourcePathComputerDelegate.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourcePathComputerDelegate.java
new file mode 100644
index 0000000..be0e397
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/MWESourcePathComputerDelegate.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourcePathComputerDelegate;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+import org.eclipse.jdt.launching.JavaRuntime;
+
+public class MWESourcePathComputerDelegate implements ISourcePathComputerDelegate {
+ /**
+ * returns all SourceContainer corresponding to the entries as defined in the base project of the launch
+ * configuration. The classpath resolving process is used from JavaRuntime, but we use our own container creator
+ */
+ public ISourceContainer[] computeSourceContainers(ILaunchConfiguration configuration, IProgressMonitor monitor)
+ throws CoreException {
+ IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedSourceLookupPath(configuration);
+ IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveSourceLookupPath(entries, configuration);
+
+ ISourceContainer[] containers = SourceLookupUtil.translate(resolved);
+ return containers;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/PackageFragmentRootContainer.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/PackageFragmentRootContainer.java
new file mode 100644
index 0000000..5e48841
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/PackageFragmentRootContainer.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
+import org.eclipse.debug.core.sourcelookup.containers.AbstractSourceContainer;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+
+/**
+ * adapted from
+ * org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer
+ * but doesn't look only for .java and .class files
+ */
+public class PackageFragmentRootContainer extends AbstractSourceContainer {
+
+ private IPackageFragmentRoot fRoot;
+
+ public static final String TYPE_ID = Activator.PLUGIN_ID + ".packageFragmentRootContainer";
+
+ public PackageFragmentRootContainer(IPackageFragmentRoot root) {
+ fRoot = root;
+ }
+
+ public Object[] findSourceElements(String name) throws CoreException {
+ int index = name.lastIndexOf('.');
+ String typeName = name;
+ String suffix = "";
+ if (index >= 0) {
+ suffix = name.substring(index);
+ typeName = typeName.substring(0, index);
+ }
+ typeName = typeName.replace('/', '.');
+ typeName = typeName.replace('\\', '.');
+ index = typeName.lastIndexOf('.');
+ String packageName = "";
+ if (index >= 0) {
+ packageName = typeName.substring(0, index);
+ typeName = typeName.substring(index + 1);
+ }
+
+ IPackageFragment fragment = fRoot.getPackageFragment(packageName);
+ if (fragment.exists()) {
+ String elementName = typeName + suffix;
+ Object[] resources = fragment.getNonJavaResources();
+ for (Object resource : resources) {
+ if (resource instanceof IStorage) {
+ IStorage storage = (IStorage) resource;
+ if (elementName.equals(storage.getName()))
+ return new Object[] { resource };
+ }
+ }
+ }
+ return EMPTY;
+ }
+
+ public String getName() {
+ return fRoot.getElementName();
+ }
+
+ public ISourceContainerType getType() {
+ return getSourceContainerType(TYPE_ID);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return obj instanceof PackageFragmentRootContainer
+ && ((PackageFragmentRootContainer) obj)
+ .getPackageFragmentRoot().equals(
+ getPackageFragmentRoot());
+ }
+
+ public IPackageFragmentRoot getPackageFragmentRoot() {
+ return fRoot;
+ }
+
+ @Override
+ public int hashCode() {
+ return fRoot.hashCode();
+ }
+
+ public IPath getPath() {
+ return getPackageFragmentRoot().getPath();
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceFolderSourceContainer.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceFolderSourceContainer.java
new file mode 100644
index 0000000..81a5215
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceFolderSourceContainer.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
+import org.eclipse.debug.core.sourcelookup.containers.CompositeSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer;
+
+/**
+ * Source container that captures all declared source folders of an underlying java project.
+ *
+ * Adapted from JavaProjectSourceContainer but searches for all kinds of names, not only for java-like named resources
+ */
+public class SourceFolderSourceContainer extends CompositeSourceContainer {
+
+ // Java project
+ private IJavaProject fProject;
+
+ // Source folders
+ private ISourceContainer[] fSourceFolders;
+
+ public static final String TYPE_ID = Activator.PLUGIN_ID + ".sourceFolderSourceContainer";
+
+ public SourceFolderSourceContainer(IJavaProject project) {
+ if (project == null)
+ throw new IllegalArgumentException();
+ fProject = project;
+ }
+
+ public String getName() {
+ return fProject.getElementName();
+ }
+
+ public ISourceContainerType getType() {
+ return getSourceContainerType(TYPE_ID);
+ }
+
+ /**
+ * create a FolderSourceContainer for each declared source folder of the java project
+ */
+ @Override
+ protected ISourceContainer[] createSourceContainers() throws CoreException {
+ if (fSourceFolders == null) {
+ List<ISourceContainer> containers = new ArrayList<ISourceContainer>();
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ if (fProject.getProject().isOpen()) {
+ IClasspathEntry[] entries = fProject.getRawClasspath();
+ for (int i = 0; i < entries.length; i++) {
+ IClasspathEntry entry = entries[i];
+ switch (entry.getEntryKind()) {
+ case IClasspathEntry.CPE_SOURCE:
+ IPath path = entry.getPath();
+ IResource resource = root.findMember(path);
+ if (resource instanceof IContainer) {
+ containers.add(new FolderSourceContainer((IContainer) resource, false));
+ }
+ break;
+ }
+ }
+ }
+ fSourceFolders = containers.toArray(new ISourceContainer[containers.size()]);
+ }
+ return fSourceFolders;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj instanceof JavaProjectSourceContainer) {
+ return fProject.equals(obj);
+ }
+ return super.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return fProject.hashCode();
+ }
+
+ @Override
+ public Object[] findSourceElements(String name) throws CoreException {
+ // force container initialization
+ getSourceContainers();
+ return findSourceElements(name, fSourceFolders);
+ }
+
+ @Override
+ public void dispose() {
+ fSourceFolders = null;
+ super.dispose();
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceLookupUtil.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceLookupUtil.java
new file mode 100644
index 0000000..671f8ac
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/debug/sourcelookup/SourceLookupUtil.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Clemens Kadura (zAJKa) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.debug.sourcelookup;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.ExternalArchiveSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IJavaModel;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
+
+/**
+ * adapted from org.eclipse.jdt.internal.launching.JavaSourceLookupUtil<br>
+ * - doesn't look only for .java and .class files<br>
+ * - no check for source lookups as MWE files are sources themselves
+ */
+public class SourceLookupUtil {
+
+ private static IJavaModel model;
+
+ /**
+ * Translates the given runtime classpath entries into associated source containers.
+ */
+ public static ISourceContainer[] translate(IRuntimeClasspathEntry[] entries) {
+ List<ISourceContainer> containers = new ArrayList<ISourceContainer>(entries.length);
+ for (IRuntimeClasspathEntry entry : entries) {
+ ISourceContainer container = null;
+ switch (entry.getType()) {
+ case IRuntimeClasspathEntry.ARCHIVE:
+ IPackageFragmentRoot root = getPackageFragmentRoot(entry);
+ if (root == null) {
+ String path = entry.getLocation();
+ File file = new File(path);
+ if (file.isDirectory()) {
+ IResource resource = entry.getResource();
+ if (resource instanceof IContainer)
+ container = new FolderSourceContainer((IContainer) resource, false);
+ else
+ container = new DirectorySourceContainer(file, false);
+ } else
+ container = new ExternalArchiveSourceContainer(path, true);
+ } else {
+ container = new PackageFragmentRootContainer(root);
+ }
+ break;
+ case IRuntimeClasspathEntry.PROJECT:
+ IResource resource = entry.getResource();
+ if (resource != null && resource.getType() == IResource.PROJECT) {
+ IJavaProject javaProject = JavaCore.create((IProject) resource);
+ if (javaProject.exists())
+ container = new SourceFolderSourceContainer(javaProject);
+ else if (resource.exists())
+ container = new ProjectSourceContainer((IProject) resource, false);
+ }
+ break;
+ default:
+ // no other classpath types are valid in a resolved path
+ break;
+ }
+ if (container != null && !containers.contains(container)) {
+ containers.add(container);
+ }
+ }
+ return containers.toArray(new ISourceContainer[containers.size()]);
+ }
+
+ private static IPackageFragmentRoot getPackageFragmentRoot(IRuntimeClasspathEntry entry) {
+ IResource resource = entry.getResource();
+
+ if (resource != null) {
+ // our own project jars...
+ IProject project = resource.getProject();
+ IJavaProject jp = JavaCore.create(project);
+ if (project.isOpen() && jp.exists()) {
+ IPackageFragmentRoot root = jp.getPackageFragmentRoot(resource);
+ return root;
+ }
+ }
+
+ if (model == null)
+ model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
+
+ // ... or external jars, that are registered in one of the open projects at runtime
+ IPath reqPath = (resource == null ? new Path(entry.getLocation()) : entry.getPath());
+ try {
+ for (IJavaProject jp : model.getJavaProjects()) {
+ if (jp.getProject().isOpen())
+ for (IPackageFragmentRoot root : jp.getPackageFragmentRoots())
+ if (root.isExternal() && root.getPath().equals(reqPath))
+ return root;
+ }
+ } catch (JavaModelException e) {
+ Activator.logError(e); // should not occur
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWEDebuggerLauncher.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWEDebuggerLauncher.java
new file mode 100644
index 0000000..4c995e9
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWEDebuggerLauncher.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.eclipse.launch;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.emf.mwe.internal.core.debug.communication.Connection;
+import org.eclipse.emf.mwe.internal.ui.debug.model.DebugTarget;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.launching.AbstractVMRunner;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.SocketUtil;
+import org.eclipse.jdt.launching.VMRunnerConfiguration;
+
+/**
+ * The Launcher starts the workflow execution process in a new runtime VM.<br>
+ * It establishes the socket connection for communication between the runtime VM and the debugger framework.<br>
+ * It instantiates the debug model representation.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWEDebuggerLauncher extends AbstractVMRunner {
+ private IVMInstall vm;
+
+ public MWEDebuggerLauncher(IVMInstall vmInstance) {
+ vm = vmInstance;
+ }
+
+ @Override
+ protected String getPluginIdentifier() {
+ return Activator.PLUGIN_ID;
+ }
+
+ @SuppressWarnings("null")
+ public void run(VMRunnerConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException {
+
+ // port for communication between runtime VM and Eclipse
+ int commPort = SocketUtil.findFreePort();
+ if (commPort == -1) {
+ throw new DebugException(Activator.createErrorStatus(
+ "Unable to find free port to start communication with debugger runtime VM" + " --> aborting",
+ null));
+ }
+
+ // params for rumtime VM start
+ String[] cmdLine = renderCommandLine(config, commPort);
+ File workingDir = new File(config.getWorkingDirectory());
+ String[] envp = config.getEnvironment();
+
+ Connection connection = new Connection();
+
+ Process p = null;
+ try {
+
+ try {
+ connection.startListeningSocket(commPort);
+ } catch (IOException e) {
+ throw new DebugException(Activator.createErrorStatus(
+ "Unable to start debugger listening socket on port " + commPort + " --> aborting", e));
+ }
+
+ ConnectRunnable runnable = startListeningThread(connection);
+
+ // start runtime VM
+ p = DebugPlugin.exec(cmdLine, workingDir, envp);
+ if (p == null) {
+ throw new DebugException(Activator.createErrorStatus(
+ "Couldn't start Debugger runtime process --> aborting", null));
+ }
+
+ // instantiate MWE debug model to support Eclipse
+ IProcess process = DebugPlugin.newProcess(launch, p, renderProcessLabel("Debugger Process"));
+
+ // wait for runtime process connected to the server socket
+ while (runnable.isRunning() && !process.isTerminated()) {
+ if (monitor.isCanceled()) {
+ p.destroy();
+ runnable.cancel();
+ }
+ try {
+ if (p.exitValue() != 0)
+ runnable.cancel();
+ } catch (IllegalThreadStateException e) {
+ // occurs in normal process (p is still running)
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ Exception e = runnable.getException();
+ if (e != null || process.isTerminated()) {
+ if (runnable.isRunning())
+ runnable.cancel();
+ throw new DebugException(Activator.createErrorStatus(
+ "Debugger runtime process didn't respond properly --> aborting", null));
+ }
+ DebugTarget.newDebugTarget(launch, process, connection);
+ } catch (CoreException e) {
+ if (p != null)
+ p.destroy();
+ connection.close();
+ throw e;
+ }
+ }
+
+ private String[] renderCommandLine(VMRunnerConfiguration config, int commPort) throws CoreException {
+ // program string
+ List<String> arguments = new ArrayList<String>();
+ arguments.add(findJavaExecutable());
+
+ // VM arguments
+ String[] vmArgs = config.getVMArguments();
+ if (vmArgs != null)
+ for (int i = 0; i < vmArgs.length; i++)
+ arguments.add(vmArgs[i]);
+
+ // classpath
+ String[] cp = config.getClassPath();
+ if (cp.length > 0) {
+ arguments.add("-classpath");
+ StringBuilder cpSb = new StringBuilder();
+ for (String cpEntry : cp) {
+ cpSb.append(cpEntry);
+ cpSb.append(File.pathSeparator);
+ }
+ arguments.add(cpSb.substring(0, cpSb.lastIndexOf(File.pathSeparator)));
+ }
+ // TODO: ER: make sure that all runtime classes that are provided by extensions (handlers, adapters) are in the class path
+
+ // the class to launch
+ arguments.add(config.getClassToLaunch());
+
+ // programArgs
+ String[] progArgs = config.getProgramArguments();
+ for (int i = 0; i < progArgs.length; i++)
+ arguments.add(progArgs[i]);
+
+ arguments.add("" + commPort);
+
+ String[] cmdLine = new String[arguments.size()];
+ arguments.toArray(cmdLine);
+ return cmdLine;
+ }
+
+ private String findJavaExecutable() throws CoreException {
+
+ char fgSeparator = File.separatorChar;
+ String[] fgCandidateJavaLocations = { "bin" + fgSeparator + "javaw", "bin" + fgSeparator + "javaw.exe",
+ "jre" + fgSeparator + "bin" + fgSeparator + "javaw",
+ "jre" + fgSeparator + "bin" + fgSeparator + "javaw.exe", "bin" + fgSeparator + "java",
+ "bin" + fgSeparator + "java.exe", "jre" + fgSeparator + "bin" + fgSeparator + "java",
+ "jre" + fgSeparator + "bin" + fgSeparator + "java.exe" };
+ File vmInstallLocation = vm.getInstallLocation();
+ for (int i = 0; i < fgCandidateJavaLocations.length; i++) {
+ File javaFile = new File(vmInstallLocation, fgCandidateJavaLocations[i]);
+ if (javaFile.isFile()) {
+ return javaFile.getAbsolutePath();
+ }
+ }
+ throw new DebugException(Activator.createErrorStatus("Unable to locate executable for " + vm.getName()
+ + " --> aborting", null));
+ }
+
+ private static String renderProcessLabel(String command) {
+ String timestamp = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(
+ new Date(System.currentTimeMillis()));
+ return command + " (" + timestamp + ")";
+ }
+
+ /** ************************************************************************* */
+
+ private ConnectRunnable startListeningThread(Connection connector) {
+ ConnectRunnable runnable = new ConnectRunnable(connector);
+ Thread connectThread = new Thread(runnable, "Listening Connector");
+ runnable.setThread(connectThread);
+ connectThread.setDaemon(true);
+ connectThread.start();
+ return runnable;
+ }
+
+ class ConnectRunnable implements Runnable {
+ private Connection fConnector = null;
+
+ private Exception fException = null;
+
+ private Thread thread = null;
+
+ public ConnectRunnable(Connection connector) {
+ fConnector = connector;
+ }
+
+ public void run() {
+ try {
+ int timeout = JavaRuntime.getPreferences().getInt(JavaRuntime.PREF_CONNECT_TIMEOUT);
+ fConnector.accept(timeout);
+ } catch (Exception e) {
+ fException = e;
+ }
+ }
+
+ public void cancel() {
+ fConnector.close();
+ }
+
+ public Exception getException() {
+ return fException;
+ }
+
+ public void setThread(Thread thread) {
+ this.thread = thread;
+ }
+
+ public boolean isRunning() {
+ return thread.isAlive();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchConfigurationConstants.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchConfigurationConstants.java
new file mode 100644
index 0000000..26d5cfb
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchConfigurationConstants.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.eclipse.launch;
+
+/**
+ * Launch configuration constants that are used in addition to the <code>IJavaLaunchConfigurationConstants</code>
+ * ones.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public interface MWELaunchConfigurationConstants {
+
+ public static final String ATTR_MWE_WORKFLOW_FILE = "startWorkflow";
+
+ public static final String ATTR_MWE_JAVA_DEBUG_MODE = "java_debug";
+
+ // must match with the launchConfigurationType id from plugin.xml
+ public static final String WORKFLOW_LAUNCH_CONFIGURATION_TYPE_ID = "org.eclipse.emf.mwe.ui.MWELaunchConfigType";
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchDelegate.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchDelegate.java
new file mode 100644
index 0000000..e3e20c6
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchDelegate.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.eclipse.launch;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.emf.mwe.core.WorkflowRunner;
+import org.eclipse.emf.mwe.internal.core.debug.processing.DebugMonitor;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.VMRunnerConfiguration;
+
+/**
+ * This launch delegate decides in which mode to run the workflow execution process (run or debug) and redirects
+ * to the JavaLaunchDelegate or delegates to the WorkflowDebuggerLauncher.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWELaunchDelegate extends AbstractJavaLaunchConfigurationDelegate {
+
+ private static final String wfRunnerClassName = WorkflowRunner.class.getName();
+
+ private String wfFileName;
+
+ public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
+ throws CoreException {
+
+ if (monitor.isCanceled())
+ return;
+
+ monitor.beginTask("Launching VM...", 3);
+ monitor.worked(1);
+
+ // get file to execute
+ wfFileName = configuration.getAttribute(MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE,
+ (String) null);
+ if (wfFileName == null) {
+ throw new DebugException(Activator.createErrorStatus("Workflow file is not specified --> aborting",
+ null));
+ }
+
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(wfFileName));
+
+ // add abs. path because ResourceListSelectionDialog creates it relative
+ // to the WS-root
+ if (wfFileName.startsWith("/"))
+ wfFileName = file.getLocation().toString();
+
+ // check if file exist
+ if (!file.exists()) {
+ throw new DebugException(Activator.createErrorStatus("file " + file.getFullPath()
+ + " does not exist. --> aborting", null));
+ }
+
+ // register this class as listener for termination of the runtime process (see handleDebugEvents)
+ DebugPlugin.getDefault().addDebugEventListener(this);
+ boolean javaDebug = configuration.getAttribute(MWELaunchConfigurationConstants.ATTR_MWE_JAVA_DEBUG_MODE,
+ false);
+
+ if (!mode.equals(ILaunchManager.DEBUG_MODE) || javaDebug) {
+ // redirect to a JavaLauchDelegate; set config attributes accordingly
+ monitor.subTask("preparing Java launch...");
+
+ ILaunchConfigurationWorkingCopy wc = configuration.copy("JavaLaunch");
+
+ try {
+ final ILaunchConfigurationType configType = getLaunchManager().getLaunchConfigurationType(
+ IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
+ wc = configType.newInstance(null, configuration.getName());
+ } catch (final CoreException e) {
+ throw new DebugException(Activator.createErrorStatus(
+ "Error creating launch configuration. --> aborting", e));
+ }
+
+ wc.setAttributes(configuration.getAttributes());
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, wfRunnerClassName);
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "\"" + wfFileName + "\"");
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION, "workflow - " + wfFileName);
+
+ monitor.worked(1);
+ monitor.subTask("delegating to Java launch...");
+
+ Job[] autoBuildJobs;
+ Job[] manBuildJobs;
+ do {
+ autoBuildJobs = Job.getJobManager().find(ResourcesPlugin.FAMILY_AUTO_BUILD);
+ manBuildJobs = Job.getJobManager().find(ResourcesPlugin.FAMILY_MANUAL_BUILD);
+ } while (autoBuildJobs.length > 0 || manBuildJobs.length > 0);
+
+ getLaunchManager().removeLaunch(launch);
+
+ DebugUITools.launch(wc, mode);
+
+ } else {
+ monitor.subTask("preparing debugger launch...");
+
+ // runner
+ IVMInstall vm = JavaRuntime.computeVMInstall(configuration);
+ MWEDebuggerLauncher launcher = new MWEDebuggerLauncher(vm);
+
+ // classpath
+ String[] classpath = getClasspath(configuration);
+
+ // working dir
+ String workingDirName = null;
+ IJavaProject jp = getJavaProject(configuration);
+ if (jp != null) {
+ IProject p = jp.getProject();
+ workingDirName = p.getLocation().toFile().getAbsolutePath();
+ }
+
+ // program arguments
+ String[] progArgs = new String[3];
+ progArgs[0] = wfFileName;
+ progArgs[1] = "-m";
+ progArgs[2] = DebugMonitor.class.getName();
+
+ String vmArgs = configuration.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS,
+ (String) null);
+
+ // bundle config
+ VMRunnerConfiguration runnerConfig = new VMRunnerConfiguration(wfRunnerClassName, classpath);
+ runnerConfig.setWorkingDirectory(workingDirName);
+ runnerConfig.setProgramArguments(progArgs);
+ runnerConfig.setVMArguments(DebugPlugin.parseArguments(vmArgs));
+
+ monitor.worked(1);
+ monitor.subTask("launching debugger ...");
+
+ // run
+ launcher.run(runnerConfig, launch, monitor);
+ }
+ monitor.done();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.launching.AbstractJavaLaunchConfigurationDelegate#handleDebugEvents(org.eclipse.debug.core.DebugEvent[])
+ */
+ @Override
+ public void handleDebugEvents(DebugEvent[] events) {
+ for (int i = 0; i < events.length; i++) {
+ DebugEvent event = events[i];
+ if (event.getKind() == DebugEvent.TERMINATE) {
+ new Job("refresh resources") {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE,
+ monitor);
+ } catch (CoreException e) {
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+ }
+ super.handleDebugEvents(events);
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchShortcut.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchShortcut.java
new file mode 100644
index 0000000..48442f6
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/eclipse/launch/MWELaunchShortcut.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.eclipse.launch;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.ILaunchShortcut;
+import org.eclipse.emf.mwe.core.WorkflowRunner;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.core.search.SearchRequestor;
+import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ * This class is an action handler that responds to a context menu run or debug action.<br>
+ * It creates a launchConfiguration if there is non already for the specified workflow file, stores it and
+ * starts it in the resp. mode
+ *
+ * @author Sven Efftinge (http://www.efftinge.de)
+ * @author Clemens Kadura (zAJKa) - adapted for debugger
+ */
+public class MWELaunchShortcut implements ILaunchShortcut {
+
+ private IFile currFile;
+
+ private ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
+
+ public void launch(final ISelection selection, final String mode) {
+ if (selection instanceof IStructuredSelection) {
+ final IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+ final Object object = structuredSelection.getFirstElement();
+ if (object instanceof IAdaptable) {
+ currFile = (IFile) ((IAdaptable) object).getAdapter(IResource.class);
+ launch(mode);
+ }
+ }
+ }
+
+ public void launch(final IEditorPart editor, final String mode) {
+ final IEditorInput input = editor.getEditorInput();
+ currFile = (IFile) input.getAdapter(IFile.class);
+ launch(mode);
+ }
+
+ private void launch(final String mode) {
+ try {
+ locateWfRunner(currFile);
+ } catch (CoreException e) {
+ Activator.logError(e);
+ Activator.showError(e.getStatus());
+ return;
+ }
+
+ LaunchConfigurationInfo info = new LaunchConfigurationInfo(currFile);
+ ILaunchConfiguration[] configs;
+ ILaunchConfiguration config = null;
+ try {
+ configs = launchManager.getLaunchConfigurations();
+ for (ILaunchConfiguration configuration : configs)
+ if (info.configEquals(configuration)) {
+ config = configuration;
+ break;
+ }
+ if (config == null)
+ config = createConfiguration(info);
+ DebugUITools.launch(config, mode);
+ currFile.getProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
+ } catch (CoreException e) {
+ Activator.logError(e);
+ Activator.showError(e.getStatus());
+ return;
+ }
+ }
+
+ private void locateWfRunner(final IResource resource) throws CoreException {
+ if (!checkClasspathEntries(resource, WorkflowRunner.class.getName()))
+ throw new DebugException(Activator.createErrorStatus(
+ "Can't execute.\n MWE release jars are required in the project's classpath! --> aborting",
+ null));
+ }
+
+ private boolean checkClasspathEntries(final IResource resource, String classNameToFind) throws CoreException {
+ // TODO: ER: put required MWE packages always to the classpath
+ final IJavaProject project = JavaCore.create(resource.getProject());
+ final SearchPattern pattern = SearchPattern
+ .createPattern(classNameToFind, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS,
+ SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE);
+ final IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { project }, true);
+ final TypeDeclarationSearchRequestor requestor = new TypeDeclarationSearchRequestor();
+
+ final SearchEngine searchEngine = new SearchEngine();
+ searchEngine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
+ scope, requestor, null);
+ return requestor.match();
+ }
+
+ public class TypeDeclarationSearchRequestor extends SearchRequestor {
+
+ private IType match = null;
+
+ @Override
+ public void acceptSearchMatch(final SearchMatch match) {
+ this.match = (IType) match.getElement();
+ }
+
+ public boolean match() {
+ return match != null;
+ }
+ }
+
+ protected ILaunchConfiguration createConfiguration(final LaunchConfigurationInfo info) throws CoreException {
+ ILaunchConfiguration config = null;
+ ILaunchConfigurationWorkingCopy wc = null;
+ final ILaunchConfigurationType configType = launchManager
+ .getLaunchConfigurationType(MWELaunchConfigurationConstants.WORKFLOW_LAUNCH_CONFIGURATION_TYPE_ID);
+
+ // 2nd param is Name of the LaunchConfig in the Config Window
+ wc = configType.newInstance(null, launchManager.generateUniqueLaunchConfigurationNameFrom(info.name));
+
+ // the 4 values displayed in the Config main window
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, info.project);
+ wc.setAttribute(MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, info.wfFile);
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_STOP_IN_MAIN, false);
+ wc.setAttribute(MWELaunchConfigurationConstants.ATTR_MWE_JAVA_DEBUG_MODE, false);
+
+ // the values displayed in the VM arguments field
+ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, "-Xms40m\n-Xmx256m");
+
+ config = wc.doSave();
+
+ return config;
+ }
+
+ private class LaunchConfigurationInfo {
+ private String name;
+
+ private String project;
+
+ private String wfFile;
+
+ private LaunchConfigurationInfo(IFile file) {
+ name = file.getName();
+ project = file.getProject().getName();
+ wfFile = file.getFullPath().toString();
+ }
+
+ private boolean configEquals(final ILaunchConfiguration a) throws CoreException {
+ return wfFile.equals(a.getAttribute(MWELaunchConfigurationConstants.ATTR_MWE_WORKFLOW_FILE, "X"))
+ && project.equals(a.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "X"));
+ }
+
+ }
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/wizard/NewWorkflowFileWizard.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/wizard/NewWorkflowFileWizard.java
new file mode 100644
index 0000000..836bc9c
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/wizard/NewWorkflowFileWizard.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2006 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.wizard;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.WizardNewFileCreationPage;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+public class NewWorkflowFileWizard extends BasicNewResourceWizard {
+ private Page mainPage;
+
+ private String extension = "mwe";
+
+ String initialContents = "";
+ /*
+ * (non-Javadoc) Method declared on IWizard.
+ */
+ @Override
+ public void addPages() {
+ super.addPages();
+ mainPage = new Page(getSelection());//$NON-NLS-1$
+ addPage(mainPage);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWorkbenchWizard.
+ */
+
+ @Override
+ public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+ super.init(workbench, currentSelection);
+ setWindowTitle("New File");
+ setNeedsProgressMonitor(true);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on BasicNewResourceWizard.
+ */
+ @Override
+ protected void initializeDefaultPageImageDescriptor() {
+ ImageDescriptor desc =
+ // IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/newfile_wiz.png");//$NON-NLS-1$
+ AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.ui.ide", "$nl$/icons/full/wizban/newfile_wiz.png");
+ setDefaultPageImageDescriptor(desc);
+ }
+
+ @Override
+ public boolean canFinish() {
+ return mainPage.getFileName().endsWith("." + extension);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizard.
+ */
+ @Override
+ public boolean performFinish() {
+ final IFile file = mainPage.createNewFile();
+ if (file == null) {
+ return false;
+ }
+
+ selectAndReveal(file);
+ getShell().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ try {
+ IDE.openEditor(page, file, true);
+ } catch (PartInitException e) {
+ Activator.logError(e);
+ }
+ }
+ });
+ return true;
+ }
+
+ class Page extends WizardNewFileCreationPage {
+
+ public Page(IStructuredSelection selection) {
+ super("newFilePage1", selection);
+ setFileName("newWorkflowFile." + extension);
+ setTitle("New Workflow File");
+ setDescription("Creates a new Workflow File");
+ }
+
+ @Override
+ public String getErrorMessage() {
+ if (!getFileName().endsWith("." + extension))
+ return "file extension must be ." + extension;
+ return null;
+ }
+
+ @Override
+ protected InputStream getInitialContents() {
+ return new ByteArrayInputStream(initialContents.getBytes());
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/Activator.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/Activator.java
new file mode 100644
index 0000000..d1a02f8
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/Activator.java
@@ -0,0 +1,87 @@
+package org.eclipse.emf.mwe.internal.ui.workflow;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.emf.mwe.ui";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ public static void logError(Exception e) {
+ logError(e.getMessage(), e);
+ }
+
+ public static void logError(String msg, Exception e) {
+ logError(createErrorStatus(msg, e));
+ }
+
+ public static void logError(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ public static IStatus createErrorStatus(String msg, Exception e) {
+ return new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, msg, e);
+ }
+
+ public static void showError(final String msg) {
+ showError(createErrorStatus(msg, null));
+ }
+
+ public static void showError(final IStatus status) {
+ try {
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ ErrorDialog.openError(null, null, null, status);
+ }
+ });
+ } catch (Exception e) {
+ // e.g. NullPointerException if no active window
+ }
+ }
+
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/debug/MWEPluginAdapter.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/debug/MWEPluginAdapter.java
new file mode 100644
index 0000000..ac5929f
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/debug/MWEPluginAdapter.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2005 - 2007 committers of openArchitectureWare and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * committers of openArchitectureWare - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.mwe.internal.ui.workflow.debug;
+
+import static org.eclipse.emf.mwe.internal.core.debug.mwe.WorkflowElementAdapter.TYPE;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.emf.mwe.core.issues.Issues;
+import org.eclipse.emf.mwe.core.issues.IssuesImpl;
+import org.eclipse.emf.mwe.internal.core.ast.AbstractASTBase;
+import org.eclipse.emf.mwe.internal.core.ast.ComponentAST;
+import org.eclipse.emf.mwe.internal.core.ast.InclusionAST;
+import org.eclipse.emf.mwe.internal.core.ast.parser.Location;
+import org.eclipse.emf.mwe.internal.core.ast.parser.XmlLocationAnalyser;
+import org.eclipse.emf.mwe.internal.core.ast.util.WorkflowFactory;
+import org.eclipse.emf.mwe.internal.ui.debug.model.MWEBreakpoint;
+import org.eclipse.emf.mwe.internal.ui.debug.processing.PluginAdapter;
+import org.eclipse.emf.mwe.internal.ui.workflow.Activator;
+import org.eclipse.emf.mwe.internal.ui.workflow.util.PluginConfigurationElementUtil;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * The IPluginAdapter implementation for WorkflowComponents.
+ *
+ * @author Clemens Kadura (zAJKa)
+ */
+public class MWEPluginAdapter implements PluginAdapter {
+
+ private XmlLocationAnalyser locationAnalyser;
+ private static Set<String> extensions = new HashSet<String>();
+
+ static {
+ extensions.add("mwe");
+ extensions.add("oaw");
+ }
+
+ // -------------------------------------------------------------------------
+
+ public MWEPluginAdapter() {
+ this.locationAnalyser = new XmlLocationAnalyser();
+ }
+
+ public boolean canHandleResourceExtension(String ext) {
+ return getRequiredExtension().contains(ext);
+ }
+
+ public boolean canHandleType(String type) {
+ return TYPE.equals(type);
+ }
+
+ private Set<String> getRequiredExtension() {
+ return extensions;
+ }
+
+ public String getEditorId() {
+ IConfigurationElement[] configElements = PluginConfigurationElementUtil.getConfigElements("org.eclipse.ui.editors/" + "editor[extensions=mwe, oaw]");
+ for (IConfigurationElement element : configElements) {
+ if (element.getAttribute("default").equalsIgnoreCase("true")) {
+ return element.getAttribute("id");
+ }
+ }
+ return configElements.length != 0?configElements[0].getAttribute("id"):null;
+ }
+
+ public boolean isToggleBpEnabled(IResource resource, int start, int end, int line) {
+ return getComponentAstAtLine(resource, line) != null;
+ }
+
+ public MWEBreakpoint createBreakpoint(IResource resource, int start, int end, int line) throws CoreException {
+ // TODO: ER: allow BP on file's end tag (e.g. </workflow> )
+ ComponentAST comp = getComponentAstAtLine(resource, line);
+ if (comp == null)
+ return null;
+ // get the correct start and end of the tag
+ return new MWEBreakpoint(resource, getElementName(comp), comp.getLineNumber(), comp.getOffset(), comp.getLength());
+ }
+
+ public IBreakpoint checkBreakpoints(IBreakpoint[] bps, IResource resource, int start, int end, int line) throws CoreException {
+ ComponentAST comp = getComponentAstAtLine(resource, line);
+ if (comp == null)
+ return null;
+
+ Location loc = locationAnalyser.adapt(comp.getLocation());
+ for (IBreakpoint bp1 : bps) {
+ MWEBreakpoint bp = (MWEBreakpoint) bp1;
+ if (bp.getResource().equals(resource.getFullPath().toString()) && bp.getLine() == loc.getLineNumber()
+ && bp.getCharStart() == loc.getNameStart() && bp.getCharEnd() == loc.getNameEnd())
+ return bp;
+ }
+ return null;
+ }
+
+ // get the closest ComponentAst that surrounds the lineNumber
+ private ComponentAST getComponentAstAtLine(IResource resource, int lineNumber) {
+ IPath path = resource.getFullPath();
+ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+ String wfFileName = file.getLocation().toString();
+
+ final WorkflowFactory factory = new WorkflowFactory();
+ final Issues issues = new IssuesImpl();
+ final Map<String, String> params = new HashMap<String, String>();
+
+ AbstractASTBase wfAST = factory.parseAndInitialize(wfFileName, issues, params);
+ if (wfAST != null && wfAST instanceof ComponentAST) {
+ List<AbstractASTBase> candidates = ((ComponentAST) wfAST).getChildren();
+
+ AbstractASTBase candidate = null;
+ Location loc = null;
+ for (AbstractASTBase next : candidates) {
+ loc = locationAnalyser.adapt(next.getLocation());
+ next.setLocation(loc);
+ if (loc.getLineNumber() > lineNumber) {
+ if (candidate instanceof ComponentAST)
+ return (ComponentAST) candidate;
+ }
+ candidate = next;
+ }
+ if (candidate instanceof ComponentAST)
+ return (ComponentAST) candidate;
+ }
+ return null;
+ }
+
+ private String getElementName(ComponentAST ast) {
+ if (ast.getId() != null)
+ return ast.getId();
+ if (ast instanceof InclusionAST)
+ return ((InclusionAST) ast).getFile();
+ String clazz = new Path(ast.getClazz()).getFileExtension();
+ if (clazz != null)
+ return clazz;
+ return ast.getClazz();
+ }
+
+ private Image icon = null;
+
+ public Image getIcon() {
+ if (icon != null)
+ return icon;
+ IPath path = new Path("/icons/workflowfile.gif");
+ InputStream is = null;
+ try {
+ is = FileLocator.openStream(Activator.getDefault().getBundle(), path, false);
+ } catch (IOException e) {
+ }
+ if (is != null) {
+ final ImageData iData = new ImageData(is);
+ icon = new Image(Display.getCurrent(), iData);
+ return icon;
+ }
+ return null;
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/util/PluginConfigurationElementUtil.java b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/util/PluginConfigurationElementUtil.java
new file mode 100644
index 0000000..81ec86b
--- /dev/null
+++ b/plugins/org.eclipse.emf.mwe.ui/src/org/eclipse/emf/mwe/internal/ui/workflow/util/PluginConfigurationElementUtil.java
@@ -0,0 +1,51 @@
+package org.eclipse.emf.mwe.internal.ui.workflow.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+
+public class PluginConfigurationElementUtil {
+
+ public static String g