Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Frost2012-08-03 15:06:49 -0400
committerChristopher Frost2012-08-03 15:06:49 -0400
commit2952ee9850149aefc0880f1a3ebe836efb35caf5 (patch)
tree4ad1d407d98ca291f1e4c983c74f10f95001caa6
parentc94ef82447154b8a228dd9a75097423be20763bd (diff)
downloadorg.eclipse.virgo.kernel-2952ee9850149aefc0880f1a3ebe836efb35caf5.tar.gz
org.eclipse.virgo.kernel-2952ee9850149aefc0880f1a3ebe836efb35caf5.tar.xz
org.eclipse.virgo.kernel-2952ee9850149aefc0880f1a3ebe836efb35caf5.zip
(385314) Consolidate git repos - extensions and test-stubs
-rw-r--r--build.versions2
-rw-r--r--org.eclipse.virgo.kernel.agent.dm/ivy.xml22
-rw-r--r--org.eclipse.virgo.kernel.artifact/ivy.xml2
-rw-r--r--org.eclipse.virgo.kernel.deployer.dm/ivy.xml4
-rw-r--r--org.eclipse.virgo.kernel.deployer.test/ivy.xml8
-rw-r--r--org.eclipse.virgo.kernel.deployer/ivy.xml8
-rw-r--r--org.eclipse.virgo.kernel.dmfragment/ivy.xml2
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.classpath30
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.project41
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.virgo.ide.bundlor.core.prefs5
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.wst.common.project.facet.core.xml4
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.settings/org.springframework.ide.eclipse.core.prefs68
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/.springBeans13
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/build.xml8
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/ivy.xml26
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/EquinoxLauncherConfiguration.java71
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/ExtendedEquinoxLauncher.java90
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileClosingBundleFileWrapperFactoryHook.java76
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileWrapper.java34
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ClassLoaderCreator.java32
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtendedBundleFileWrapperFactoryHook.java200
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtensionsHookConfigurator.java38
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHook.java366
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableBundleFileWrapperFactoryHook.java66
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHook.java122
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHook.java137
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/.gitignore0
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/about.html28
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHookTests.java147
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHookTests.java102
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHookTests.java122
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/src/test/resources/hooks/classloading/bundle/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.virgo.kernel.equinox.extensions/template.mf16
-rw-r--r--org.eclipse.virgo.kernel.model/ivy.xml2
-rw-r--r--org.eclipse.virgo.kernel.osgi/ivy.xml8
-rw-r--r--org.eclipse.virgo.kernel.services/ivy.xml4
-rw-r--r--org.eclipse.virgo.kernel.shell/ivy.xml2
-rw-r--r--org.eclipse.virgo.kernel.test/ivy.xml7
-rw-r--r--org.eclipse.virgo.kernel.userregion/ivy.xml4
-rw-r--r--org.eclipse.virgo.kernel.userregionfactory/ivy.xml6
-rw-r--r--org.eclipse.virgo.kernel/ivy.xml1
-rw-r--r--org.eclipse.virgo.management.shell/.classpath12
-rw-r--r--org.eclipse.virgo.management.shell/.project28
-rw-r--r--org.eclipse.virgo.management.shell/build.xml10
-rw-r--r--org.eclipse.virgo.management.shell/ivy.xml27
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleInputStream.java86
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStream.java145
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/InputHandler.java76
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/KEYS.java16
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/Scanner.java151
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/SimpleByteBuffer.java149
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/CommandCompleter.java91
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandler.java31
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScanner.java374
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/Grep.java119
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/HistoryHolder.java103
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/ANSITerminalTypeMappings.java33
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/Callback.java17
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallback.java30
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/SCOTerminalTypeMappings.java34
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSession.java139
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandler.java31
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScanner.java296
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetManager.java149
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStream.java41
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TerminalTypeMappings.java70
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT100TerminalTypeMappings.java34
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT220TerminalTypeMappings.java24
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT320TerminalTypeMappings.java35
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHook.java98
-rw-r--r--org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookConfigurator.java25
-rw-r--r--org.eclipse.virgo.management.shell/src/main/resources/about.html28
-rw-r--r--org.eclipse.virgo.management.shell/src/main/resources/hookconfigurators.properties1
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleInputStreamTests.java43
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStreamTests.java41
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/HistoryHolderTests.java68
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/SimpleByteBufferTests.java96
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/CommandCompleterTests.java99
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandlerTests.java54
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScannerTests.java256
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/GrepTests.java93
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallbackTests.java56
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSessionTests.java129
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandlerTests.java49
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScannerTests.java212
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetManagerTests.java136
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStreamTests.java39
-rw-r--r--org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookTests.java84
-rw-r--r--org.eclipse.virgo.management.shell/template.mf18
89 files changed, 5861 insertions, 42 deletions
diff --git a/build.versions b/build.versions
index d0b7ad1d..203adaf8 100644
--- a/build.versions
+++ b/build.versions
@@ -15,7 +15,6 @@ ch.qos.logback.classic=1.0.0.v20111214-2030
ch.qos.logback.core=1.0.0.v20111214-2030
ch.qos.logback.slf4j=1.0.0.v20120123-1500
org.eclipse.virgo.medic=3.6.0.D-20120717201225
-org.eclipse.virgo.osgi=3.6.0.D-20120711092707
org.eclipse.virgo.repository=3.6.0.D-20120717202028
org.eclipse.virgo.util=3.6.0.D-20120717181632
org.slf4j=1.6.1
@@ -55,6 +54,5 @@ javax.servlet.jsp=2.2.0.v201112011158
javax.transaction=1.1.1.v201105210645
org.easymock=2.3.0
org.eclipse.virgo.test=3.6.0.D-20120717182335
-org.eclipse.virgo.teststubs=3.6.0.D-20120711092322
org.hsqldb=1.8.0.9
org.junit=4.7.0
diff --git a/org.eclipse.virgo.kernel.agent.dm/ivy.xml b/org.eclipse.virgo.kernel.agent.dm/ivy.xml
index fab350db..44907feb 100644
--- a/org.eclipse.virgo.kernel.agent.dm/ivy.xml
+++ b/org.eclipse.virgo.kernel.agent.dm/ivy.xml
@@ -13,10 +13,10 @@
</publications>
<dependencies>
- <dependency name='com.springsource.org.junit' rev='${org.junit}' org='org.junit' conf='test->runtime'/>
- <dependency name='com.springsource.org.easymock' rev='${org.easymock}' org='org.easymock' conf='test->runtime'/>
- <dependency name='org.eclipse.virgo.teststubs.osgi' rev='${org.eclipse.virgo.teststubs}' org='org.eclipse.virgo.teststubs' conf='test->runtime'/>
- <dependency name='org.eclipse.osgi' rev='${org.eclipse.osgi}' org='org.eclipse.virgo.mirrored' conf='compile->runtime'/>
+ <dependency org='org.junit' name='com.springsource.org.junit' rev='${org.junit}' conf='test->runtime'/>
+ <dependency org='org.easymock' name='com.springsource.org.easymock' rev='${org.easymock}' conf='test->runtime'/>
+ <dependency org='org.eclipse.virgo.test' name='org.eclipse.virgo.test.stubs' rev='${org.eclipse.virgo.test}' conf='test->runtime'/>
+ <dependency org='org.eclipse.virgo.mirrored' name='org.eclipse.osgi' rev='${org.eclipse.osgi}' conf='compile->runtime'/>
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.osgi.services" rev="${org.eclipse.osgi.services}" conf="compile->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.cm" rev="${org.eclipse.equinox.cm}" conf="compile->runtime"/>
@@ -24,13 +24,13 @@
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.region" rev="${org.eclipse.equinox.region}" conf="compile->runtime"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.deployer" rev="latest.integration" conf='compile->compile'/>
- <dependency name='org.eclipse.virgo.util.io' rev='${org.eclipse.virgo.util}' org='org.eclipse.virgo.util' conf='compile->compile'/>
- <dependency name='org.eclipse.virgo.util.osgi' rev='${org.eclipse.virgo.util}' org='org.eclipse.virgo.util' conf='compile->compile'/>
- <dependency name='org.slf4j.api' rev='${org.slf4j.api}' org='org.eclipse.virgo.mirrored' conf='compile->runtime'/>
- <dependency name='com.springsource.slf4j.nop' rev='${org.slf4j}' org='org.slf4j' conf='test->runtime'/>
- <dependency name='org.eclipse.virgo.medic' rev='${org.eclipse.virgo.medic}' org='org.eclipse.virgo.medic' conf='aspects, compile->runtime'/>
- <dependency name='org.eclipse.virgo.medic.core' rev='${org.eclipse.virgo.medic}' org='org.eclipse.virgo.medic' conf='runtime->runtime'/>
- <dependency name='org.eclipse.virgo.medic.test' rev='${org.eclipse.virgo.medic}' org='org.eclipse.virgo.medic' conf='test->runtime'/>
+ <dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.io' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
+ <dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.osgi' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
+ <dependency org='org.eclipse.virgo.mirrored' name='org.slf4j.api' rev='${org.slf4j.api}' conf='compile->runtime'/>
+ <dependency org='org.slf4j' name='com.springsource.slf4j.nop' rev='${org.slf4j}' conf='test->runtime'/>
+ <dependency org='org.eclipse.virgo.medic' name='org.eclipse.virgo.medic' rev='${org.eclipse.virgo.medic}' conf='aspects, compile->runtime'/>
+ <dependency org='org.eclipse.virgo.medic' name='org.eclipse.virgo.medic.core' rev='${org.eclipse.virgo.medic}' conf='runtime->runtime'/>
+ <dependency org='org.eclipse.virgo.medic' name='org.eclipse.virgo.medic.test' rev='${org.eclipse.virgo.medic}' conf='test->runtime'/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.extender" rev="${org.eclipse.gemini.blueprint}" conf="compile->compile"/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.core" rev="${org.eclipse.gemini.blueprint}" conf="compile->compile"/>
<override org="org.springframework" rev="${org.springframework}"/>
diff --git a/org.eclipse.virgo.kernel.artifact/ivy.xml b/org.eclipse.virgo.kernel.artifact/ivy.xml
index fcbd3d2c..4064aa97 100644
--- a/org.eclipse.virgo.kernel.artifact/ivy.xml
+++ b/org.eclipse.virgo.kernel.artifact/ivy.xml
@@ -16,7 +16,7 @@
<dependency org="org.eclipse.virgo.repository" name="org.eclipse.virgo.repository" rev="${org.eclipse.virgo.repository}" conf="compile->compile" />
<dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.osgi.manifest" rev="${org.eclipse.virgo.util}" conf="compile->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
diff --git a/org.eclipse.virgo.kernel.deployer.dm/ivy.xml b/org.eclipse.virgo.kernel.deployer.dm/ivy.xml
index 4ac3b5c7..7f7d58b7 100644
--- a/org.eclipse.virgo.kernel.deployer.dm/ivy.xml
+++ b/org.eclipse.virgo.kernel.deployer.dm/ivy.xml
@@ -16,12 +16,12 @@
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<dependency name='com.springsource.org.easymock' rev='${org.easymock}' org='org.easymock' conf='test->runtime'/>
- <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev="${org.eclipse.virgo.teststubs}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
<dependency org="org.slf4j" name="com.springsource.slf4j.nop" rev="${org.slf4j}" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="${org.springframework}" conf="compile->runtime"/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.core" rev="${org.eclipse.gemini.blueprint}" conf="compile->runtime"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.deployer" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev="${org.eclipse.virgo.medic}" conf="aspects, compile->runtime"/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.core" rev="${org.eclipse.virgo.medic}" conf="runtime->runtime"/>
diff --git a/org.eclipse.virgo.kernel.deployer.test/ivy.xml b/org.eclipse.virgo.kernel.deployer.test/ivy.xml
index c9d2b8f6..9cc54b84 100644
--- a/org.eclipse.virgo.kernel.deployer.test/ivy.xml
+++ b/org.eclipse.virgo.kernel.deployer.test/ivy.xml
@@ -21,7 +21,7 @@
<dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.common" rev="${org.eclipse.virgo.util}" conf="test->compile"/>
<dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.io" rev="${org.eclipse.virgo.util}" conf="test->compile"/>
<dependency org="org.eclipse.virgo.util" name="org.eclipse.virgo.util.math" rev="${org.eclipse.virgo.util}" conf="test->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="test->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.model" rev="latest.integration" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.deployer" rev="latest.integration" conf="test->compile"/>
@@ -53,8 +53,8 @@
<dependency org="javax.portlet" name="com.springsource.javax.portlet" rev="${javax.portlet}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="javax.servlet" rev="${javax.servlet}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="javax.el" rev="${javax.el}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.extensions.equinox" rev="${org.eclipse.virgo.osgi}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.launcher" rev="${org.eclipse.virgo.osgi}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.equinox.extensions" rev="latest.integration" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.launcher" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="org.slf4j.jul" rev="${org.slf4j.jul}" conf="test->runtime"/>
<dependency name='org.eclipse.virgo.repository' rev='${org.eclipse.virgo.repository}' conf='compile->compile' org='org.eclipse.virgo.repository'/>
@@ -68,7 +68,7 @@
<exclude org="org.eclipse.osgi"/>
<override org="org.eclipse.virgo.mirrored" module="org.eclipse.osgi" rev="${org.eclipse.osgi}"/>
- <override org="org.eclipse.virgo.osgi" rev="${org.eclipse.virgo.osgi}"/>
+ <override org="org.eclipse.virgo.test" rev="${org.eclipse.virgo.test}"/>
<override org="org.eclipse.virgo.util" rev="${org.eclipse.virgo.util}"/>
</dependencies>
diff --git a/org.eclipse.virgo.kernel.deployer/ivy.xml b/org.eclipse.virgo.kernel.deployer/ivy.xml
index bac06446..06c235d8 100644
--- a/org.eclipse.virgo.kernel.deployer/ivy.xml
+++ b/org.eclipse.virgo.kernel.deployer/ivy.xml
@@ -15,7 +15,7 @@
<dependencies>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev="${org.eclipse.virgo.teststubs}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="compile->runtime"/>
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.event" rev="${org.eclipse.equinox.event}" conf="compile->runtime"/>
@@ -34,9 +34,9 @@
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.extender" rev="${org.eclipse.gemini.blueprint}" conf="compile->runtime"/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.io" rev="${org.eclipse.gemini.blueprint}" conf="compile->runtime"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.deployer.api" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.deployer.hot" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.deployer.api" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.deployer.hot" rev="${org.eclipse.virgo.nano}" conf="aspects->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="aspects->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.services" rev="latest.integration" conf="aspects->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.artifact" rev="latest.integration" conf="compile->compile"/>
diff --git a/org.eclipse.virgo.kernel.dmfragment/ivy.xml b/org.eclipse.virgo.kernel.dmfragment/ivy.xml
index a01fb169..fce4b622 100644
--- a/org.eclipse.virgo.kernel.dmfragment/ivy.xml
+++ b/org.eclipse.virgo.kernel.dmfragment/ivy.xml
@@ -21,7 +21,7 @@
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.extender" rev="${org.eclipse.gemini.blueprint}" conf="compile->runtime"/>
<dependency org="org.eclipse.gemini" name="org.eclipse.gemini.blueprint.io" rev="${org.eclipse.gemini.blueprint}" conf="compile->runtime"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.mirrored" name="org.slf4j.api" rev="${org.slf4j.api}" conf="compile->runtime"/>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.classpath b/org.eclipse.virgo.kernel.equinox.extensions/.classpath
new file mode 100644
index 00000000..f4648a9f
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.classpath
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="org.eclipse.virgo.osgi.extensions/equinox/ExtendedOSGi.java" kind="src" path="src/main/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" path="src/main/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="false"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="com.springsource.server.ide.jdt.core.test.classpathentry" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/OSGI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.eclipse.virgo.mirrored/org.eclipse.osgi/3.8.0.v20120508-2119/org.eclipse.osgi-3.8.0.v20120508-2119.jar" sourcepath="/OSGI_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.7.1.R37x_v20110808-1106/org.eclipse.osgi-sources-3.7.1.R37x_v20110808-1106.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar" sourcepath="/OSGI_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/3.6.0.D-20120711092322/org.eclipse.virgo.teststubs.osgi-3.6.0.D-20120711092322.jar" sourcepath="/OSGI_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/3.6.0.D-20120711092322/org.eclipse.virgo.teststubs.osgi-sources-3.6.0.D-20120711092322.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.12.RELEASE/com.springsource.org.aspectj.runtime-1.6.12.RELEASE.jar" sourcepath="/OSGI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.12.RELEASE/com.springsource.org.aspectj.runtime-sources-1.6.12.RELEASE.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.project b/org.eclipse.virgo.kernel.equinox.extensions/.project
new file mode 100644
index 00000000..616f86c7
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.project
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.osgi.extensions.equinox</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.wst.common.project.facet.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.dev.eclipse.serverdevelopmentbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.springframework.ide.eclipse.core.springbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.springsource.server.ide.bundlor.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.springsource.server.ide.facet.core.bundlenature</nature>
+ <nature>org.springframework.ide.eclipse.core.springnature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>com.springsource.server.dev.eclipse.serverdevelopmentnature</nature>
+ <nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.virgo.ide.bundlor.core.prefs b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.virgo.ide.bundlor.core.prefs
new file mode 100644
index 00000000..809c0b6d
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.virgo.ide.bundlor.core.prefs
@@ -0,0 +1,5 @@
+#Wed Nov 04 14:40:56 GMT 2009
+org.eclipse.virgo.ide.bundlor.core.bundlor.generated.manifest.autoformatting=true
+org.eclipse.virgo.ide.bundlor.core.byte.code.scanning=true
+org.eclipse.virgo.ide.bundlor.core.template.properties.files=
+eclipse.preferences.version=1
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.wst.common.project.facet.core.xml b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 00000000..801f856c
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+ <installed facet="com.springsource.server.bundle" version="1.0"/>
+</faceted-project>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.springframework.ide.eclipse.core.prefs b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.springframework.ide.eclipse.core.prefs
new file mode 100644
index 00000000..87bcfa13
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.settings/org.springframework.ide.eclipse.core.prefs
@@ -0,0 +1,68 @@
+#Mon Dec 06 11:34:13 GMT 2010
+eclipse.preferences.version=1
+org.springframework.ide.eclipse.core.builders.enable.aopreferencemodelbuilder=true
+org.springframework.ide.eclipse.core.builders.enable.beanmetadatabuilder=true
+org.springframework.ide.eclipse.core.builders.enable.osgibundleupdater=false
+org.springframework.ide.eclipse.core.enable.project.preferences=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.enable.org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.applicationVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivationPolicyRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleActivatorRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleManifestVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleSymbolicNameRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.bundleVersionRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.exportPackageRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.importRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.parsingProblemsRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.server.ide.manifest.core.requireBundleRule-com.springsource.server.ide.manifest.core.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.AvoidDriverManagerDataSource-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ImportElementsAtTopRulee-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.ParentBeanSpecifiesAbstractClassRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.RefElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.TooManyBeansInFileRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UnnecessaryValueElementRule-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.com.springsource.sts.bestpractices.UseBeanInheritance-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.bestpractices.legacyxmlusage.jndiobjectfactory-com.springsource.sts.bestpractices.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importLibraryVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.importPackageVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.com.springsource.sts.server.quickfix.requireBundleVersionRule-com.springsource.sts.server.quickfix.manifestvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.autowire.autowire-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanAlias-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanClass-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanConstructorArgument-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinition-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanDefinitionHolder-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanFactory-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanInitDestroyMethod-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.beanReference-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.methodOverride-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.parsingProblems-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.requiredProperty-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.beans.core.toolAnnotation-org.springframework.ide.eclipse.beans.core.beansvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.core.springClasspath-org.springframework.ide.eclipse.core.springvalidator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.action-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.actionstate-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attribute-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.attributemapper-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.beanaction-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationaction-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.evaluationresult-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.exceptionhandler-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.import-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.inputattribute-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.mapping-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.outputattribute-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.set-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.state-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.subflowstate-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.transition-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.variable-org.springframework.ide.eclipse.webflow.core.validator=false
+org.springframework.ide.eclipse.core.validator.rule.enable.org.springframework.ide.eclipse.webflow.core.validation.webflowstate-org.springframework.ide.eclipse.webflow.core.validator=false
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/.springBeans b/org.eclipse.virgo.kernel.equinox.extensions/.springBeans
new file mode 100644
index 00000000..8058887d
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/.springBeans
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beansProjectDescription>
+ <version>1</version>
+ <pluginVersion><![CDATA[2.2.6.200908051215-RELEASE]]></pluginVersion>
+ <configSuffixes>
+ <configSuffix><![CDATA[xml]]></configSuffix>
+ </configSuffixes>
+ <enableImports><![CDATA[false]]></enableImports>
+ <configs>
+ </configs>
+ <configSets>
+ </configSets>
+</beansProjectDescription>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/build.xml b/org.eclipse.virgo.kernel.equinox.extensions/build.xml
new file mode 100644
index 00000000..4a65221c
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/build.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.kernel.equinox.extensions">
+
+ <property file="${basedir}/../build.versions"/>
+ <property file="${basedir}/../build.properties"/>
+ <import file="${basedir}/../virgo-build/standard/default.xml"/>
+
+</project>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/ivy.xml b/org.eclipse.virgo.kernel.equinox.extensions/ivy.xml
new file mode 100644
index 00000000..a1022c0e
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/ivy.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.osgi" module="${ant.project.name}"/>
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="compile->compile"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/EquinoxLauncherConfiguration.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/EquinoxLauncherConfiguration.java
new file mode 100644
index 00000000..17302ce8
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/EquinoxLauncherConfiguration.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ */
+public final class EquinoxLauncherConfiguration {
+
+ private final Map<String, String> frameworkProperties = new HashMap<String, String>();
+
+ private URI profilePath;
+
+ private URI installPath;
+
+ private URI configPath;
+
+ private boolean clean = false;
+
+ public URI getProfilePath() {
+ return profilePath;
+ }
+
+ public void setProfilePath(URI profilePath) {
+ this.profilePath = profilePath;
+ }
+
+ public URI getInstallPath() {
+ return installPath;
+ }
+
+ public void setInstallPath(URI installPath) {
+ this.installPath = installPath;
+ }
+
+ public URI getConfigPath() {
+ return configPath;
+ }
+
+ public void setConfigPath(URI configPath) {
+ this.configPath = configPath;
+ }
+
+ public boolean isClean() {
+ return clean;
+ }
+
+ public void setClean(boolean clean) {
+ this.clean = clean;
+ }
+
+ public void setFrameworkProperty(String key, String value) {
+ this.frameworkProperties.put(key, value);
+ }
+
+ public Map<String, String> getFrameworkProperties() {
+ return this.frameworkProperties;
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/ExtendedEquinoxLauncher.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/ExtendedEquinoxLauncher.java
new file mode 100644
index 00000000..9dc1dc6b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/ExtendedEquinoxLauncher.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.runtime.adaptor.LocationManager;
+import org.eclipse.osgi.baseadaptor.HookRegistry;
+import org.eclipse.osgi.framework.internal.core.Constants;
+import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.launch.Equinox;
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.ExtensionsHookConfigurator;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+
+
+/**
+ */
+public final class ExtendedEquinoxLauncher {
+
+ private static final String PROP_CONTEXT_BOOTDELEGATION = "osgi.context.bootdelegation";
+ private static final String PROP_COMPATIBILITY_BOOTDELEGATION = "osgi.compatibility.bootdelegation";
+
+ /**
+ * Equinox-specific property to control clean startup.
+ */
+ private static final String PROP_OSGI_CLEAN = "osgi.clean";
+
+ /**
+ * Equinox-specific property for setting the parent <code>ClassLoader</code>.
+ */
+ private static final String PROP_OSGI_PARENT_CLASSLOADER = "osgi.parentClassloader";
+
+ public static Equinox launch(EquinoxLauncherConfiguration config) throws BundleException {
+ try {
+ Field f = FrameworkProperties.class.getDeclaredField("properties");
+ f.setAccessible(true);
+ f.set(null, null);
+ } catch (Exception e) {
+ System.out.println("Unable to reset Equinox FrameworkProperties");
+ e.printStackTrace(System.out);
+ }
+
+ Map<String, String> configuration = populateConfiguration(config);
+ Equinox equinox = new Equinox(configuration);
+ equinox.start();
+ equinox.getBundleContext().registerService(Framework.class.getName(), equinox, null);
+
+ return equinox;
+ }
+
+ private static Map<String, String> populateConfiguration(EquinoxLauncherConfiguration config) {
+ Map<String, String> configuration = new HashMap<String, String>();
+ configuration.putAll(config.getFrameworkProperties());
+
+ mergeListProperty(configuration, HookRegistry.PROP_HOOK_CONFIGURATORS_INCLUDE, ExtensionsHookConfigurator.class.getName());
+
+ configuration.put(PROP_OSGI_PARENT_CLASSLOADER, "fwk");
+ configuration.put(PROP_CONTEXT_BOOTDELEGATION, "false");
+ configuration.put(PROP_COMPATIBILITY_BOOTDELEGATION, "false");
+ if (config.getProfilePath() != null) {
+ configuration.put(Constants.OSGI_JAVA_PROFILE, config.getProfilePath().toString());
+ }
+ configuration.put(Constants.OSGI_JAVA_PROFILE_BOOTDELEGATION, Constants.OSGI_BOOTDELEGATION_OVERRIDE);
+ configuration.put(LocationManager.PROP_CONFIG_AREA, config.getConfigPath().toString());
+ configuration.put(LocationManager.PROP_INSTALL_AREA, config.getInstallPath().toString());
+ configuration.put(PROP_OSGI_CLEAN, Boolean.toString(config.isClean()));
+ return configuration;
+ }
+
+ private static void mergeListProperty(Map<String, String> properties, String key, String value) {
+ String existingValue = properties.get(key);
+ if (existingValue != null) {
+ properties.put(key, existingValue + "," + value);
+ } else {
+ properties.put(key, value);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileClosingBundleFileWrapperFactoryHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileClosingBundleFileWrapperFactoryHook.java
new file mode 100644
index 00000000..9ba68ee0
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileClosingBundleFileWrapperFactoryHook.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
+
+
+/**
+ * A {@link BundleFileWrapperFactoryHook} that keeps track of {@link BundleFile BundleFiles} and,
+ * when instructed to clean up, ensures that they are closed.
+ *
+ * <p />
+ *
+ * This is a workaround for Equinox bug 290389. Unfortunately when working with nested frameworks
+ * the suggested workaround of calling PackageAdmin.refreshPackages does not work for the
+ * child framework's composite bundle.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+public final class BundleFileClosingBundleFileWrapperFactoryHook implements BundleFileWrapperFactoryHook {
+
+ private final Object monitor = new Object();
+
+ private final List<BundleFile> bundleFiles = new ArrayList<BundleFile>();
+
+ private static final BundleFileClosingBundleFileWrapperFactoryHook INSTANCE = new BundleFileClosingBundleFileWrapperFactoryHook();
+
+ private BundleFileClosingBundleFileWrapperFactoryHook() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) throws IOException {
+ synchronized (this.monitor) {
+ this.bundleFiles.add(bundleFile);
+ }
+ return null;
+ }
+
+ public void cleanup() {
+ List<BundleFile> localBundleFiles;
+ synchronized (this.monitor) {
+ localBundleFiles = new ArrayList<BundleFile>(this.bundleFiles);
+ this.bundleFiles.clear();
+ }
+ for (BundleFile bundleFile : localBundleFiles) {
+ try {
+ bundleFile.close();
+ } catch (IOException _) {
+ }
+ }
+ }
+
+ public static BundleFileClosingBundleFileWrapperFactoryHook getInstance() {
+ return INSTANCE;
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileWrapper.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileWrapper.java
new file mode 100644
index 00000000..953a4772
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/BundleFileWrapper.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+
+/**
+ * A <code>BundleFileWrapper</code> implementation can be plugged into the {@link PluggableBundleFileWrapperFactoryHook}
+ * at runtime. It will be called to wrap each {@BundleFile BundleFile} that is subsequently accessed by
+ * Equinox.<p />
+ *
+ * <strong>Concurrent Semantics</strong><br /> Implementations <strong>must</strong> be thread-safe.
+ *
+ */
+public interface BundleFileWrapper {
+
+ /**
+ * Provides an opportunity to wrap the supplied {@link BundleFile}. If the wrapper does not wish to wrap the
+ * supplied <code>BundleFile</code> then <code>null</code> must be returned.
+ *
+ * @param bundleFile The <code>BundleFile</code> to be wrapped
+ * @return The wrapped <code>BundleFile</code>, or <code>null</code> if the no wrapping is required.
+ */
+ BundleFile wrapBundleFile(BundleFile bundleFile);
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ClassLoaderCreator.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ClassLoaderCreator.java
new file mode 100644
index 00000000..700b49d2
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ClassLoaderCreator.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
+
+
+/**
+ * A <code>ClassLoaderCreator</code> is used to create an Equinox {@link BaseClassLoader} for a {@link org.osgi.framework.Bundle Bundle}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations must be thread-safe.
+ *
+ */
+public interface ClassLoaderCreator {
+
+ public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data, String[] bundleclasspath);
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtendedBundleFileWrapperFactoryHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtendedBundleFileWrapperFactoryHook.java
new file mode 100644
index 00000000..562d0982
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtendedBundleFileWrapperFactoryHook.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Enumeration;
+import java.util.jar.JarFile;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
+
+/**
+ * A {@link BundleFileWrapperFactoryHook} implementation that wraps {@link BundleFile BundleFiles} to ensure that all
+ * returned resource {@link URL URLs} have a <code>file:</code> protocol, not a <code>bundleresource:</code>
+ * protocol as is the Equinox default.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * This class is <strong>thread-safe</strong>.
+ *
+ */
+final class ExtendedBundleFileWrapperFactoryHook implements BundleFileWrapperFactoryHook {
+
+ /**
+ * {@inheritDoc}
+ */
+ public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) throws IOException {
+ return new FileResourceEnforcingBundleFile(bundleFile);
+ }
+
+ /**
+ * A concrete extension of {@link BundleFile} that ensures that all resource {@link URL URLs} returned have a
+ * <code>file:</code> protocol, not a <code>bundleresource:</code> protocol as is the Equinox default.
+ * <p>
+ * <strong>Concurrent Semantics</strong><br />
+ * As thread-safe as the encapsulated <code>BundleFile</code> instance.
+ *
+ */
+ private static class FileResourceEnforcingBundleFile extends BundleFile {
+
+ private final BundleFile bundleFile;
+
+ private FileResourceEnforcingBundleFile(BundleFile bundleFile) {
+ this.bundleFile = bundleFile;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void close() throws IOException {
+ this.bundleFile.close();
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean containsDir(String dir) {
+ return this.bundleFile.containsDir(dir);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public BundleEntry getEntry(String path) {
+ BundleEntry entry = this.bundleFile.getEntry(path);
+ return entry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Enumeration<String> getEntryPaths(String path) {
+ Enumeration<String> paths = this.bundleFile.getEntryPaths(path);
+ return paths;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public File getFile(String path, boolean nativeCode) {
+ return this.bundleFile.getFile(path, nativeCode);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void open() throws IOException {
+ this.bundleFile.open();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public File getBaseFile() {
+ return this.bundleFile.getBaseFile();
+ }
+
+ /**
+ * Locates the resource in the BundleFile identified by the supplied path and, if found, returns a
+ * <code>file</code> protocol URL for the resource.
+ *
+ * @return a <code>file</code> protocol URL for the resource
+ */
+ @Override
+ public URL getResourceURL(String path, long hostBundleID, int index) {
+ return doGetResourceURL(path);
+ }
+
+ /**
+ * Locates the resource in the BundleFile identified by the supplied path and, if found, returns a
+ * <code>file</code> protocol URL for the resource.
+ *
+ * @return a <code>file</code> protocol URL for the resource
+ */
+ @Override
+ public URL getResourceURL(String path, long hostBundleID) {
+ return doGetResourceURL(path);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public URL getResourceURL(String path, BaseData hostData, int index) {
+ return doGetResourceURL(path);
+ }
+
+ private URL doGetResourceURL(String path) {
+ BundleEntry entry = getEntry(path);
+ if (entry != null) {
+ return getLocalURLForEntry(entry);
+ } else {
+ return null;
+ }
+ }
+
+ private URL getLocalURLForEntry(BundleEntry entry) {
+ URL url = entry.getLocalURL();
+ try {
+ url.openConnection().setDefaultUseCaches(false);
+ url.openConnection().setUseCaches(false);
+ } catch (Exception e) {
+
+ }
+ if (!"jar".equals(url.getProtocol()) || doesJarEntryReallyExist(url)) {
+ return url;
+ } else {
+ return null;
+ }
+ }
+
+ private boolean doesJarEntryReallyExist(URL url) {
+ boolean entryExists = false;
+ JarFile jarFile = null;
+ try {
+ URLConnection connection = url.openConnection();
+ if (connection instanceof JarURLConnection) {
+ JarURLConnection jarURLConnection = (JarURLConnection) connection;
+ jarFile = jarURLConnection.getJarFile();
+ String entryName = jarURLConnection.getEntryName();
+ if (entryName != null && jarFile != null && jarFile.getEntry(entryName) != null) {
+ entryExists = true;
+ }
+ }
+ } catch (IOException ioe) {
+ entryExists = false;
+ } finally {
+ if (jarFile != null) {
+ try {
+ jarFile.close();
+ } catch (IOException _) {
+ }
+ }
+ }
+ return entryExists;
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtensionsHookConfigurator.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtensionsHookConfigurator.java
new file mode 100644
index 00000000..30e5b33d
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/ExtensionsHookConfigurator.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import org.eclipse.osgi.baseadaptor.HookConfigurator;
+import org.eclipse.osgi.baseadaptor.HookRegistry;
+
+/**
+ * Configures Equinox hooks with which its runtime behaviour is customised.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+public class ExtensionsHookConfigurator implements HookConfigurator {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addHooks(HookRegistry hookRegistry) {
+ hookRegistry.addClassLoadingHook(PluggableClassLoadingHook.getInstance());
+ hookRegistry.addBundleFileWrapperFactoryHook(new ExtendedBundleFileWrapperFactoryHook());
+ hookRegistry.addBundleFileWrapperFactoryHook(BundleFileClosingBundleFileWrapperFactoryHook.getInstance());
+ hookRegistry.addBundleFileWrapperFactoryHook(PluggableBundleFileWrapperFactoryHook.getInstance());
+ hookRegistry.addClassLoaderDelegateHook(PluggableDelegatingClassLoaderDelegateHook.getInstance());
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHook.java
new file mode 100644
index 00000000..1449535c
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHook.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleData;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegateHook;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.packageadmin.ExportedPackage;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+/**
+ * A {@link ClassLoaderDelegateHook} which in {@link #postFindResource} and {@link #postFindResources} propagates the
+ * attempt to get <code>META-INF</code> resource(s) to the principle bundle's dependencies, unless the request is being
+ * driven through Spring DM's DelgatedNamespaceHandlerResolver.
+ *
+ * <p />
+ *
+ * The list of a bundle's dependencies are cached to avoid determining the dependencies every time. A bundle's entry
+ * in the cached is cleared whenever an <code>UNRESOLVED</code> event is received for the bundle. <code>UNRESOLVED</code>
+ * events are fired both during uninstall and during {@link PackageAdmin#refreshPackages(Bundle[]) refreshPackages}
+ * processing.
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+@SuppressWarnings("deprecation")
+public class MetaInfResourceClassLoaderDelegateHook implements ClassLoaderDelegateHook {
+
+ private static final String SPRINGDM_DELEGATED_NAMESPACE_HANDLER_RESOLVER_CLASS_NAME = "org.springframework.osgi.context.support.DelegatedNamespaceHandlerResolver";
+
+ private static final String SPRINGDM_DELEGATED_ENTITY_RESOLVER_CLASS_NAME = "org.springframework.osgi.context.support.DelegatedEntityResolver";
+
+ private static final String BLUEPRINT_DELEGATED_NAMESPACE_HANDLER_RESOLVER_CLASS_NAME = "org.eclipse.gemini.blueprint.context.support.DelegatedNamespaceHandlerResolver";
+
+ private static final String BLUEPRINT_DELEGATED_ENTITY_RESOLVER_CLASS_NAME = "org.eclipse.gemini.blueprint.context.support.ChainedEntityResolver";
+
+ private static final String EXCLUDED_RESOURCE_MANIFEST = "MANIFEST.MF";
+
+ private static final String EXCLUDED_RESOURCE_SPRING_DIR = "spring";
+
+ private static final String EXCLUDED_RESOURCE_BLUEPRINT_DIR = "blueprint";
+
+ private static final String EXCLUDED_RESOURCE_SPRING_DIR_SUFFIX = ".xml";
+
+ private final BundleContext systemBundleContext;
+
+ private final PackageAdmin packageAdmin;
+
+ private final ThreadLocal<Object> resourceSearchInProgress = new ThreadLocal<Object>();
+
+ private final Object SEARCH_IN_PROGRESS_MARKER = new Object();
+
+ private final Object monitor = new Object();
+
+ private final WeakHashMap<Bundle, Set<Bundle>> dependenciesCache = new WeakHashMap<Bundle, Set<Bundle>>();
+
+ private final BundleListener cacheClearingBundleListener = new CacheClearingBundleListener();
+
+ /**
+ * Create a new hook that will use the supplied <code>systemBundleContext</code> to lookup bundles, and the supplied
+ * <code>packageAdmin</code> to determine a bundle's dependencies.
+ *
+ * @param systemBundleContext the {@link BundleContext} of the system bundle
+ * @param packageAdmin the {@link PackageAdmin} to use to determine a bundle's dependencies
+ */
+ public MetaInfResourceClassLoaderDelegateHook(BundleContext systemBundleContext, PackageAdmin packageAdmin) {
+ this.systemBundleContext = systemBundleContext;
+ this.packageAdmin = packageAdmin;
+ }
+
+ public void init() {
+ this.systemBundleContext.addBundleListener(this.cacheClearingBundleListener);
+ }
+
+ public void destroy() {
+ this.systemBundleContext.removeBundleListener(this.cacheClearingBundleListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public URL postFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ if (this.resourceSearchInProgress.get() == null && isDelegatedResource(name)) {
+ try {
+ this.resourceSearchInProgress.set(SEARCH_IN_PROGRESS_MARKER);
+
+ Bundle[] bundles = getDependencyBundles(classLoader.getBundle());
+ for (Bundle dependency : bundles) {
+ try {
+ int state = dependency.getState();
+ if (state == Bundle.ACTIVE || state == Bundle.RESOLVED) {
+ URL resource = dependency.getResource(name);
+ if (resource != null) {
+ return resource;
+ }
+ } else {
+ removeDependency(classLoader.getBundle(), dependency);
+ }
+ } catch (IllegalStateException _) {
+ // Dependency now UNINSTALLED
+ removeDependency(classLoader.getBundle(), dependency);
+ }
+ }
+ } finally {
+ this.resourceSearchInProgress.set(null);
+ }
+ }
+ return null;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Enumeration<URL> postFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ if (this.resourceSearchInProgress.get() == null && isDelegatedResource(name)) {
+ try {
+ this.resourceSearchInProgress.set(SEARCH_IN_PROGRESS_MARKER);
+
+ Set<URL> found = new HashSet<URL>();
+ Bundle[] bundles = getDependencyBundles(classLoader.getBundle());
+ for (Bundle dependency : bundles) {
+ try {
+ int state = dependency.getState();
+ if (state == Bundle.RESOLVED || state == Bundle.ACTIVE) {
+ addAll(found, dependency.getResources(name));
+ } else {
+ removeDependency(classLoader.getBundle(), dependency);
+ }
+ } catch (IOException _) {
+ } catch (IllegalStateException _) {
+ // Dependency now UNINSTALLED
+ removeDependency(classLoader.getBundle(), dependency);
+ }
+ }
+
+ if (!found.isEmpty()) {
+ return new IteratorEnumerationAdaptor<URL>(found.iterator());
+ }
+ } finally {
+ this.resourceSearchInProgress.set(null);
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isDelegatedResource(String name) {
+ return isMetaInfResource(name) && !isDelegatedResolverCall();
+ }
+
+ /**
+ * Queries whether or not the supplied resource name is a META-INF resource.
+ *
+ * @param name the resource name.
+ * @return <code>true</code> if the resource is a META-INF resource.
+ */
+ private boolean isMetaInfResource(String name) {
+ if (!name.startsWith("/META-INF") && !name.startsWith("META-INF")) {
+ return false;
+ }
+ if (name.contains(EXCLUDED_RESOURCE_MANIFEST)) {
+ return false;
+ }
+ if ((name.contains(EXCLUDED_RESOURCE_SPRING_DIR) || name.contains(EXCLUDED_RESOURCE_BLUEPRINT_DIR))
+ && name.endsWith(EXCLUDED_RESOURCE_SPRING_DIR_SUFFIX)) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isDelegatedResolverCall() {
+ Class<?>[] stackTrace = new SecurityManagerExecutionStackAccessor().getExecutionStack();
+ return isSpringDmDelegatedResolverCall(stackTrace) || isBlueprintDelegatedResolverCall(stackTrace);
+ }
+
+ private final class SecurityManagerExecutionStackAccessor extends SecurityManager {
+
+ public Class<?>[] getExecutionStack() {
+ Class<?>[] classes = super.getClassContext();
+ Class<?>[] executionStack = new Class<?>[classes.length - 1];
+
+ System.arraycopy(classes, 1, executionStack, 0, executionStack.length);
+
+ return executionStack;
+ }
+ }
+
+ private boolean isSpringDmDelegatedResolverCall(Class<?>[] stackTrace) {
+ return isDelegatedResolverCall(stackTrace, SPRINGDM_DELEGATED_NAMESPACE_HANDLER_RESOLVER_CLASS_NAME, SPRINGDM_DELEGATED_ENTITY_RESOLVER_CLASS_NAME);
+ }
+
+ private boolean isBlueprintDelegatedResolverCall(Class<?>[] stackTrace) {
+ return isDelegatedResolverCall(stackTrace, BLUEPRINT_DELEGATED_NAMESPACE_HANDLER_RESOLVER_CLASS_NAME, BLUEPRINT_DELEGATED_ENTITY_RESOLVER_CLASS_NAME);
+ }
+
+ private boolean isDelegatedResolverCall(Class<?>[] stackTrace, String namespaceResolver, String entityResolver) {
+ for (Class<?> clazz : stackTrace) {
+ String className = clazz.getName();
+ if (namespaceResolver.equals(className) || entityResolver.equals(className)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void addAll(Collection<URL> target, Enumeration<URL> source) {
+ while (source != null && source.hasMoreElements()) {
+ target.add(source.nextElement());
+ }
+ }
+
+ private Bundle[] getDependencyBundles(Bundle bundle) {
+ synchronized (this.monitor) {
+ Set<Bundle> dependencies = this.dependenciesCache.get(bundle);
+ if (dependencies != null) {
+ return dependencies.toArray(new Bundle[dependencies.size()]);
+ }
+ }
+
+ Set<Bundle> dependencies = determineDependencies(bundle);
+ synchronized (this.monitor) {
+ this.dependenciesCache.put(bundle, dependencies);
+ return dependencies.toArray(new Bundle[dependencies.size()]);
+ }
+ }
+
+ private void removeDependency(Bundle bundle, Bundle dependency) {
+ synchronized (this.monitor) {
+ Set<Bundle> dependencies = this.dependenciesCache.get(bundle);
+ if (dependencies != null) {
+ dependencies.remove(dependency);
+ }
+ }
+ }
+
+ private Set<Bundle> determineDependencies(Bundle bundle) {
+ Set<Bundle> bundles = new HashSet<Bundle>();
+ for (Bundle candidate : this.systemBundleContext.getBundles()) {
+ if (!candidate.equals(bundle)) {
+ ExportedPackage[] exportedPackages = getExportedPackages(candidate);
+ if (exportedPackages != null) {
+ for (ExportedPackage exportedPackage : exportedPackages) {
+ Bundle[] importingBundles = exportedPackage.getImportingBundles();
+ if (importingBundles != null) {
+ for (Bundle importer : importingBundles) {
+ if (importer.equals(bundle)) {
+ bundles.add(candidate);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return bundles;
+ }
+
+ protected ExportedPackage[] getExportedPackages(Bundle bundle) {
+ return this.packageAdmin.getExportedPackages(bundle);
+ }
+
+ private static class IteratorEnumerationAdaptor<T> implements Enumeration<T> {
+
+ private final Iterator<T> iterator;
+
+ private IteratorEnumerationAdaptor(Iterator<T> iterator) {
+ this.iterator = iterator;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasMoreElements() {
+ return this.iterator.hasNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public T nextElement() {
+ return this.iterator.next();
+ }
+ }
+
+ private final class CacheClearingBundleListener implements BundleListener {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void bundleChanged(BundleEvent event) {
+ if (BundleEvent.UNRESOLVED == event.getType()) {
+ synchronized (monitor) {
+ dependenciesCache.remove(event.getBundle());
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class<?> postFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String postFindLibrary(String name, BundleClassLoader classLoader, BundleData data) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class<?> preFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String preFindLibrary(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public URL preFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Enumeration<URL> preFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableBundleFileWrapperFactoryHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableBundleFileWrapperFactoryHook.java
new file mode 100644
index 00000000..0dd13d91
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableBundleFileWrapperFactoryHook.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.io.IOException;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
+import org.eclipse.osgi.baseadaptor.hooks.BundleFileWrapperFactoryHook;
+
+
+/**
+ * A {@link BundleFileWrapperFactoryHook} into which a {@link BundleFileWrapper} implementation can be plugged. The {@link BundleFileWrapper}
+ * implementation is called to wrap {@link BundleFile BundleFiles} during bundle installation and update.
+ *
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+public class PluggableBundleFileWrapperFactoryHook implements BundleFileWrapperFactoryHook {
+
+ private volatile BundleFileWrapper wrapper;
+
+ private final Object monitor = new Object();
+
+ private static final PluggableBundleFileWrapperFactoryHook INSTANCE = new PluggableBundleFileWrapperFactoryHook();
+
+ private PluggableBundleFileWrapperFactoryHook() {
+
+ }
+
+ public static PluggableBundleFileWrapperFactoryHook getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public BundleFile wrapBundleFile(BundleFile bundleFile, Object content, BaseData data, boolean base) throws IOException {
+ synchronized(this.monitor) {
+ if (wrapper != null) {
+ return wrapper.wrapBundleFile(bundleFile);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public void setBundleFileWrapper(BundleFileWrapper wrapper) {
+ synchronized(this.monitor) {
+ this.wrapper = wrapper;
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHook.java
new file mode 100644
index 00000000..fabc1fde
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHook.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry;
+import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook;
+import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
+import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry;
+import org.eclipse.osgi.baseadaptor.loader.ClasspathManager;
+import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
+
+/**
+ * A {@link ClassLoadingHook} into which a {@link ClassLoaderCreator} can be plugged to provide a custom class loader
+ * for a bundle.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+public final class PluggableClassLoadingHook implements ClassLoadingHook {
+
+ private static final PluggableClassLoadingHook INSTANCE = new PluggableClassLoadingHook();
+
+ private final Object monitor = new Object();
+
+ private volatile ClassLoaderCreator creator;
+
+ private ClassLoader bundleClassLoaderParent;
+
+ private PluggableClassLoadingHook() {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean addClassPathEntry(ArrayList<ClasspathEntry> cpEntries, String cp, ClasspathManager hostmanager, BaseData sourcedata, ProtectionDomain sourcedomain) {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data,
+ String[] bundleclasspath) {
+ if (this.creator != null) {
+ return this.creator.createClassLoader(parent, delegate, domain, data, bundleclasspath);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String findLibrary(BaseData data, String libName) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ClassLoader getBundleClassLoaderParent() {
+ synchronized (this.monitor) {
+ return this.bundleClassLoaderParent;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] processClass(String name, byte[] classbytes, ClasspathEntry classpathEntry, BundleEntry entry, ClasspathManager manager) {
+ return null;
+ }
+
+ public void setClassLoaderCreator(ClassLoaderCreator creator) {
+ synchronized (this.monitor) {
+ this.creator = creator;
+ }
+ }
+
+ /**
+ * @return singleton
+ */
+ public static PluggableClassLoadingHook getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Sets the class loader to be used as the parent of bundle class loaders.
+ *
+ * @param bundleClassLoaderParent the class loader to be used
+ */
+ public void setBundleClassLoaderParent(ClassLoader bundleClassLoaderParent) {
+ synchronized (this.monitor) {
+ this.bundleClassLoaderParent = bundleClassLoaderParent;
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHook.java b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHook.java
new file mode 100644
index 00000000..a45a1463
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHook.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleData;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegateHook;
+
+
+/**
+ * A pluggable {@link ClassLoaderDelegateHook} into which one or more <code>ClassLoaderDelegateHook</code>
+ * can be plugged.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Thread-safe.
+ *
+ */
+public class PluggableDelegatingClassLoaderDelegateHook implements ClassLoaderDelegateHook {
+
+ private final List<ClassLoaderDelegateHook> delegates = new CopyOnWriteArrayList<ClassLoaderDelegateHook>();
+
+ private static final PluggableDelegatingClassLoaderDelegateHook INSTANCE = new PluggableDelegatingClassLoaderDelegateHook();
+
+ private PluggableDelegatingClassLoaderDelegateHook() {
+ }
+
+ public static PluggableDelegatingClassLoaderDelegateHook getInstance() {
+ return INSTANCE;
+ }
+
+ public void addDelegate(ClassLoaderDelegateHook delegate) {
+ this.delegates.add(delegate);
+ }
+
+ public void removeDelegate(ClassLoaderDelegateHook delegate) {
+ this.delegates.remove(delegate);
+ }
+
+ public Class<?> postFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ Class<?> clazz = delegate.postFindClass(name, classLoader, data);
+ if (clazz != null) {
+ return clazz;
+ }
+ }
+ return null;
+ }
+
+ public String postFindLibrary(String name, BundleClassLoader classLoader, BundleData data) {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ String library = delegate.postFindLibrary(name, classLoader, data);
+ if (library != null) {
+ return library;
+ }
+ }
+ return null;
+ }
+
+ public URL postFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ URL resource = delegate.postFindResource(name, classLoader, data);
+ if (resource != null) {
+ return resource;
+ }
+ }
+ return null;
+ }
+
+ public Enumeration<URL> postFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ Enumeration<URL> resources = delegate.postFindResources(name, classLoader, data);
+ if (resources != null) {
+ return resources;
+ }
+ }
+ return null;
+ }
+
+ public Class<?> preFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ Class<?> clazz = delegate.preFindClass(name, classLoader, data);
+ if (clazz != null) {
+ return clazz;
+ }
+ }
+ return null;
+ }
+
+ public String preFindLibrary(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ String library = delegate.preFindLibrary(name, classLoader, data);
+ if (library != null) {
+ return library;
+ }
+ }
+ return null;
+ }
+
+ public URL preFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ URL resource = delegate.preFindResource(name, classLoader, data);
+ if (resource != null) {
+ return resource;
+ }
+ }
+ return null;
+ }
+
+ public Enumeration<URL> preFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException {
+ for (ClassLoaderDelegateHook delegate : this.delegates) {
+ Enumeration<URL> resources = delegate.preFindResources(name, classLoader, data);
+ if (resources != null) {
+ return resources;
+ }
+ }
+ return null;
+ }
+
+
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/.gitignore b/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/.gitignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/.gitignore
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/about.html b/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/about.html
new file mode 100644
index 00000000..c258ef55
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/main/resources/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHookTests.java b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHookTests.java
new file mode 100644
index 00000000..173416f2
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/MetaInfResourceClassLoaderDelegateHookTests.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+import org.osgi.service.packageadmin.ExportedPackage;
+
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.MetaInfResourceClassLoaderDelegateHook;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundle;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+
+
+/**
+ */
+@SuppressWarnings("deprecation")
+public class MetaInfResourceClassLoaderDelegateHookTests {
+
+ private final BundleClassLoader classLoader = createMock(BundleClassLoader.class);
+
+ private final StubBundle principleBundle = new StubBundle(3L, "principle", new Version(1, 0, 0), "");
+
+ private final StubBundle installedBundleOne = new StubBundle(1L, "one", new Version(1, 0, 0), "");
+
+ private final StubBundle installedBundleTwo = new StubBundle(2L, "two", new Version(1, 0, 0), "");
+
+ private final StubBundleContext principleBundleContext = new StubBundleContext(this.principleBundle);
+
+ private final UnitTestMetaInfResourceClassLoaderDelegateHook hook = new UnitTestMetaInfResourceClassLoaderDelegateHook(this.principleBundleContext);
+
+ @Before
+ public void initialise() {
+ this.principleBundle.setBundleContext(this.principleBundleContext);
+
+ expect(this.classLoader.getBundle()).andReturn(this.principleBundle).anyTimes();
+ replay(this.classLoader);
+
+ this.installedBundleOne.setState(Bundle.ACTIVE);
+ this.installedBundleTwo.setState(Bundle.RESOLVED);
+
+ this.principleBundleContext.addInstalledBundle(this.installedBundleOne);
+ this.principleBundleContext.addInstalledBundle(this.installedBundleTwo);
+ }
+
+ @Test
+ public void findResourceWithNoExportedPackages() throws FileNotFoundException {
+ assertNull(hook.postFindResource("META-INF/the.resource", classLoader, null));
+ }
+
+ @Test
+ public void findResourcesWithNoExportedPackages() throws FileNotFoundException {
+ assertNull(hook.postFindResources("META-INF/the.resource", classLoader, null));
+ }
+
+ @Test
+ public void findResource() throws FileNotFoundException, MalformedURLException {
+ ExportedPackage exportedPackage = createMock(ExportedPackage.class);
+ expect(exportedPackage.getImportingBundles()).andReturn(new Bundle[] {this.principleBundle});
+ replay(exportedPackage);
+
+ hook.exportedPackages.put(this.installedBundleTwo, new ExportedPackage[] {exportedPackage});
+
+ URL resourceUrl = new URL("file:/resource");
+ this.installedBundleTwo.addResource("META-INF/the.resource", resourceUrl);
+
+ assertEquals(resourceUrl, this.hook.postFindResource("META-INF/the.resource", this.classLoader, null));
+ }
+
+ @Test
+ public void findResources() throws FileNotFoundException, MalformedURLException {
+ ExportedPackage exportedPackage = createMock(ExportedPackage.class);
+ expect(exportedPackage.getImportingBundles()).andReturn(new Bundle[] {this.principleBundle}).anyTimes();
+ replay(exportedPackage);
+
+ hook.exportedPackages.put(this.installedBundleTwo, new ExportedPackage[] {exportedPackage});
+ hook.exportedPackages.put(this.installedBundleOne, new ExportedPackage[] {exportedPackage});
+
+ URL resourceUrlOne = new URL("file:/resource/one");
+ URL resourceUrlTwo = new URL("file:/resource/two");
+
+ this.installedBundleOne.addResources("META-INF/the.resource", createEnumeration(resourceUrlOne));
+ this.installedBundleTwo.addResources("META-INF/the.resource", createEnumeration(resourceUrlTwo));
+
+ Enumeration<?> postFindResources = this.hook.postFindResources("META-INF/the.resource", this.classLoader, null);
+ assertNotNull(postFindResources);
+
+ List<URL> results = new ArrayList<URL>();
+ while (postFindResources.hasMoreElements()) {
+ results.add((URL)postFindResources.nextElement());
+ }
+
+ assertEquals(2, results.size());
+ assertTrue(results.contains(resourceUrlOne));
+ assertTrue(results.contains(resourceUrlTwo));
+ }
+
+ private Enumeration<URL> createEnumeration(URL url) {
+ Vector<URL> vector = new Vector<URL>();
+ vector.add(url);
+ return vector.elements();
+ }
+
+ private static final class UnitTestMetaInfResourceClassLoaderDelegateHook extends MetaInfResourceClassLoaderDelegateHook {
+
+ public UnitTestMetaInfResourceClassLoaderDelegateHook(BundleContext systemBundleContext) {
+ super(systemBundleContext, null);
+ }
+
+ private final Map<Bundle, ExportedPackage[]> exportedPackages = new HashMap<Bundle, ExportedPackage[]>();
+
+ @Override
+ protected ExportedPackage[] getExportedPackages(Bundle bundle) {
+ return this.exportedPackages.get(bundle);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHookTests.java b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHookTests.java
new file mode 100644
index 00000000..70715e14
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableClassLoadingHookTests.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.osgi.baseadaptor.BaseData;
+import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate;
+import org.eclipse.osgi.launch.Equinox;
+import org.eclipse.virgo.osgi.extensions.equinox.EquinoxLauncherConfiguration;
+import org.eclipse.virgo.osgi.extensions.equinox.ExtendedEquinoxLauncher;
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.ClassLoaderCreator;
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableClassLoadingHook;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+
+/**
+ */
+public class PluggableClassLoadingHookTests {
+
+ private Equinox osgi;
+
+ private BundleContext context;
+
+ @Before
+ public void setUp() throws BundleException {
+ EquinoxLauncherConfiguration config = new EquinoxLauncherConfiguration();
+ config.setConfigPath(new File("target/config").toURI());
+ config.setInstallPath(new File("target/install").toURI());
+
+ this.osgi = ExtendedEquinoxLauncher.launch(config);
+ this.context = osgi.getBundleContext();
+ }
+
+ @After
+ public void after() throws BundleException {
+ if(this.osgi != null) {
+ this.osgi.stop();
+ }
+ }
+
+ @Test
+ public void testAddClassLoaderCreator() throws Exception {
+ final List<BaseData> baseDatas = new ArrayList<BaseData>();
+
+ ClassLoaderCreator creator = new ClassLoaderCreator() {
+
+ public BaseClassLoader createClassLoader(ClassLoader parent, ClassLoaderDelegate delegate, BundleProtectionDomain domain, BaseData data,
+ String[] bundleclasspath) {
+ baseDatas.add(data);
+ return null;
+ }
+
+ };
+
+ PluggableClassLoadingHook.getInstance().setClassLoaderCreator(creator);
+ this.context.registerService(ClassLoaderCreator.class.getName(), creator, null);
+
+ Bundle b = this.context.installBundle(new File("src/test/resources/hooks/classloading/bundle").toURI().toString());
+ try {
+ b.loadClass("foo");
+ fail("shouldn't be able to load foo!");
+ } catch (ClassNotFoundException e) {
+ // expected
+ assertEquals(1, baseDatas.size());
+ assertEquals("hooks.classloading", baseDatas.get(0).getSymbolicName());
+ }
+ }
+
+ @Test
+ public void testBundleClassLoaderParent() {
+ PluggableClassLoadingHook hook = PluggableClassLoadingHook.getInstance();
+
+ assertNull(hook.getBundleClassLoaderParent());
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ hook.setBundleClassLoaderParent(classLoader);
+ assertEquals(classLoader, hook.getBundleClassLoaderParent());
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHookTests.java b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHookTests.java
new file mode 100644
index 00000000..7db05d62
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/test/java/org/eclipse/virgo/kernel/equinox/extensions/hooks/PluggableDelegatingClassLoaderDelegateHookTests.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2010 VMware Inc.
+ * 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:
+ * VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.virgo.osgi.extensions.equinox.hooks;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Vector;
+
+import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
+import org.eclipse.osgi.framework.adaptor.BundleData;
+import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegateHook;
+import org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableDelegatingClassLoaderDelegateHook;
+import org.junit.Test;
+
+/**
+ * Tests for {@link PluggableDelegatingClassLoaderDelegateHook}
+ */
+public class PluggableDelegatingClassLoaderDelegateHookTests {
+
+ private final ClassLoaderDelegateHook hook1 = createMock(ClassLoaderDelegateHook.class);
+
+ private final ClassLoaderDelegateHook hook2 = createMock(ClassLoaderDelegateHook.class);
+
+ private final PluggableDelegatingClassLoaderDelegateHook delegatingHook = PluggableDelegatingClassLoaderDelegateHook.getInstance();
+
+ private final BundleClassLoader classLoader = createMock(BundleClassLoader.class);
+
+ private final BundleData bundleData = createMock(BundleData.class);
+
+ @Test
+ public void preFindClass() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("preFindClass", String.class, BundleClassLoader.class, BundleData.class), String.class);
+ }
+
+ @Test
+ public void postFindClass() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("postFindClass", String.class, BundleClassLoader.class, BundleData.class), String.class);
+ }
+
+ @Test
+ public void preFindResource() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("preFindResource", String.class, BundleClassLoader.class, BundleData.class), new URL("file:foo"));
+ }
+
+ @Test
+ public void postFindResource() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("postFindResource", String.class, BundleClassLoader.class, BundleData.class), new URL("file:foo"));
+ }
+
+ @Test
+ public void preFindLibrary() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("preFindLibrary", String.class, BundleClassLoader.class, BundleData.class), "library");
+ }
+
+ @Test
+ public void postFindLibrary() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("postFindLibrary", String.class, BundleClassLoader.class, BundleData.class), "library");
+ }
+
+ @Test
+ public void preFindResources() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("preFindResources", String.class, BundleClassLoader.class, BundleData.class), new Vector<URL>().elements());
+ }
+
+ @Test
+ public void postFindResources() throws Exception {
+ performTest(ClassLoaderDelegateHook.class.getMethod("postFindResources", String.class, BundleClassLoader.class, BundleData.class), new Vector<URL>().elements());
+ }
+
+ private void performTest(Method method, Object mockResult) throws Exception {
+
+ Object result = method.invoke(this.delegatingHook, "foo", this.classLoader, bundleData);
+ assertNull(result);
+
+ delegatingHook.addDelegate(hook1);
+ delegatingHook.addDelegate(hook2);
+
+ expect(method.invoke(hook1, "foo", this.classLoader, this.bundleData)).andReturn(null);
+ expect(method.invoke(hook2, "foo", this.classLoader, this.bundleData)).andReturn(null);
+
+ replay(hook1, hook2);
+
+ result = method.invoke(this.delegatingHook, "foo", this.classLoader, bundleData);
+ assertNull(result);
+
+ verify(hook1, hook2);
+
+ reset(hook1, hook2);
+
+ expect(method.invoke(hook1, "foo", this.classLoader, this.bundleData)).andReturn(mockResult);
+
+ replay(hook1, hook2);
+
+ result = method.invoke(this.delegatingHook, "foo", this.classLoader, bundleData);
+ assertEquals(mockResult, result);
+
+ delegatingHook.removeDelegate(hook1);
+ delegatingHook.removeDelegate(hook2);
+
+ result = method.invoke(this.delegatingHook, "foo", this.classLoader, bundleData);
+ assertNull(result);
+
+ verify(hook1, hook2);
+ }
+}
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/src/test/resources/hooks/classloading/bundle/META-INF/MANIFEST.MF b/org.eclipse.virgo.kernel.equinox.extensions/src/test/resources/hooks/classloading/bundle/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..b018ed42
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/src/test/resources/hooks/classloading/bundle/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1
+Bundle-Manifest-Version: 2
+Bundle-SymbolicName: hooks.classloading
diff --git a/org.eclipse.virgo.kernel.equinox.extensions/template.mf b/org.eclipse.virgo.kernel.equinox.extensions/template.mf
new file mode 100644
index 00000000..ebee1f1f
--- /dev/null
+++ b/org.eclipse.virgo.kernel.equinox.extensions/template.mf
@@ -0,0 +1,16 @@
+Bundle-ManifestVersion: 2
+Bundle-Name: Equinox Specific OSGi Extensions
+Bundle-SymbolicName: org.eclipse.virgo.osgi.extensions.equinox
+Bundle-Version: ${version}
+Fragment-Host: org.eclipse.osgi; extension:=framework
+Excluded-Exports:
+ *.internal.*,
+ org.eclipse.core.*,
+ org.eclipse.osgi.*,
+ org.osgi.framework.*,
+ org.osgi.service.*
+Excluded-Imports:
+ org.eclipse.core.*;version="0",
+ org.eclipse.osgi.*;version="0",
+ org.osgi.framework.*;version="0",
+ org.osgi.service.*;version="0"
diff --git a/org.eclipse.virgo.kernel.model/ivy.xml b/org.eclipse.virgo.kernel.model/ivy.xml
index e84a6b2c..77dccb21 100644
--- a/org.eclipse.virgo.kernel.model/ivy.xml
+++ b/org.eclipse.virgo.kernel.model/ivy.xml
@@ -15,7 +15,7 @@
<dependencies>
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev="${org.eclipse.virgo.teststubs}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
<dependency org="org.slf4j" name="com.springsource.slf4j.nop" rev="${org.slf4j}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.stubs" rev="latest.integration" conf="test->runtime"/>
diff --git a/org.eclipse.virgo.kernel.osgi/ivy.xml b/org.eclipse.virgo.kernel.osgi/ivy.xml
index b51d2346..7637e8e8 100644
--- a/org.eclipse.virgo.kernel.osgi/ivy.xml
+++ b/org.eclipse.virgo.kernel.osgi/ivy.xml
@@ -21,19 +21,19 @@
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.region" rev="${org.eclipse.equinox.region}" conf="compile->compile"/>
<dependency org='org.eclipse.virgo.mirrored' name='org.slf4j.api' rev='${org.slf4j.api}' conf='compile->runtime'/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.services" rev="latest.integration" conf="compile->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="aspects, compile->runtime"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.artifact" rev="latest.integration" conf="compile->compile"/>
+ <dependency org='org.eclipse.virgo.kernel' name='org.eclipse.virgo.kernel.equinox.extensions' rev='latest.integration' conf='compile->compile'/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="aspects, compile->runtime"/>
<dependency org='org.slf4j' name='com.springsource.slf4j.nop' rev='${org.slf4j}' conf='test->runtime' />
<dependency org='org.eclipse.virgo.repository' name='org.eclipse.virgo.repository' rev='${org.eclipse.virgo.repository}' conf='compile->compile' />
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.osgi.manifest' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.common' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.math' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
- <dependency org='org.eclipse.virgo.osgi' name='org.eclipse.virgo.osgi.extensions.equinox' rev='${org.eclipse.virgo.osgi}' conf='compile->compile'/>
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.io' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.parser.manifest' rev='${org.eclipse.virgo.util}' conf='compile->compile'/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
- <dependency org='org.eclipse.virgo.teststubs' name='org.eclipse.virgo.teststubs.osgi' rev='${org.eclipse.virgo.teststubs}' conf='test->runtime'/>
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.launcher" rev="${org.eclipse.virgo.osgi}" conf="compile->compile"/>
+ <dependency org='org.eclipse.virgo.test' name='org.eclipse.virgo.test.stubs' rev='${org.eclipse.virgo.test}' conf='test->runtime'/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.launcher" rev="${org.eclipse.virgo.test}" conf="test->compile"/>
<override org="org.eclipse.virgo.repository" rev="${org.eclipse.virgo.repository}"/>
<override org="org.eclipse.virgo.util" rev="${org.eclipse.virgo.util}"/>
diff --git a/org.eclipse.virgo.kernel.services/ivy.xml b/org.eclipse.virgo.kernel.services/ivy.xml
index ae345b00..07738c94 100644
--- a/org.eclipse.virgo.kernel.services/ivy.xml
+++ b/org.eclipse.virgo.kernel.services/ivy.xml
@@ -14,13 +14,13 @@
<dependencies>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.artifact" rev="latest.integration" conf="compile->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev='${org.eclipse.virgo.nano}' conf='compile->compile'/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev='${org.eclipse.virgo.nano}' conf='compile->compile'/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev='${org.easymock}' conf='test->runtime'/>
<dependency org="org.junit" name="com.springsource.org.junit" rev='${org.junit}' conf='test->runtime'/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic" rev='${org.eclipse.virgo.medic}' conf='aspects, compile->runtime'/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.core" rev='${org.eclipse.virgo.medic}' conf='runtime->runtime'/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.test" rev='${org.eclipse.virgo.medic}' conf='test->runtime'/>
- <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev='${org.eclipse.virgo.teststubs}' conf='test->runtime'/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev='${org.eclipse.virgo.test}' conf='test->runtime'/>
<dependency org="org.eclipse.virgo.repository" name="org.eclipse.virgo.repository" rev='${org.eclipse.virgo.repository}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.mirrored" name="org.slf4j.api" rev='${org.slf4j.api}' conf='compile->runtime'/>
<dependency org="org.slf4j" name="com.springsource.slf4j.nop" rev='${org.slf4j}' conf='test->runtime'/>
diff --git a/org.eclipse.virgo.kernel.shell/ivy.xml b/org.eclipse.virgo.kernel.shell/ivy.xml
index 77638a26..b83da33f 100644
--- a/org.eclipse.virgo.kernel.shell/ivy.xml
+++ b/org.eclipse.virgo.kernel.shell/ivy.xml
@@ -36,7 +36,7 @@
<dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.test" rev="${org.eclipse.virgo.medic}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.teststubs" name="org.eclipse.virgo.teststubs.osgi" rev="${org.eclipse.virgo.teststubs}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
<override org="org.springframework" rev="${org.springframework}"/>
<override org="org.slf4j" rev="${org.slf4j}"/>
diff --git a/org.eclipse.virgo.kernel.test/ivy.xml b/org.eclipse.virgo.kernel.test/ivy.xml
index ebe12f27..e177f458 100644
--- a/org.eclipse.virgo.kernel.test/ivy.xml
+++ b/org.eclipse.virgo.kernel.test/ivy.xml
@@ -35,7 +35,7 @@
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.console" rev="${org.eclipse.equinox.console}" conf="test->runtime" />
<dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.equinox.console.ssh" rev="${org.eclipse.equinox.console.ssh}" conf="test->runtime" />
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="test->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.deployer" rev="latest.integration" conf="test->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.shell" rev="latest.integration" conf="test->runtime"/>
@@ -51,9 +51,8 @@
<dependency org="org.eclipse.virgo.repository" name="org.eclipse.virgo.repository" rev="${org.eclipse.virgo.repository}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.framework" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
-
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.launcher" rev="${org.eclipse.virgo.osgi}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.extensions.equinox" rev="${org.eclipse.virgo.osgi}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.launcher" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.equinox.extensions" rev="latest.integration" conf="test->runtime"/>
<!-- the following conf should be test->runtime but for some reason that does not pull down the dependency -->
<dependency org="org.aspectj" name="com.springsource.org.aspectj.runtime" rev="${org.aspectj}" conf="test->runtime"/>
diff --git a/org.eclipse.virgo.kernel.userregion/ivy.xml b/org.eclipse.virgo.kernel.userregion/ivy.xml
index 80a26d92..b9a719bf 100644
--- a/org.eclipse.virgo.kernel.userregion/ivy.xml
+++ b/org.eclipse.virgo.kernel.userregion/ivy.xml
@@ -23,17 +23,17 @@
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.services" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.artifact" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.deployer" rev="latest.integration" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.kernel" name='org.eclipse.virgo.kernel.equinox.extensions' rev='latest.integration' conf='compile->compile' />
<dependency org="org.slf4j" name='com.springsource.slf4j.nop' rev='${org.slf4j}' conf='test->runtime' />
<dependency org="org.eclipse.virgo.repository" name='org.eclipse.virgo.repository' rev='${org.eclipse.virgo.repository}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.osgi' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.osgi.manifest' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.common' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.math' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
- <dependency org="org.eclipse.virgo.osgi" name='org.eclipse.virgo.osgi.extensions.equinox' rev='${org.eclipse.virgo.osgi}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.io' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org="org.eclipse.virgo.util" name='org.eclipse.virgo.util.parser.manifest' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
- <dependency org="org.eclipse.virgo.teststubs" name='org.eclipse.virgo.teststubs.osgi' rev='${org.eclipse.virgo.teststubs}' conf='test->runtime'/>
+ <dependency org="org.eclipse.virgo.test" name='org.eclipse.virgo.test.stubs' rev='${org.eclipse.virgo.test}' conf='test->runtime'/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="compile->compile"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="2.5.6.SEC01" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.core" rev="2.5.6.SEC01" conf="test->runtime"/>
diff --git a/org.eclipse.virgo.kernel.userregionfactory/ivy.xml b/org.eclipse.virgo.kernel.userregionfactory/ivy.xml
index ab1b3f3b..7cd2c51a 100644
--- a/org.eclipse.virgo.kernel.userregionfactory/ivy.xml
+++ b/org.eclipse.virgo.kernel.userregionfactory/ivy.xml
@@ -18,8 +18,7 @@
<dependency org="org.eclipse.virgo.mirrored" name='org.eclipse.equinox.region' rev='${org.eclipse.equinox.region}' conf='compile->compile' />
<dependency org='org.eclipse.virgo.medic' name='org.eclipse.virgo.medic' rev='${org.eclipse.virgo.medic}' conf='aspects, compile->runtime'/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.osgi" rev="latest.integration" conf="compile->compile"/>
- <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.kernel.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
- <dependency org="org.eclipse.virgo.osgi" name="org.eclipse.virgo.osgi.launcher" rev="${org.eclipse.virgo.osgi}" conf="compile->compile"/>
+ <dependency org="org.eclipse.virgo.nano" name="org.eclipse.virgo.nano.core" rev="${org.eclipse.virgo.nano}" conf="compile->compile"/>
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.osgi' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<dependency org='org.eclipse.virgo.util' name='org.eclipse.virgo.util.osgi.manifest' rev='${org.eclipse.virgo.util}' conf='compile->compile' />
<!-- TEST -->
@@ -27,7 +26,8 @@
<dependency org="org.slf4j" name="com.springsource.slf4j.nop" rev="${org.slf4j}" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
<dependency org="org.eclipse.virgo.medic" name="org.eclipse.virgo.medic.test" rev="${org.eclipse.virgo.medic}" conf="test->runtime"/>
- <dependency org='org.eclipse.virgo.teststubs' name='org.eclipse.virgo.teststubs.osgi' rev='${org.eclipse.virgo.teststubs}' conf='test->runtime'/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.launcher" rev="${org.eclipse.virgo.test}" conf="test->compile"/>
+ <dependency org='org.eclipse.virgo.test' name='org.eclipse.virgo.test.stubs' rev='${org.eclipse.virgo.test}' conf='test->runtime'/>
<exclude org="org.eclipse.osgi"/>
diff --git a/org.eclipse.virgo.kernel/ivy.xml b/org.eclipse.virgo.kernel/ivy.xml
index 2a57024a..14215d16 100644
--- a/org.eclipse.virgo.kernel/ivy.xml
+++ b/org.eclipse.virgo.kernel/ivy.xml
@@ -21,6 +21,7 @@
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.services" rev="latest.integration"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.shell" rev="latest.integration"/>
<dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.userregionfactory" rev="latest.integration"/>
+ <dependency org="org.eclipse.virgo.kernel" name="org.eclipse.virgo.kernel.equinox.extensions" rev="latest.integration"/>
</dependencies>
</ivy-module>
diff --git a/org.eclipse.virgo.management.shell/.classpath b/org.eclipse.virgo.management.shell/.classpath
new file mode 100644
index 00000000..94013f6d
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/test/java"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/OSGI_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.eclipse.virgo.mirrored/org.eclipse.osgi/3.8.0.v20120508-2119/org.eclipse.osgi-3.8.0.v20120508-2119.jar" sourcepath="/OSGI_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.7.1.R37x_v20110808-1106/org.eclipse.osgi-sources-3.7.1.R37x_v20110808-1106.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-2.3.0.jar" sourcepath="/OSGI_IVY_CACHE/org.easymock/com.springsource.org.easymock/2.3.0/com.springsource.org.easymock-sources-2.3.0.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/3.6.0.D-20120711092322/org.eclipse.virgo.teststubs.osgi-3.6.0.D-20120711092322.jar" sourcepath="OSGI_IVY_CACHE/org.eclipse.virgo.teststubs/org.eclipse.virgo.teststubs.osgi/2.2.0.D-20101207145338/org.eclipse.virgo.teststubs.osgi-sources-2.2.0.D-20101207145338.jar"/>
+ <classpathentry kind="var" path="OSGI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.12.RELEASE/com.springsource.org.aspectj.runtime-1.6.12.RELEASE.jar" sourcepath="/OSGI_IVY_CACHE/org.aspectj/com.springsource.org.aspectj.runtime/1.6.12.RELEASE/com.springsource.org.aspectj.runtime-sources-1.6.12.RELEASE.jar"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/org.eclipse.virgo.management.shell/.project b/org.eclipse.virgo.management.shell/.project
new file mode 100644
index 00000000..b8d30686
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.virgo.osgi.console</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/org.eclipse.virgo.management.shell/build.xml b/org.eclipse.virgo.management.shell/build.xml
new file mode 100644
index 00000000..decc3d49
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/build.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="org.eclipse.virgo.management.shell">
+
+ <property file="${basedir}/../build.properties"/>
+ <property file="${basedir}/../build.versions"/>
+ <import file="${basedir}/../virgo-build/standard/default.xml"/>
+
+ <!--target name="test.do" depends="quality-common.test.do, smoke-test"/-->
+
+</project>
diff --git a/org.eclipse.virgo.management.shell/ivy.xml b/org.eclipse.virgo.management.shell/ivy.xml
new file mode 100644
index 00000000..d8fc7ed8
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/ivy.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
+<ivy-module
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
+ version="1.3">
+
+ <info organisation="org.eclipse.virgo.osgi" module="${ant.project.name}" />
+
+ <configurations>
+ <include file="${virgo.build.dir}/common/default-ivy-configurations.xml"/>
+ </configurations>
+
+ <publications>
+ <artifact name="${ant.project.name}"/>
+ <artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
+ </publications>
+
+ <dependencies>
+ <dependency org="org.eclipse.virgo.mirrored" name="org.eclipse.osgi" rev="${org.eclipse.osgi}" conf="compile->compile"/>
+ <dependency org="org.junit" name="com.springsource.org.junit" rev="${org.junit}" conf="test->runtime"/>
+ <dependency org="org.easymock" name="com.springsource.org.easymock" rev="${org.easymock}" conf="test->runtime"/>
+ <dependency org="org.eclipse.virgo.test" name="org.eclipse.virgo.test.stubs" rev="${org.eclipse.virgo.test}" conf="test->runtime"/>
+
+ </dependencies>
+
+</ivy-module>
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleInputStream.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleInputStream.java
new file mode 100644
index 00000000..33ea0c0c
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleInputStream.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * This class serves as an input stream, which wraps the actual input (e.g. from the telnet) and buffers the lines.
+ */
+public class ConsoleInputStream extends InputStream {
+
+ private final ArrayList<byte[]> buffer = new ArrayList<byte[]>();
+
+ private byte[] current;
+
+ private int pos;
+
+ private boolean isClosed;
+
+ public synchronized int read() {
+ while (current == null && buffer.isEmpty() && !isClosed) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ return -1;
+ }
+ }
+ if (isClosed) {
+ return -1;
+ }
+
+ try {
+ if (current == null) {
+ current = buffer.remove(0);
+ return current[pos++] & 0xFF;
+ } else {
+
+ return current[pos++] & 0xFF;
+ }
+ } finally {
+ if (current != null) {
+ if (pos == current.length) {
+ current = null;
+ pos = 0;
+ }
+ }
+ }
+
+ }
+
+ public int read(byte b[], int off, int len) throws IOException {
+ if (len == 0) {
+ return len;
+ }
+ int i = read();
+ if (i == -1) {
+ return -1;
+ }
+ b[off] = (byte) i;
+ return 1;
+ }
+
+ public synchronized void close() throws IOException {
+ isClosed = true;
+ notifyAll();
+ }
+
+ public synchronized void add(byte[] data) {
+ if (data.length > 0) {
+ buffer.add(data);
+ notify();
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStream.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStream.java
new file mode 100644
index 00000000..16a4d763
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStream.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This class wraps the actual output stream (e.g., a socket output stream) and is responsible for buffering and
+ * flushing the characters to the actual output stream.
+ */
+public class ConsoleOutputStream extends OutputStream {
+
+ /**
+ * A size of the used buffer.
+ */
+ public static final int BUFFER_SIZE = 2048;
+
+ public final static byte CR = (byte) '\r';
+
+ public final static byte LF = (byte) '\n';
+
+ OutputStream out;
+
+ OutputStream oldOut;
+
+ private boolean isEcho = true;
+
+ private boolean queueing = false;
+
+ private byte prevByte;
+
+ private byte[] buffer;
+
+ private int pos;
+
+ /**
+ * Initiates with instance of the output stream to which it will send data. Here it writes to a socket output
+ * stream.
+ *
+ * @param out OutputStream for console output
+ */
+ public ConsoleOutputStream(OutputStream out) {
+ this.out = out;
+ buffer = new byte[BUFFER_SIZE];
+ pos = 0;
+ }
+
+ /**
+ * An implementation of the corresponding abstract method in OutputStream.
+ */
+ public synchronized void write(int i) throws IOException {
+
+ if (!queueing) {
+ if (isEcho) {
+ if (i == '\r' || i == '\0') {
+ queueing = true;
+ prevByte = (byte) i;
+ } else if (i == '\n') {
+ add(CR);
+ add(LF);
+ } else {
+ add(i);
+ }
+ }
+ } else { // awaiting '\n' AFTER '\r', and '\b' AFTER '\0'
+ if (prevByte == '\0' && i == '\b') {
+ isEcho = !isEcho;
+ } else if (isEcho) {
+ if (prevByte == '\r' && i == '\n') {
+ add(CR);
+ add(LF);
+ } else {
+ add(CR);
+ add(LF);
+ add(i);
+ }
+ }
+
+ queueing = false;
+ flush();
+ }
+
+ }
+
+ /**
+ * Empties the buffer and sends data to the socket output stream.
+ *
+ * @throws IOException
+ */
+ public synchronized void flush() throws IOException {
+ if (pos > 0) {
+ out.write(buffer, 0, pos);
+ pos = 0;
+ }
+ }
+
+ /**
+ * Adds a variable of type integer to the buffer.
+ *
+ * @param i integer to add
+ * @throws java.io.IOException if there are problems adding the integer
+ */
+ private void add(int i) throws IOException {
+ buffer[pos] = (byte) i;
+ pos++;
+
+ if (pos == buffer.length) {
+ flush();
+ }
+ }
+
+ /**
+ * Closes this OutputStream.
+ *
+ * @throws IOException
+ */
+ public void close() throws IOException {
+ out.close();
+ }
+
+ /**
+ * Substitutes the output stream. The old one is stored so that it can be restored later.
+ *
+ * @param newOut new output stream to use.
+ */
+ public void setOutput(OutputStream newOut) {
+ if (newOut != null) {
+ oldOut = out;
+ out = newOut;
+ } else {
+ out = oldOut;
+ }
+
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/InputHandler.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/InputHandler.java
new file mode 100644
index 00000000..06bd6e68
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/InputHandler.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.Scanner;
+
+/**
+ * This class represents a generic handler of content, read from some input stream. It reads from the stream, and passes
+ * what is read to a processor, which performs some actions on the content, eventually writing to an output stream. This
+ * handler should be customized with a concrete content processor.
+ */
+public abstract class InputHandler extends Thread {
+
+ protected Scanner inputScanner;
+
+ protected OutputStream out;
+
+ protected ConsoleInputStream in;
+
+ protected InputStream input;
+
+ protected byte[] buffer;
+
+ protected static final int MAX_SIZE = 2048;
+
+ public InputHandler(InputStream input, ConsoleInputStream in, OutputStream out) {
+ this.input = input;
+ this.in = in;
+ this.out = out;
+ buffer = new byte[MAX_SIZE];
+ }
+
+ public void run() {
+ int count;
+ try {
+ while ((count = input.read(buffer)) > -1) {
+ for (int i = 0; i < count; i++) {
+ inputScanner.scan(buffer[i]);
+ }
+ }
+ } catch (IOException e) {
+ // Printing stack trace is not needed since the streams are closed immediately
+ // do nothing
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e1) {
+ // do nothing
+ }
+ try {
+ out.close();
+ } catch (IOException e1) {
+ // do nothing
+ }
+ }
+ }
+
+ public Scanner getScanner() {
+ return inputScanner;
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/KEYS.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/KEYS.java
new file mode 100644
index 00000000..0a1636ac
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/KEYS.java
@@ -0,0 +1,16 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+public enum KEYS {
+ UP, DOWN, RIGHT, LEFT, CENTER, HOME, END, PGUP, PGDN, INS, DEL, UNFINISHED, UNKNOWN
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/Scanner.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/Scanner.java
new file mode 100644
index 00000000..903f4800
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/Scanner.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+import org.eclipse.virgo.osgi.console.telnet.ANSITerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.SCOTerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT100TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT220TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT320TerminalTypeMappings;
+
+/**
+ * A common superclass for content processor for the telnet protocol and for command line editing (processing delete,
+ * backspace, arrows, command history, etc.).
+ */
+public abstract class Scanner {
+
+ protected static final byte BS = 8;
+
+ private byte BACKSPACE;
+
+ protected static final byte LF = 10;
+
+ protected static final byte CR = 13;
+
+ protected static final byte ESC = 27;
+
+ protected static final byte SPACE = 32;
+
+ private byte DEL;
+
+ protected static final byte MAX_CHAR = 127;
+
+ protected static final String DEFAULT_TTYPE = File.separatorChar == '/' ? "XTERM" : "ANSI";
+
+ protected OutputStream toTelnet;
+
+ protected ConsoleInputStream toShell;
+
+ protected Map<String, KEYS> currentEscapesToKey;
+
+ protected final Map<String, TerminalTypeMappings> supportedEscapeSequences;
+
+ protected String[] escapes;
+
+ public Scanner(ConsoleInputStream toShell, OutputStream toTelnet) {
+ this.toShell = toShell;
+ this.toTelnet = toTelnet;
+ supportedEscapeSequences = new HashMap<String, TerminalTypeMappings>();
+ supportedEscapeSequences.put("ANSI", new ANSITerminalTypeMappings());
+ supportedEscapeSequences.put("VT100", new VT100TerminalTypeMappings());
+ VT220TerminalTypeMappings vtMappings = new VT220TerminalTypeMappings();
+ supportedEscapeSequences.put("VT220", new VT220TerminalTypeMappings());
+ supportedEscapeSequences.put("XTERM", vtMappings);
+ supportedEscapeSequences.put("VT320", new VT320TerminalTypeMappings());
+ supportedEscapeSequences.put("SCO", new SCOTerminalTypeMappings());
+ }
+
+ public abstract void scan(int b) throws IOException;
+
+ protected void echo(int b) throws IOException {
+ toTelnet.write(b);
+ }
+
+ protected void flush() throws IOException {
+ toTelnet.flush();
+ }
+
+ protected KEYS checkEscape(String possibleEsc) {
+ if (currentEscapesToKey.get(possibleEsc) != null) {
+ return currentEscapesToKey.get(possibleEsc);
+ }
+
+ for (String escape : escapes) {
+ if (escape.startsWith(possibleEsc)) {
+ return KEYS.UNFINISHED;
+ }
+ }
+ return KEYS.UNKNOWN;
+ }
+
+ protected String esc;
+
+ protected boolean isEsc = false;
+
+ protected void startEsc() {
+ isEsc = true;
+ esc = "";
+ }
+
+ protected abstract void scanEsc(final int b) throws IOException;
+
+ public byte getBackspace() {
+ return BACKSPACE;
+ }
+
+ public void setBackspace(byte backspace) {
+ BACKSPACE = backspace;
+ }
+
+ public byte getDel() {
+ return DEL;
+ }
+
+ public void setDel(byte del) {
+ DEL = del;
+ }
+
+ public Map<String, KEYS> getCurrentEscapesToKey() {
+ return currentEscapesToKey;
+ }
+
+ public void setCurrentEscapesToKey(Map<String, KEYS> currentEscapesToKey) {
+ this.currentEscapesToKey = currentEscapesToKey;
+ }
+
+ public String[] getEscapes() {
+ if (escapes != null) {
+ return Arrays.copyOf(escapes, escapes.length);
+ } else {
+ return null;
+ }
+ }
+
+ public void setEscapes(String[] escapes) {
+ if (escapes != null) {
+ this.escapes = Arrays.copyOf(escapes, escapes.length);
+ } else {
+ this.escapes = null;
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/SimpleByteBuffer.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/SimpleByteBuffer.java
new file mode 100644
index 00000000..d00ca538
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/common/SimpleByteBuffer.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+/**
+ * This is a helper class, which buffers one line of input. It provides for simple line editing - insertion, deletion,
+ * left and right movement, deletion through the backspace key.
+ */
+public class SimpleByteBuffer {
+
+ private static int INITAL_SIZE = 13;
+
+ private byte[] buffer;
+
+ private int pos = 0;
+
+ private int size = 0;
+
+ public SimpleByteBuffer() {
+ buffer = new byte[INITAL_SIZE];
+ }
+
+ public void add(final int b) {
+ if (size >= buffer.length) {
+ rezize();
+ }
+ buffer[size++] = (byte) b;
+ }
+
+ private void rezize() {
+ final byte[] newbuffeer = new byte[buffer.length << 1];
+ System.arraycopy(buffer, 0, newbuffeer, 0, buffer.length);
+ buffer = newbuffeer;
+ }
+
+ public void insert(int b) {
+ if (size >= buffer.length) {
+ rezize();
+ }
+ final int forCopy = size - pos;
+ if (forCopy > 0) {
+ System.arraycopy(buffer, pos, buffer, pos + 1, forCopy);
+ }
+ buffer[pos++] = (byte) b;
+ size++;
+ }
+
+ public int goRight() {
+ if (pos < size) {
+ return buffer[pos++] & 0xFF;
+ }
+ return -1;
+ }
+
+ public boolean goLeft() {
+ if (pos > 0) {
+ pos--;
+ return true;
+ }
+ return false;
+ }
+
+ public void delete() {
+ if (pos < size) {
+ final int forCopy = size - pos;
+ System.arraycopy(buffer, pos + 1, buffer, pos, forCopy);
+ size--;
+ }
+ }
+
+ public boolean backSpace() {
+ if (pos > 0 && size > 0) {
+ final int forCopy = size - pos;
+ System.arraycopy(buffer, pos, buffer, pos - 1, forCopy);
+ size--;
+ pos--;
+ return true;
+ }
+ return false;
+ }
+
+ public void delAll() {
+ pos = 0;
+ size = 0;
+ }
+
+ public byte[] getCurrentData() {
+ byte[] res = new byte[size];
+ System.arraycopy(buffer, 0, res, 0, size);
+ pos = 0;
+ size = 0;
+ return res;
+ }
+
+ public void set(byte[] newData) {
+ pos = 0;
+ size = 0;
+ if (newData != null) {
+ for (byte data : newData) {
+ insert(data);
+ }
+ }
+ }
+
+ public int getPos() {
+ return pos;
+ }
+
+ public byte[] copyCurrentData() {
+ byte[] res = new byte[size];
+ System.arraycopy(buffer, 0, res, 0, size);
+ return res;
+ }
+
+ public int getCurrentChar() {
+ if (pos < size) {
+ return buffer[pos] & 0xFF;
+ } else {
+ return -1;
+ }
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int resetPos() {
+ int res = pos;
+ pos = 0;
+ return res;
+ }
+
+ public void replace(int b) {
+ if (pos == size) {
+ insert(b);
+ } else {
+ buffer[pos++] = (byte) b;
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/CommandCompleter.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/CommandCompleter.java
new file mode 100644
index 00000000..42bea126
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/CommandCompleter.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class implements basic command completion. It can complete only OSGi commands, not command parameters. It
+ * registers a tracker, with which it tracks all CommandProvider services, and when a new one becomes available, it adds
+ * its command methods in a local cache, which the completer uses to complete the command name given the first letters
+ * of the command.
+ */
+public class CommandCompleter {
+
+ private Set<String> availableCommands;
+
+ private ServiceTracker<CommandProvider, Object> cpTracker;
+
+ private BundleContext context = null;
+
+ public CommandCompleter(BundleContext context) {
+ this.context = context;
+ availableCommands = new HashSet<String>();
+ availableCommands = Collections.synchronizedSet(availableCommands);
+ availableCommands.add("more");
+ availableCommands.add("disconnect");
+ availableCommands.add("grep");
+ if (context != null) {
+ cpTracker = new ServiceTracker<CommandProvider, Object>(context, CommandProvider.class.getName(), new CommandProviderCustomizer());
+ cpTracker.open();
+ }
+ }
+
+ public String[] complete(String prefix) {
+ ArrayList<String> candidates = new ArrayList<String>();
+ for (String command : availableCommands) {
+ if (command.startsWith(prefix)) {
+ candidates.add(command);
+ }
+ }
+
+ return candidates.toArray(new String[candidates.size()]);
+ }
+
+ class CommandProviderCustomizer implements ServiceTrackerCustomizer<CommandProvider, Object> {
+
+ public Object addingService(ServiceReference<CommandProvider> reference) {
+ CommandProvider provider = context.getService(reference);
+ Method[] methods = provider.getClass().getMethods();
+ for (Method method : methods) {
+ if (method.getName().startsWith("_")) {
+ availableCommands.add(method.getName().substring(1));
+ }
+ }
+ return null;
+ }
+
+ public void modifiedService(ServiceReference<CommandProvider> reference, Object service) {
+ // do nothing
+ }
+
+ public void removedService(ServiceReference<CommandProvider> reference, Object service) {
+ CommandProvider provider = context.getService(reference);
+ Method[] methods = provider.getClass().getMethods();
+ for (Method method : methods) {
+ if (method.getName().startsWith("_")) {
+ availableCommands.remove(method.getName());
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandler.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandler.java
new file mode 100644
index 00000000..234b522a
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandler.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.virgo.osgi.console.supportability.ConsoleInputScanner;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.InputHandler;
+import org.osgi.framework.BundleContext;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * This class customizes the generic handler with a concrete content processor, which provides command line editing.
+ */
+public class ConsoleInputHandler extends InputHandler {
+
+ public ConsoleInputHandler(InputStream input, ConsoleInputStream in, OutputStream out, BundleContext context) {
+ super(input, in, out);
+ inputScanner = new ConsoleInputScanner(in, out, context);
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScanner.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScanner.java
new file mode 100644
index 00000000..7dcab178
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScanner.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.virgo.osgi.console.supportability.CommandCompleter;
+import org.eclipse.virgo.osgi.console.supportability.Grep;
+import org.eclipse.virgo.osgi.console.supportability.HistoryHolder;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+import org.eclipse.virgo.osgi.console.common.Scanner;
+import org.eclipse.virgo.osgi.console.common.SimpleByteBuffer;
+import org.osgi.framework.BundleContext;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+/**
+ * This class performs the processing of the input special characters, and updates respectively what is displayed in the
+ * output. It handles escape sequences, delete, backspace, arrows, and provides command history and grep.
+ */
+public class ConsoleInputScanner extends Scanner {
+
+ private static final byte TAB = 9;
+
+ private boolean isCR = false;
+
+ private boolean replace = false;
+
+ private final HistoryHolder history;
+
+ private final SimpleByteBuffer buffer;
+
+ private CommandCompleter completer;
+
+ public ConsoleInputScanner(ConsoleInputStream toShell, OutputStream toTelnet, BundleContext context) {
+ super(toShell, toTelnet);
+ history = new HistoryHolder();
+ buffer = new SimpleByteBuffer();
+ completer = new CommandCompleter(context);
+ }
+
+ public void scan(int b) throws IOException {
+ b &= 0xFF;
+ if (isCR) {
+ isCR = false;
+ if (b == LF) {
+ return;
+ }
+ }
+ if (isEsc) {
+ scanEsc(b);
+ } else {
+ if (b == getBackspace()) {
+ backSpace();
+ } else if (b == TAB) {
+ tab();
+ } else if (b == CR) {
+ isCR = true;
+ processData();
+ } else if (b == LF) {
+ processData();
+ } else if (b == ESC) {
+ startEsc();
+ } else if (b == getDel()) {
+ delete();
+ } else {
+ if (b >= SPACE && b < MAX_CHAR) {
+ newChar(b);
+ }
+ }
+ }
+ }
+
+ private void delete() throws IOException {
+ clearLine();
+ buffer.delete();
+ echoBuff();
+ flush();
+ }
+
+ private void backSpace() throws IOException {
+ clearLine();
+ buffer.backSpace();
+ echoBuff();
+ flush();
+ }
+
+ private void tab() throws IOException {
+ byte[] cur = buffer.copyCurrentData();
+ String currentInput = new String(cur).trim();
+ String[] completionCandidates = completer.complete(currentInput);
+
+ if (completionCandidates.length == 1) {
+ String suffix = completionCandidates[0].substring(currentInput.length());
+ byte[] completion = suffix.getBytes();
+ for (byte symbol : completion) {
+ buffer.insert(symbol);
+ echo(symbol);
+
+ }
+ flush();
+ return;
+ }
+
+ echo(CR);
+ echo(LF);
+ flush();
+
+ if (completionCandidates.length == 0) {
+ buffer.getCurrentData();
+ String errorMessage = "No such command";
+ for (byte symbol : errorMessage.getBytes()) {
+ echo(symbol);
+ }
+ } else {
+ for (String candidate : completionCandidates) {
+ for (byte symbol : candidate.getBytes()) {
+ echo(symbol);
+ }
+ echo(SPACE);
+ echo(SPACE);
+ }
+ }
+
+ echo(CR);
+ echo(LF);
+ flush();
+ echo('o');
+ echo('s');
+ echo('g');
+ echo('i');
+ echo('>');
+ echo(SPACE);
+ echoBuff();
+ flush();
+ }
+
+ protected void clearLine() throws IOException {
+ int size = buffer.getSize();
+ int pos = buffer.getPos();
+ for (int i = size - pos; i < size; i++) {
+ echo(BS);
+ }
+ for (int i = 0; i < size; i++) {
+ echo(SPACE);
+ }
+ for (int i = 0; i < size; i++) {
+ echo(BS);
+ }
+ }
+
+ protected void echoBuff() throws IOException {
+ byte[] data = buffer.copyCurrentData();
+ for (byte b : data) {
+ echo(b);
+ }
+ int pos = buffer.getPos();
+ for (int i = data.length; i > pos; i--) {
+ echo(BS);
+ }
+ }
+
+ protected void newChar(int b) throws IOException {
+ if (buffer.getPos() < buffer.getSize()) {
+ if (replace) {
+ buffer.replace(b);
+ } else {
+ buffer.insert(b);
+ }
+ clearLine();
+ echoBuff();
+ flush();
+ } else {
+ if (replace) {
+ buffer.replace(b);
+ } else {
+ buffer.insert(b);
+ }
+ }
+ }
+
+ private void processData() throws IOException {
+ buffer.add(CR);
+ buffer.add(LF);
+ echo(CR);
+ echo(LF);
+ flush();
+ byte[] curr = buffer.getCurrentData();
+ history.add(curr);
+
+ int index = 0;
+ boolean isGrep = false;
+ for (; index < curr.length; index++) {
+ if (curr[index] == '|') {
+ isGrep = true;
+ break;
+ }
+ }
+
+ if (isGrep) {
+ byte[] grepExpression = new byte[curr.length - index - 1];
+ System.arraycopy(curr, index + 1, grepExpression, 0, grepExpression.length);
+ Grep grep = new Grep(grepExpression, toTelnet);
+ grep.start();
+ byte[] array = Arrays.copyOf(curr, index + 2);
+ array[index] = CR;
+ array[index + 1] = LF;
+ toShell.add(array);
+ } else {
+ toShell.add(curr);
+ }
+ }
+
+ public void resetHistory() {
+ history.reset();
+ }
+
+ protected void scanEsc(final int b) throws IOException {
+ esc += (char) b;
+ KEYS key = checkEscape(esc);
+ if (key == KEYS.UNFINISHED) {
+ return;
+ }
+ if (key == KEYS.UNKNOWN) {
+ isEsc = false;
+ scan(b);
+ return;
+ }
+ isEsc = false;
+ switch (key) {
+ case UP:
+ processUpArrow();
+ break;
+ case DOWN:
+ processDownArrow();
+ break;
+ case RIGHT:
+ processRightArrow();
+ break;
+ case LEFT:
+ processLeftArrow();
+ break;
+ case HOME:
+ processHome();
+ break;
+ case END:
+ processEnd();
+ break;
+ case PGUP:
+ processPgUp();
+ break;
+ case PGDN:
+ processPgDn();
+ break;
+ case INS:
+ processIns();
+ break;
+ case DEL:
+ delete();
+ break;
+ default: // CENTER
+ break;
+ }
+ }
+
+ private static final byte[] INVERSE_ON = { ESC, '[', '7', 'm' };
+
+ private static final byte[] INVERSE_OFF = { ESC, '[', '2', '7', 'm' };
+
+ private void echo(byte[] data) throws IOException {
+ for (byte b : data) {
+ echo(b);
+ }
+ }
+
+ private void processIns() throws IOException {
+ replace = !replace;
+ int b = buffer.getCurrentChar();
+ echo(INVERSE_ON);
+ echo(replace ? 'R' : 'I');
+ flush();
+ try {
+ Thread.sleep(300);
+ } catch (InterruptedException e) {
+ // do not care $JL-EXC$
+ }
+ echo(INVERSE_OFF);
+ echo(BS);
+ echo(b == -1 ? SPACE : b);
+ echo(BS);
+ flush();
+ }
+
+ private void processPgDn() throws IOException {
+ byte[] last = history.last();
+ if (last != null) {
+ clearLine();
+ buffer.set(last);
+ echoBuff();
+ flush();
+ }
+ }
+
+ private void processPgUp() throws IOException {
+ byte[] first = history.first();
+ if (first != null) {
+ clearLine();
+ buffer.set(first);
+ echoBuff();
+ flush();
+ }
+ }
+
+ private void processHome() throws IOException {
+ int pos = buffer.resetPos();
+ if (pos > 0) {
+ for (int i = 0; i < pos; i++) {
+ echo(BS);
+ }
+ flush();
+ }
+ }
+
+ private void processEnd() throws IOException {
+ int b;
+ while ((b = buffer.goRight()) != -1) {
+ echo(b);
+ }
+ flush();
+ }
+
+ private void processLeftArrow() throws IOException {
+ if (buffer.goLeft()) {
+ echo(BS);
+ flush();
+ }
+ }
+
+ private void processRightArrow() throws IOException {
+ int b = buffer.goRight();
+ if (b != -1) {
+ echo(b);
+ flush();
+ }
+ }
+
+ private void processDownArrow() throws IOException {
+ byte[] next = history.next();
+ if (next != null) {
+ clearLine();
+ buffer.set(next);
+ echoBuff();
+ flush();
+ }
+ }
+
+ private void processUpArrow() throws IOException {
+ clearLine();
+ byte[] prev = history.prev();
+ buffer.set(prev);
+ echoBuff();
+ flush();
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/Grep.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/Grep.java
new file mode 100644
index 00000000..2f26001e
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/Grep.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+
+import java.io.*;
+import java.util.ArrayList;
+
+/**
+ * This class implements grep. Since in Equinox 3.6 there is not piping support, grep cannot be implemented as a shell
+ * command. That is why it is implemented as part of the command line editing features. The socket output stream inside
+ * ConsoleOutputStream is substituted with a PipedOutputStream, so that what the command writes to the output stream
+ * does not go to the console, but is read through a PipedInputStream and is filtered for the searched expression. After
+ * all output of the command is read and filtered, the socket output stream inside ConsoleOutputStream is restored and
+ * the lines of the command output, which match the grep expression, are written to it.
+ */
+public class Grep extends Thread {
+
+ private String expression;
+
+ private ConsoleOutputStream out;
+
+ private PipedInputStream input;
+
+ private PipedOutputStream output;
+
+ private BufferedReader reader;
+
+ private ArrayList<String> filteredOutput;
+
+ private static int LENGTH = 4;
+
+ public Grep(byte[] expression, OutputStream out) {
+ String expr = (new String(expression)).trim();
+ int index = expr.indexOf("grep");
+ this.expression = expr.substring(index + LENGTH).trim();
+ this.out = (ConsoleOutputStream) out;
+ input = new PipedInputStream();
+ try {
+ output = new PipedOutputStream(input);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ this.out.setOutput(output);
+ filteredOutput = new ArrayList<String>();
+ }
+
+ public void run() {
+ reader = new BufferedReader(new InputStreamReader(input));
+ boolean hasMore = true;
+ try {
+ while (hasMore) {
+ String line = getLine();
+ hasMore = line != null;
+ if (hasMore) {
+ // last line containing the osgi prompt should be output although it does not contain the grep
+ // expression
+ if (line.contains(expression) || line.contains("osgi>")) {
+ filteredOutput.add(line);
+ }
+
+ if (line.contains("osgi>")) {
+ hasMore = false;
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ out.setOutput(null);
+ PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)));
+ for (int i = 0; i < filteredOutput.size(); i++) {
+ if (i == filteredOutput.size() - 1 && filteredOutput.get(i).contains("osgi>")) {
+ writer.print(filteredOutput.get(i));
+ writer.print(" ");
+ } else {
+ writer.println(filteredOutput.get(i));
+ }
+ writer.flush();
+ }
+ }
+
+ private String getLine() throws IOException {
+ StringBuilder line = new StringBuilder();
+ boolean quit = false;
+ while (!quit) {
+ int c = reader.read();
+ if (c < 0) {
+ quit = true;
+ } else {
+ switch (c) {
+ case '\r':
+ break;
+ case '\n':
+ return line.toString();
+ default:
+ line.append((char) c);
+ if (line.toString().contains("osgi>")) {
+ return line.toString();
+ }
+ break;
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/HistoryHolder.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/HistoryHolder.java
new file mode 100644
index 00000000..dc39af95
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/supportability/HistoryHolder.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+/**
+ * A helper class, which implements history.
+ */
+public class HistoryHolder {
+
+ private static final int MAX = 100;
+
+ private final byte[][] history;
+
+ private int size;
+
+ private int pos;
+
+ public HistoryHolder() {
+ history = new byte[MAX][];
+ }
+
+ public synchronized void reset() {
+ size = 0;
+ pos = 0;
+ for (int i = 0; i < MAX; i++) {
+ history[i] = null;
+ }
+ }
+
+ public synchronized void add(byte[] data) {
+ try {
+ data = new String(data, "US-ASCII").trim().getBytes("US-ASCII");
+ } catch (UnsupportedEncodingException e) {
+
+ }
+ if (data.length == 0) {
+ pos = size;
+ return;
+ }
+ for (int i = 0; i < size; i++) {
+ if (Arrays.equals(history[i], data)) {
+ System.arraycopy(history, i + 1, history, i, size - i - 1);
+ history[size - 1] = data;
+ pos = size;
+ return;
+ }
+ }
+ if (size >= MAX) {
+ System.arraycopy(history, 1, history, 0, size - 1);
+ size--;
+ }
+ history[size++] = data;
+ pos = size;
+ }
+
+ public synchronized byte[] next() {
+ if (pos >= size - 1) {
+ return null;
+ }
+ return history[++pos];
+ }
+
+ public synchronized byte[] last() {
+ if (size > 0) {
+ pos = size - 1;
+ return history[pos];
+ } else {
+ return null;
+ }
+ }
+
+ public synchronized byte[] first() {
+ if (size > 0) {
+ pos = 0;
+ return history[pos];
+ } else {
+ return null;
+ }
+ }
+
+ public synchronized byte[] prev() {
+ if (size == 0) {
+ return null;
+ }
+ if (pos == 0) {
+ return history[pos];
+ } else {
+ return history[--pos];
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/ANSITerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/ANSITerminalTypeMappings.java
new file mode 100644
index 00000000..9468f7f0
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/ANSITerminalTypeMappings.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+
+public class ANSITerminalTypeMappings extends TerminalTypeMappings {
+
+ public ANSITerminalTypeMappings() {
+ super();
+ BACKSPACE = 8;
+ DEL = 127;
+ }
+
+ public void setKeypadMappings() {
+ escapesToKey.put("[1~", KEYS.HOME); //$NON-NLS-1$
+ escapesToKey.put("[4~", KEYS.END); //$NON-NLS-1$
+ escapesToKey.put("[5~", KEYS.PGUP); //$NON-NLS-1$
+ escapesToKey.put("[6~", KEYS.PGDN); //$NON-NLS-1$
+ escapesToKey.put("[2~", KEYS.INS); //$NON-NLS-1$
+ escapesToKey.put("[3~", KEYS.DEL); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/Callback.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/Callback.java
new file mode 100644
index 00000000..6b2474e8
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/Callback.java
@@ -0,0 +1,17 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+public interface Callback {
+
+ public void finished();
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallback.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallback.java
new file mode 100644
index 00000000..883c6ead
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallback.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.Callback;
+import org.eclipse.virgo.osgi.console.telnet.TelnetConsoleSession;
+
+public class NegotiationFinishedCallback implements Callback {
+
+ private TelnetConsoleSession consoleSession;
+
+ public NegotiationFinishedCallback(TelnetConsoleSession consoleSession) {
+ this.consoleSession = consoleSession;
+ }
+
+ @Override
+ public void finished() {
+ consoleSession.telnetNegotiationFinished();
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/SCOTerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/SCOTerminalTypeMappings.java
new file mode 100644
index 00000000..b337e99a
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/SCOTerminalTypeMappings.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+
+public class SCOTerminalTypeMappings extends TerminalTypeMappings {
+
+ public SCOTerminalTypeMappings() {
+ super();
+
+ BACKSPACE = -1;
+ DEL = 127;
+ }
+
+ @Override
+ public void setKeypadMappings() {
+ escapesToKey.put("[H", KEYS.HOME);
+ escapesToKey.put("F", KEYS.END);
+ escapesToKey.put("[L", KEYS.INS);
+ escapesToKey.put("[I", KEYS.PGUP);
+ escapesToKey.put("[G", KEYS.PGDN);
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSession.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSession.java
new file mode 100644
index 00000000..d955e575
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSession.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ * Hristo Iliev, SAP AG
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.Callback;
+import org.eclipse.virgo.osgi.console.telnet.NegotiationFinishedCallback;
+import org.eclipse.virgo.osgi.console.telnet.TelnetInputHandler;
+import org.eclipse.virgo.osgi.console.telnet.TelnetOutputStream;
+import org.eclipse.osgi.framework.console.ConsoleSession;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.supportability.ConsoleInputHandler;
+import org.osgi.framework.BundleContext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * This class provides an implementation of a ConsoleSession. It creates a handler for the input from telnet and wraps
+ * its streams to add handling for command line editing.
+ */
+public class TelnetConsoleSession extends ConsoleSession {
+
+ private final Socket s;
+
+ private InputStream input;
+
+ private final ConsoleInputStream in;
+
+ private final TelnetOutputStream out;
+
+ protected boolean isTelnetNegotiationFinished = false;
+
+ private Callback callback;
+
+ private static final long TIMEOUT = 1000;
+
+ private static final long NEGOTIATION_TIMEOUT = 60000;
+
+ private final BundleContext context;
+
+ public TelnetConsoleSession(Socket s, BundleContext context) throws IOException {
+ in = new ConsoleInputStream();
+ out = new TelnetOutputStream(s.getOutputStream());
+ out.autoSend();
+ this.s = s;
+ this.context = context;
+
+ callback = new NegotiationFinishedCallback(this);
+ }
+
+ public synchronized void start() throws IOException {
+ start(NEGOTIATION_TIMEOUT);
+ }
+
+ public synchronized void start(long negotiationTimeout) throws IOException {
+ TelnetInputHandler telnetInputHandler = new TelnetInputHandler(s.getInputStream(), in, out, callback);
+ telnetInputHandler.start();
+ long start = System.currentTimeMillis();
+ while (isTelnetNegotiationFinished == false && System.currentTimeMillis() - start < negotiationTimeout) {
+ try {
+ wait(TIMEOUT);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+
+ ConsoleInputStream inp = new ConsoleInputStream();
+
+ ConsoleInputHandler consoleInputHandler = new ConsoleInputHandler(in, inp, out, context);
+ consoleInputHandler.getScanner().setBackspace(telnetInputHandler.getScanner().getBackspace());
+ consoleInputHandler.getScanner().setDel(telnetInputHandler.getScanner().getDel());
+ consoleInputHandler.getScanner().setCurrentEscapesToKey(telnetInputHandler.getScanner().getCurrentEscapesToKey());
+ consoleInputHandler.getScanner().setEscapes(telnetInputHandler.getScanner().getEscapes());
+
+ consoleInputHandler.start();
+ input = inp;
+ }
+
+ public synchronized void telnetNegotiationFinished() {
+ isTelnetNegotiationFinished = true;
+ notify();
+
+ }
+
+ public synchronized InputStream getInput() {
+ return input;
+ }
+
+ public synchronized OutputStream getOutput() {
+ return out;
+ }
+
+ public synchronized void doClose() {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (IOException ioe) {
+ // do nothing
+ }
+ }
+
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException ioe) {
+ // do nothing
+ }
+ }
+
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException ioe) {
+ // do nothing
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandler.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandler.java
new file mode 100644
index 00000000..8ab3f3c9
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandler.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.Callback;
+import org.eclipse.virgo.osgi.console.telnet.TelnetInputScanner;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.eclipse.virgo.osgi.console.common.InputHandler;
+
+import java.io.InputStream;
+
+/**
+ * This class customizes the generic handler with a concrete content processor, which provides telnet protocol handling.
+ */
+public class TelnetInputHandler extends InputHandler {
+
+ public TelnetInputHandler(InputStream input, ConsoleInputStream in, ConsoleOutputStream out, Callback callback) {
+ super(input, in, out);
+ inputScanner = new TelnetInputScanner(in, out, callback);
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScanner.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScanner.java
new file mode 100644
index 00000000..8f865b92
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScanner.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.Callback;
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+import org.eclipse.virgo.osgi.console.common.Scanner;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class performs the processing of the telnet commands, and updates respectively what is displayed in the output.
+ */
+public class TelnetInputScanner extends Scanner {
+
+ private boolean isCommand = false;
+
+ private boolean isReadingTtype = false;
+
+ private boolean shouldFinish = false;
+
+ private boolean tTypeNegotiationStarted = false;
+
+ private int lastRead = -1;
+
+ private ArrayList<Integer> currentTerminalType = new ArrayList<Integer>();
+
+ private ArrayList<Integer> lastTerminalType = null;
+
+ private Set<String> supportedTerminalTypes = new HashSet<String>();
+
+ private Callback callback;
+
+ public TelnetInputScanner(ConsoleInputStream toShell, ConsoleOutputStream toTelnet, Callback callback) {
+ super(toShell, toTelnet);
+ initializeSupportedTerminalTypes();
+ TerminalTypeMappings currentMapping = supportedEscapeSequences.get(DEFAULT_TTYPE);
+ currentEscapesToKey = currentMapping.getEscapesToKey();
+ escapes = currentMapping.getEscapes();
+ setBackspace(currentMapping.getBackspace());
+ setDel(currentMapping.getDel());
+ this.callback = callback;
+ }
+
+ private void initializeSupportedTerminalTypes() {
+ supportedTerminalTypes.add("ANSI");
+ supportedTerminalTypes.add("VT100");
+ supportedTerminalTypes.add("VT220");
+ supportedTerminalTypes.add("VT320");
+ supportedTerminalTypes.add("XTERM");
+ supportedTerminalTypes.add("SCO");
+ }
+
+ public void scan(int b) throws IOException {
+ b &= 0xFF;
+
+ if (isEsc) {
+ scanEsc(b);
+ } else if (isCommand) {
+ scanCommand(b);
+ } else if (b == IAC) {
+ startCommand();
+ } else {
+ switch (b) {
+ case ESC:
+ startEsc();
+ toShell.add(new byte[] { (byte) b });
+ break;
+ default:
+ if (b >= SPACE && b < MAX_CHAR) {
+ echo((byte) b);
+ flush();
+ }
+ toShell.add(new byte[] { (byte) b });
+ }
+
+ }
+ lastRead = b;
+ }
+
+ /*
+ * Telnet command codes are described in RFC 854, TELNET PROTOCOL SPECIFICATION available at
+ * http://www.ietf.org/rfc/rfc854.txt
+ *
+ * Telnet terminal type negotiation option is described in RFC 1091, Telnet Terminal-Type Option available at
+ * http://www.ietf.org/rfc/rfc1091.txt
+ */
+ private static final int SE = 240;
+
+ private static final int EC = 247;
+
+ private static final int EL = 248;
+
+ private static final int SB = 250;
+
+ private static final int WILL = 251;
+
+ private static final int WILL_NOT = 252;
+
+ private static final int DO = 253;
+
+ private static final int DO_NOT = 254;
+
+ private static final int TTYPE = 24;
+
+ private static final int SEND = 1;
+
+ private static final int IAC = 255;
+
+ private static final int IS = 0;
+
+ private boolean isNegotiation;
+
+ private boolean isWill;
+
+ private byte[] tTypeRequest = { (byte) IAC, (byte) SB, (byte) TTYPE, (byte) SEND, (byte) IAC, (byte) SE };
+
+ private void scanCommand(final int b) throws IOException {
+ if (isNegotiation) {
+ scanNegotiation(b);
+ } else if (isWill) {
+ isWill = false;
+ isCommand = false;
+ if (b == TTYPE && tTypeNegotiationStarted == false) {
+ sendRequest();
+ }
+ } else {
+ switch (b) {
+ case WILL:
+ isWill = true;
+ break;
+ case WILL_NOT:
+ break;
+ case DO:
+ break;
+ case DO_NOT:
+ break;
+ case SB:
+ isNegotiation = true;
+ break;
+ case EC:
+ eraseChar();
+ isCommand = false;
+ break;
+ case EL:
+ default:
+ isCommand = false;
+ break;
+ }
+ }
+ }
+
+ private void scanNegotiation(final int b) {
+ if (lastRead == SB && b == TTYPE) {
+ isReadingTtype = true;
+ } else if (b == IS) {
+
+ } else if (b == IAC) {
+
+ } else if (b == SE) {
+ isNegotiation = false;
+ isCommand = false;
+ if (isReadingTtype == true) {
+ isReadingTtype = false;
+ if (shouldFinish == true) {
+ setCurrentTerminalType();
+ shouldFinish = false;
+ return;
+ }
+ boolean isMatch = isTerminalTypeSupported();
+ boolean isLast = isLast();
+ if (isMatch == true) {
+ setCurrentTerminalType();
+ return;
+ }
+ lastTerminalType = currentTerminalType;
+ currentTerminalType = new ArrayList<Integer>();
+ if (isLast == true && isMatch == false) {
+ shouldFinish = true;
+ sendRequest();
+ } else if (isLast == false && isMatch == false) {
+ sendRequest();
+ }
+ }
+ } else if (isReadingTtype == true) {
+ currentTerminalType.add(b);
+ }
+ }
+
+ private boolean isTerminalTypeSupported() {
+ byte[] tmp = new byte[currentTerminalType.size()];
+ int idx = 0;
+ for (Integer i : currentTerminalType) {
+ tmp[idx] = i.byteValue();
+ idx++;
+ }
+ String tType = new String(tmp);
+
+ for (String terminal : supportedTerminalTypes) {
+ if (tType.toUpperCase().contains(terminal)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isLast() {
+ if (currentTerminalType.equals(lastTerminalType)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void setCurrentTerminalType() {
+ byte[] tmp = new byte[currentTerminalType.size()];
+ int idx = 0;
+ for (Integer i : currentTerminalType) {
+ tmp[idx] = i.byteValue();
+ idx++;
+ }
+ String tType = new String(tmp);
+ String term = null;
+ for (String terminal : supportedTerminalTypes) {
+ if (tType.toUpperCase().contains(terminal)) {
+ term = terminal;
+ }
+ }
+ TerminalTypeMappings currentMapping = supportedEscapeSequences.get(term);
+ if (currentMapping == null) {
+ currentMapping = supportedEscapeSequences.get(DEFAULT_TTYPE);
+ }
+ currentEscapesToKey = currentMapping.getEscapesToKey();
+ escapes = currentMapping.getEscapes();
+ setBackspace(currentMapping.getBackspace());
+ setDel(currentMapping.getDel());
+ if (callback != null) {
+ callback.finished();
+ }
+ }
+
+ private void sendRequest() {
+ try {
+ toTelnet.write(tTypeRequest);
+ toTelnet.flush();
+ if (tTypeNegotiationStarted == false) {
+ tTypeNegotiationStarted = true;
+ }
+ } catch (IOException e) {
+
+ e.printStackTrace();
+ }
+ }
+
+ private void startCommand() {
+ isCommand = true;
+ isNegotiation = false;
+ isWill = false;
+ }
+
+ private void eraseChar() throws IOException {
+ toShell.add(new byte[] { BS });
+ }
+
+ protected void scanEsc(int b) throws IOException {
+ esc += (char) b;
+ toShell.add(new byte[] { (byte) b });
+ KEYS key = checkEscape(esc);
+ if (key == KEYS.UNFINISHED) {
+ return;
+ }
+ if (key == KEYS.UNKNOWN) {
+ isEsc = false;
+ scan(b);
+ return;
+ }
+ isEsc = false;
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetManager.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetManager.java
new file mode 100644
index 00000000..16c870ce
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetManager.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.TelnetConsoleSession;
+import org.eclipse.osgi.framework.console.ConsoleSession;
+import org.osgi.framework.BundleContext;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class TelnetManager {
+
+ private ConsoleSocketGetter csg;
+
+ private int telnetPort = -1;
+
+ private String host = null;
+
+ private BundleContext context = null;
+
+ private static final String PROP_CONSOLE = "osgi.console";
+
+ public TelnetManager(BundleContext bundleContext) {
+ String consoleValue = null;
+ try {
+ consoleValue = bundleContext.getProperty(PROP_CONSOLE);
+ if (consoleValue != null && !"".equals(consoleValue) && !"none".equals(consoleValue)) {
+ parseHostAndPort(consoleValue);
+ }
+ } catch (NumberFormatException e) {
+ System.out.println("Invalid host/port in " + consoleValue + "; " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ context = bundleContext;
+ }
+
+ public void startConsoleListener() {
+ if (telnetPort != -1) {
+ try {
+ if (host != null) {
+ csg = new ConsoleSocketGetter(new ServerSocket(telnetPort, 0, InetAddress.getByName(host)), context);
+ } else {
+ csg = new ConsoleSocketGetter(new ServerSocket(telnetPort), context);
+ }
+ } catch (IOException e) {
+ System.out.println("Unable to open telnet. Reason: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void stop() {
+ if (csg != null) {
+ csg.shutdown();
+ }
+ }
+
+ public BundleContext getContext() {
+ return context;
+ }
+
+ private void parseHostAndPort(String consoleValue) {
+ int index = consoleValue.lastIndexOf(":");
+ if (index > -1) {
+ host = consoleValue.substring(0, index);
+ }
+
+ telnetPort = Integer.parseInt(consoleValue.substring(index + 1));
+ }
+
+ /**
+ * ConsoleSocketGetter - provides a Thread that listens on the port for telnet connections.
+ */
+ static class ConsoleSocketGetter implements Runnable {
+
+ /**
+ * The ServerSocket to accept connections from
+ */
+ private final ServerSocket server;
+
+ private final BundleContext context;
+
+ private volatile boolean shutdown = false;
+
+ /**
+ * Constructor - sets the server and starts the thread to listen for connections.
+ *
+ * @param server a ServerSocket to accept connections from
+ * @param context Bundle context
+ */
+ ConsoleSocketGetter(ServerSocket server, BundleContext context) {
+ this.server = server;
+ this.context = context;
+ try {
+ Method reuseAddress = server.getClass().getMethod("setReuseAddress", new Class[] { boolean.class }); //$NON-NLS-1$
+ reuseAddress.invoke(server, Boolean.TRUE);
+ } catch (Exception ex) {
+ // try to set the socket re-use property, it isn't a problem if it can't be set
+ }
+ Thread t = new Thread(this, "ConsoleSocketGetter"); //$NON-NLS-1$
+ t.setDaemon(true);
+ t.start();
+ }
+
+ public void run() {
+ // Print message containing port console actually bound to..
+ System.out.println("Listening on port: " + Integer.toString(server.getLocalPort()));
+ while (!shutdown) {
+ try {
+ Socket socket = server.accept();
+ if (socket == null)
+ throw new IOException("No socket available. Probably caused by a shutdown."); //$NON-NLS-1$
+
+ TelnetConsoleSession session = new TelnetConsoleSession(socket, context);
+ session.start(); // start the Input Handler
+ context.registerService(ConsoleSession.class.getName(), session, null);
+ } catch (Exception e) {
+ if (!shutdown)
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void shutdown() {
+ if (shutdown)
+ return;
+ shutdown = true;
+ try {
+ server.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStream.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStream.java
new file mode 100644
index 00000000..9dced417
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStream.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * This class adds to the output stream wrapper initial negotiation of telnet communication.
+ */
+public class TelnetOutputStream extends ConsoleOutputStream {
+
+ static final byte[] autoMessage = new byte[] { (byte) 255, (byte) 251, (byte) 1, // IAC WILL ECHO
+ (byte) 255, (byte) 251, (byte) 3, // IAC WILL SUPPRESS GO_AHEAD
+ (byte) 255, (byte) 253, (byte) 31, // IAC DO NAWS
+ (byte) 255, (byte) 253, (byte) 24 }; // IAC DO TTYPE
+
+ public TelnetOutputStream(OutputStream out) {
+ super(out);
+ }
+
+ /**
+ * Sends the options which a server wants to negotiate with a telnet client.
+ */
+ public synchronized void autoSend() throws IOException {
+ write(autoMessage);
+ flush();
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TerminalTypeMappings.java
new file mode 100644
index 00000000..16e8fc39
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/TerminalTypeMappings.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.virgo.osgi.console.common.KEYS;
+
+public abstract class TerminalTypeMappings {
+
+ protected Map<String, KEYS> escapesToKey;
+
+ protected String[] escapes;
+
+ protected byte BACKSPACE;
+
+ protected byte DEL;
+
+ public TerminalTypeMappings() {
+ escapesToKey = new HashMap<String, KEYS>();
+ escapesToKey.put("[A", KEYS.UP); //$NON-NLS-1$
+ escapesToKey.put("[B", KEYS.DOWN); //$NON-NLS-1$
+ escapesToKey.put("[C", KEYS.RIGHT); //$NON-NLS-1$
+ escapesToKey.put("[D", KEYS.LEFT); //$NON-NLS-1$
+ escapesToKey.put("[G", KEYS.CENTER); //$NON-NLS-1$
+ setKeypadMappings();
+ createEscapes();
+ }
+
+ public Map<String, KEYS> getEscapesToKey() {
+ return escapesToKey;
+ }
+
+ public String[] getEscapes() {
+ if (escapes != null) {
+ return Arrays.copyOf(escapes, escapes.length);
+ } else {
+ return null;
+ }
+ }
+
+ public byte getBackspace() {
+ return BACKSPACE;
+ }
+
+ public byte getDel() {
+ return DEL;
+ }
+
+ public abstract void setKeypadMappings();
+
+ private void createEscapes() {
+ escapes = new String[escapesToKey.size()];
+ Object[] temp = escapesToKey.keySet().toArray();
+ for (int i = 0; i < escapes.length; i++) {
+ escapes[i] = (String) temp[i];
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT100TerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT100TerminalTypeMappings.java
new file mode 100644
index 00000000..375452ce
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT100TerminalTypeMappings.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+
+public class VT100TerminalTypeMappings extends TerminalTypeMappings {
+
+ public VT100TerminalTypeMappings() {
+ super();
+ BACKSPACE = 127;
+ DEL = -1;
+ }
+
+ @Override
+ public void setKeypadMappings() {
+ escapesToKey.put("[H", KEYS.HOME); //$NON-NLS-1$
+ escapesToKey.put("[4~", KEYS.END); //$NON-NLS-1$
+ escapesToKey.put("[5~", KEYS.PGUP); //$NON-NLS-1$
+ escapesToKey.put("[6~", KEYS.PGDN); //$NON-NLS-1$
+ escapesToKey.put("[2~", KEYS.INS); //$NON-NLS-1$
+ escapesToKey.put("[3~", KEYS.DEL); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT220TerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT220TerminalTypeMappings.java
new file mode 100644
index 00000000..12075f37
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT220TerminalTypeMappings.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.ANSITerminalTypeMappings;
+
+public class VT220TerminalTypeMappings extends ANSITerminalTypeMappings {
+
+ public VT220TerminalTypeMappings() {
+ super();
+
+ BACKSPACE = 127;
+ DEL = -1;
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT320TerminalTypeMappings.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT320TerminalTypeMappings.java
new file mode 100644
index 00000000..9a835372
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/VT320TerminalTypeMappings.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+
+public class VT320TerminalTypeMappings extends TerminalTypeMappings {
+
+ public VT320TerminalTypeMappings() {
+ super();
+ BACKSPACE = 8;
+ DEL = 127;
+ }
+
+ @Override
+ public void setKeypadMappings() {
+ escapesToKey.put("[H", KEYS.HOME);
+ escapesToKey.put("[F", KEYS.END);
+ escapesToKey.put("[5~", KEYS.PGUP); //$NON-NLS-1$
+ escapesToKey.put("[6~", KEYS.PGDN); //$NON-NLS-1$
+ escapesToKey.put("[2~", KEYS.INS); //$NON-NLS-1$
+ escapesToKey.put("[3~", KEYS.DEL); //$NON-NLS-1$
+
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHook.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHook.java
new file mode 100644
index 00000000..8c2b71ed
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHook.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet.hook;
+
+import org.eclipse.core.runtime.adaptor.EclipseStarter;
+import org.eclipse.osgi.baseadaptor.BaseAdaptor;
+import org.eclipse.osgi.baseadaptor.hooks.AdaptorHook;
+import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
+import org.eclipse.osgi.framework.log.FrameworkLog;
+import org.eclipse.virgo.osgi.console.telnet.TelnetManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.Properties;
+
+/**
+ * This adaptor hook starts the telnet implementation on the port, specified by the OSGi property osgi.console.
+ * Principally, on this port listens the Equinox shell. In order to avoid this, the value of the property (if integer)
+ * is stored, and the property is removed. In this way, when the Equinox ConsoleManager starts, it cannot retrieve any
+ * port and does not start a console on it. After that, during the start of the framework, the hook recovers the
+ * property and starts the telnet on this port.
+ * <p/>
+ * It is possible to pass not only the port, but also the host, in order to restrict the opened server socket to a
+ * particular network address on the host.
+ */
+public class TelnetHook implements AdaptorHook {
+
+ private boolean consolePortAvailable;
+
+ private String consoleValue;
+
+ private TelnetManager telnetManager = null;
+
+ public void initialize(BaseAdaptor adaptor) {
+ consoleValue = FrameworkProperties.getProperty(EclipseStarter.PROP_CONSOLE);
+ if (consoleValue == null) {
+ return;
+ }
+ if (consoleValue.contains(":")) {
+ consolePortAvailable = true;
+ FrameworkProperties.getProperties().remove(EclipseStarter.PROP_CONSOLE);
+ } else {
+ try {
+ Integer.parseInt(consoleValue);
+ consolePortAvailable = true;
+ FrameworkProperties.getProperties().remove(EclipseStarter.PROP_CONSOLE);
+ } catch (NumberFormatException ex) {
+ // do nothing
+ }
+ }
+ }
+
+ public void frameworkStart(BundleContext context) throws BundleException {
+ if (consolePortAvailable == true) {
+ FrameworkProperties.setProperty(EclipseStarter.PROP_CONSOLE, String.valueOf(consoleValue));
+ telnetManager = new TelnetManager(context);
+ telnetManager.startConsoleListener();
+ }
+ }
+
+ public void frameworkStop(BundleContext context) throws BundleException {
+ if (telnetManager != null) {
+ telnetManager.stop();
+ }
+ }
+
+ public void frameworkStopping(BundleContext context) {
+ // Do nothing - we don't care about stopping event
+ }
+
+ public void addProperties(Properties properties) {
+ // Do nothing - we don't care about addProperties event
+ }
+
+ public URLConnection mapLocationToURLConnection(String location) throws IOException {
+ return null; // not supported
+ }
+
+ public void handleRuntimeError(Throwable error) {
+ // Do nothing - we don't know how to handle runtime errors
+ }
+
+ public FrameworkLog createFrameworkLog() {
+ return null; // not supported
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookConfigurator.java b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookConfigurator.java
new file mode 100644
index 00000000..c64c78d2
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookConfigurator.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet.hook;
+
+import org.eclipse.osgi.baseadaptor.HookConfigurator;
+import org.eclipse.osgi.baseadaptor.HookRegistry;
+
+import org.eclipse.virgo.osgi.console.telnet.hook.TelnetHook;
+
+public class TelnetHookConfigurator implements HookConfigurator {
+
+ public void addHooks(HookRegistry hookRegistry) {
+ hookRegistry.addAdaptorHook(new TelnetHook());
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/main/resources/about.html b/org.eclipse.virgo.management.shell/src/main/resources/about.html
new file mode 100644
index 00000000..c258ef55
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/resources/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.virgo.management.shell/src/main/resources/hookconfigurators.properties b/org.eclipse.virgo.management.shell/src/main/resources/hookconfigurators.properties
new file mode 100644
index 00000000..afd70174
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/main/resources/hookconfigurators.properties
@@ -0,0 +1 @@
+hook.configurators=org.eclipse.virgo.osgi.console.telnet.hook.TelnetHookConfigurator \ No newline at end of file
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleInputStreamTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleInputStreamTests.java
new file mode 100644
index 00000000..7f63b14a
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleInputStreamTests.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ConsoleInputStreamTests {
+
+ private static final int DATA_LENGTH = 4;
+
+ @Test
+ public void addReadBufferTest() throws Exception {
+ ConsoleInputStream in = new ConsoleInputStream();
+ byte[] data = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd' };
+ in.add(data);
+ byte[] read = new byte[DATA_LENGTH];
+ for (int i = 0; i < DATA_LENGTH; i++) {
+ in.read(read, i, 1);
+ Assert.assertEquals("Incorrect char read; position " + i + " expected: " + data[i] + ", actual: " + read[i], read[i], data[i]);
+ }
+ }
+
+ @Test
+ public void addReadTest() throws Exception {
+ ConsoleInputStream in = new ConsoleInputStream();
+ byte[] data = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd' };
+ in.add(data);
+ for (int i = 0; i < DATA_LENGTH; i++) {
+ byte symbol = (byte) in.read();
+ Assert.assertEquals("Incorrect char read; position " + i + " expected: " + data[i] + ", actual: " + symbol, symbol, data[i]);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStreamTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStreamTests.java
new file mode 100644
index 00000000..5bbee2f8
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/ConsoleOutputStreamTests.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+
+public class ConsoleOutputStreamTests {
+
+ private static final int DATA_LENGTH = 4;
+
+ @Test
+ public void testWrite() throws Exception {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleOutputStream out = new ConsoleOutputStream(byteOut);
+ byte[] data = new byte[] { 'a', 'b', 'c', 'd' };
+ for (byte b : data) {
+ out.write(b);
+ }
+ out.flush();
+ byte[] res = byteOut.toByteArray();
+
+ Assert.assertNotNull("Bytes not written; result null", res);
+ Assert.assertFalse("Bytes not written; result empty", res.length == 0);
+
+ for (int i = 0; i < DATA_LENGTH; i++) {
+ Assert.assertEquals("Wrong char read. Position " + i + ", expected " + data[i] + ", read " + res[i], data[i], res[i]);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/HistoryHolderTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/HistoryHolderTests.java
new file mode 100644
index 00000000..16334186
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/HistoryHolderTests.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import org.junit.Assert;
+
+import org.eclipse.virgo.osgi.console.supportability.HistoryHolder;
+import org.junit.Test;
+
+public class HistoryHolderTests {
+
+ @Test
+ public void test() {
+ HistoryHolder historyHolder = new HistoryHolder();
+ byte[] line1 = new byte[] { 'a', 'b', 'c', 'd' };
+ byte[] line2 = new byte[] { 'x', 'y', 'z' };
+ byte[] line3 = new byte[] { 'k', 'l', 'm', 'n' };
+
+ historyHolder.add(line1);
+ historyHolder.add(line2);
+ historyHolder.add(line3);
+
+ byte[] first = historyHolder.first();
+ Assert.assertEquals("Wrong length of first member", line1.length, first.length);
+ Assert.assertArrayEquals("Wrong first member", line1, first);
+
+ byte[] last = historyHolder.last();
+ Assert.assertEquals("Wrong length of last member", line3.length, last.length);
+ Assert.assertArrayEquals("Wrong last member", line3, last);
+
+ byte[] prev = historyHolder.prev();
+ Assert.assertEquals("Wrong length of previous member", line2.length, prev.length);
+ Assert.assertArrayEquals("Wrong previous member", line2, prev);
+
+ byte[] next = historyHolder.next();
+ Assert.assertEquals("Wrong length of next member", line3.length, next.length);
+ Assert.assertArrayEquals("Wrong next member", line3, next);
+
+ historyHolder.first();
+ historyHolder.add(new byte[] {});
+ byte[] current = historyHolder.prev();
+ Assert.assertEquals("Wrong length of next member", line3.length, current.length);
+ Assert.assertArrayEquals("Wrong next member", line3, current);
+
+ historyHolder.first();
+ historyHolder.add(line1);
+ current = historyHolder.prev();
+ Assert.assertEquals("Wrong length of next member", line1.length, current.length);
+ Assert.assertArrayEquals("Wrong next member", line1, current);
+ Assert.assertArrayEquals("Second line should now be first", line2, historyHolder.first());
+
+ historyHolder.reset();
+ Assert.assertNull("History should be empty", historyHolder.first());
+ Assert.assertNull("History should be empty", historyHolder.last());
+ Assert.assertNull("History should be empty", historyHolder.next());
+ Assert.assertNull("History should be empty", historyHolder.prev());
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/SimpleByteBufferTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/SimpleByteBufferTests.java
new file mode 100644
index 00000000..0f1c716c
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/common/SimpleByteBufferTests.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.common;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimpleByteBufferTests {
+
+ @Test
+ public void testBuffer() throws Exception {
+ SimpleByteBuffer buffer = new SimpleByteBuffer();
+ buffer.add('a');
+ buffer.add('b');
+ buffer.add('c');
+ buffer.add('d');
+
+ Assert.assertTrue("Wrong buffer size; expected 4, actual " + buffer.getSize(), buffer.getSize() == 4);
+
+ check(buffer, new byte[] { 'a', 'b', 'c', 'd' });
+
+ byte[] data = buffer.getCurrentData();
+ byte[] expected = new byte[] { 'a', 'b', 'c', 'd' };
+
+ Assert.assertTrue("Data not as expected: expected length " + expected.length + ", actual length " + data.length,
+ data.length == expected.length);
+
+ for (int i = 0; i < data.length; i++) {
+ Assert.assertEquals("Incorrect data read. Position " + i + ", expected " + expected[i] + ", read " + data[i], expected[i], data[i]);
+ }
+
+ buffer.insert('a');
+ buffer.insert('b');
+ buffer.insert('c');
+ buffer.insert('d');
+
+ int pos = buffer.getPos();
+ buffer.goLeft();
+ int newPos = buffer.getPos();
+ Assert.assertEquals("Error while moving left; old pos: " + pos + ", new pos: ", pos - 1, newPos);
+
+ buffer.insert('e');
+ check(buffer, new byte[] { 'a', 'b', 'c', 'e', 'd' });
+
+ buffer.goLeft();
+ buffer.delete();
+ check(buffer, new byte[] { 'a', 'b', 'c', 'd' });
+
+ pos = buffer.getPos();
+ buffer.goRight();
+ newPos = buffer.getPos();
+ Assert.assertEquals("Error while moving right; old pos: " + pos + ", new pos: ", pos + 1, newPos);
+
+ buffer.backSpace();
+ check(buffer, new byte[] { 'a', 'b', 'c' });
+
+ buffer.delAll();
+ Assert.assertTrue("Bytes in buffer not correctly deleted", (buffer.getSize() == 0) && (buffer.getPos() == 0));
+
+ buffer.set(new byte[] { 'a', 'b', 'c', 'd' });
+ check(buffer, new byte[] { 'a', 'b', 'c', 'd' });
+
+ data = buffer.copyCurrentData();
+ Assert.assertArrayEquals("Buffer copy does not work properly", new byte[] { 'a', 'b', 'c', 'd' }, data);
+
+ buffer.goLeft();
+ buffer.replace('e');
+ check(buffer, new byte[] { 'a', 'b', 'c', 'e' });
+
+ buffer.resetPos();
+ Assert.assertTrue("Resetting position does not work properly", buffer.getPos() == 0);
+
+ Assert.assertEquals("Wrong current char", 'a', buffer.getCurrentChar());
+ }
+
+ private void check(SimpleByteBuffer buffer, byte[] expected) throws Exception {
+ byte[] data = buffer.copyCurrentData();
+
+ Assert.assertTrue("Data not as expected: expected length " + expected.length + ", actual length " + data.length,
+ data.length == expected.length);
+
+ for (int i = 0; i < data.length; i++) {
+ Assert.assertEquals("Incorrect data read. Position " + i + ", expected " + expected[i] + ", read " + data[i], expected[i], data[i]);
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/CommandCompleterTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/CommandCompleterTests.java
new file mode 100644
index 00000000..a320b0a9
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/CommandCompleterTests.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.junit.Test;
+import org.junit.Assert;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.support.ObjectClassFilter;
+
+public class CommandCompleterTests {
+
+ @Test
+ public void testCompleter() throws Exception {
+ StubBundleContext context = new StubBundleContext();
+ TestCommandProvider commandProvider = new TestCommandProvider();
+ context.registerService(CommandProvider.class.getName(), commandProvider, null);
+ context.addFilter(new ObjectClassFilter(CommandProvider.class.getName()));
+ CommandCompleter completer = new CommandCompleter(context);
+ String[] matches = completer.complete("test");
+ Set<String> setMatches = convertToSet(matches);
+ Assert.assertEquals("Incorrect number of matches:", 3, setMatches.size());
+ Assert.assertTrue("Matches does not contain test", setMatches.contains("test"));
+ Assert.assertTrue("Matches does not contain testMethod", setMatches.contains("testMethod"));
+ Assert.assertTrue("Matches does not contain testMethod1", setMatches.contains("testMethod1"));
+
+ matches = completer.complete("dum");
+ setMatches = convertToSet(matches);
+ Assert.assertEquals("Incorrect number of matches:", 2, setMatches.size());
+ Assert.assertTrue("Matches does not contain dummy", setMatches.contains("dummy"));
+ Assert.assertTrue("Matches does not contain dummyMethod", setMatches.contains("dummyMethod"));
+
+ matches = completer.complete("fake");
+ setMatches = convertToSet(matches);
+ Assert.assertEquals("Incorrect number of matches:", 2, setMatches.size());
+ Assert.assertTrue("Matches does not contain fake", setMatches.contains("fake"));
+ Assert.assertTrue("Matches does not contain fake1", setMatches.contains("fake1"));
+
+ matches = completer.complete("help");
+ Assert.assertEquals("Matches should be empty", 0, matches.length);
+ }
+
+ private Set<String> convertToSet(String[] matches) {
+ HashSet<String> set = new HashSet<String>();
+ for (String match : matches) {
+ set.add(match);
+ }
+
+ return set;
+ }
+
+ class TestCommandProvider implements CommandProvider {
+
+ @Override
+ public String getHelp() {
+ return null;
+ }
+
+ public void _test() {
+
+ }
+
+ public void _testMethod() {
+
+ }
+
+ public void _testMethod1() {
+
+ }
+
+ public void _dummy() {
+
+ }
+
+ public void _dummyMethod() {
+
+ }
+
+ public void _fake() {
+
+ }
+
+ public void _fake1() {
+
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandlerTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandlerTests.java
new file mode 100644
index 00000000..c1a767e6
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputHandlerTests.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+
+public class ConsoleInputHandlerTests {
+
+ private static final long WAIT_TIME = 2000;
+
+ @Test
+ public void testHandler() throws Exception {
+ PipedInputStream input = new PipedInputStream();
+ PipedOutputStream output = new PipedOutputStream(input);
+ ConsoleInputStream in = new ConsoleInputStream();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleInputHandler handler = new ConsoleInputHandler(input, in, byteOut, null);
+ byte[] expected = new byte[] { 'a', 'b', 'c', 'd', 'e', '\r', '\n' };
+ output.write(expected);
+ output.flush();
+ handler.start();
+
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ byte[] read = new byte[expected.length];
+ for (int i = 0; i < expected.length; i++) {
+ in.read(read, i, 4);
+ Assert.assertEquals("Incorrect char read. Position " + i + ", expected " + expected[i] + ", read " + read[i], expected[i], read[i]);
+ }
+
+ output.close();
+ input.close();
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScannerTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScannerTests.java
new file mode 100644
index 00000000..a9d5c7dc
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/ConsoleInputScannerTests.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+import org.eclipse.virgo.osgi.console.telnet.ANSITerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.SCOTerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT100TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT220TerminalTypeMappings;
+import org.eclipse.virgo.osgi.console.telnet.VT320TerminalTypeMappings;
+import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext;
+import org.eclipse.virgo.teststubs.osgi.support.ObjectClassFilter;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+public class ConsoleInputScannerTests {
+
+ private static int BS;
+
+ private static final int LF = 10;
+
+ private static final int CR = 13;
+
+ private static final int ESC = 27;
+
+ private static int DELL;
+
+ @Test
+ public void test() throws Exception {
+ Set<TerminalTypeMappings> supportedEscapeSequences = new HashSet<TerminalTypeMappings>();
+ supportedEscapeSequences.add(new ANSITerminalTypeMappings());
+ supportedEscapeSequences.add(new VT100TerminalTypeMappings());
+ supportedEscapeSequences.add(new VT220TerminalTypeMappings());
+ supportedEscapeSequences.add(new VT320TerminalTypeMappings());
+ supportedEscapeSequences.add(new SCOTerminalTypeMappings());
+
+ for (TerminalTypeMappings ttMappings : supportedEscapeSequences) {
+ Map<String, KEYS> escapesToKey = ttMappings.getEscapesToKey();
+ Map<KEYS, byte[]> keysToEscapes = new HashMap<KEYS, byte[]>();
+ for (Entry<String, KEYS> entry : escapesToKey.entrySet()) {
+ keysToEscapes.put(entry.getValue(), entry.getKey().getBytes());
+ }
+
+ BS = ttMappings.getBackspace();
+ DELL = ttMappings.getDel();
+
+ testScan(ttMappings, keysToEscapes);
+ }
+ }
+
+ private void testScan(TerminalTypeMappings mappings, Map<KEYS, byte[]> keysToEscapes) throws Exception {
+ ConsoleInputStream in = new ConsoleInputStream();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleOutputStream out = new ConsoleOutputStream(byteOut);
+ StubBundleContext context = new StubBundleContext();
+ TestCommandProvider commandProvider = new TestCommandProvider();
+ context.registerService(CommandProvider.class.getName(), commandProvider, null);
+ context.addFilter(new ObjectClassFilter(CommandProvider.class.getName()));
+ ConsoleInputScanner scanner = new ConsoleInputScanner(in, out, context);
+ scanner.setBackspace(mappings.getBackspace());
+ scanner.setCurrentEscapesToKey(mappings.getEscapesToKey());
+ scanner.setDel(mappings.getDel());
+ scanner.setEscapes(mappings.getEscapes());
+
+ byte[] line1 = new byte[] { 'a', 'b', 'c', 'd', 'e' };
+ byte[] line2 = new byte[] { 't', 'e', 's', 't' };
+ byte[] line3 = new byte[] { 'l', 'a', 's', 't' };
+
+ addLine(scanner, line1);
+ checkInpusStream(in, line1);
+
+ addLine(scanner, line2);
+ checkInpusStream(in, line2);
+
+ addLine(scanner, line3);
+ checkInpusStream(in, line3);
+
+ add(scanner, keysToEscapes.get(KEYS.UP));
+ add(scanner, keysToEscapes.get(KEYS.UP));
+ String res = byteOut.toString();
+ Assert.assertTrue("Error processing up arrow; expected test, actual " + res.substring(res.length() - 4), res.endsWith("test"));
+
+ add(scanner, keysToEscapes.get(KEYS.DOWN));
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing down arrow; expected last, actual " + res.substring(res.length() - 4), res.endsWith("last"));
+
+ add(scanner, keysToEscapes.get(KEYS.PGUP));
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing PageUp; expected abcde, actual " + res.substring(res.length() - 4), res.endsWith("abcde"));
+
+ add(scanner, keysToEscapes.get(KEYS.PGDN));
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing PageDown; expected last, actual " + res.substring(res.length() - 4), res.endsWith("last"));
+
+ if (BS > 0) {
+ scanner.scan(BS);
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing backspace; expected las, actual " + res.substring(res.length() - 3), res.endsWith("las"));
+ scanner.scan('t');
+ }
+
+ if (DELL > 0) {
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ scanner.scan(DELL);
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing del; expected las, actual " + res.substring(res.length() - 3), res.endsWith("las"));
+ scanner.scan('t');
+ }
+
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ add(scanner, keysToEscapes.get(KEYS.RIGHT));
+ if (DELL > 0) {
+ scanner.scan(DELL);
+ } else {
+ add(scanner, keysToEscapes.get(KEYS.DEL));
+ }
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing arrows; expected las, actual " + res.substring(res.length() - 3), res.endsWith("las"));
+ scanner.scan('t');
+
+ if (keysToEscapes.get(KEYS.DEL) != null) {
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ add(scanner, keysToEscapes.get(KEYS.DEL));
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing delete; expected las, actual " + res.substring(res.length() - 3), res.endsWith("las"));
+ scanner.scan('t');
+ }
+
+ add(scanner, keysToEscapes.get(KEYS.HOME));
+ if (DELL > 0) {
+ scanner.scan(DELL);
+ } else {
+ add(scanner, keysToEscapes.get(KEYS.DEL));
+ }
+ res = byteOut.toString();
+ res = res.substring(res.length() - 6, res.length() - 3);
+ Assert.assertTrue("Error processing Home; expected ast, actual " + res, res.equals("ast"));
+ scanner.scan('l');
+
+ add(scanner, keysToEscapes.get(KEYS.END));
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ if (DELL > 0) {
+ scanner.scan(DELL);
+ } else {
+ add(scanner, keysToEscapes.get(KEYS.DEL));
+ }
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing End; expected las, actual " + res.substring(res.length() - 3), res.endsWith("las"));
+ scanner.scan('t');
+
+ add(scanner, keysToEscapes.get(KEYS.LEFT));
+ add(scanner, keysToEscapes.get(KEYS.INS));
+ scanner.scan('a');
+ res = byteOut.toString();
+ Assert.assertTrue("Error processing Ins; expected las, actual " + res.substring(res.length() - 4), res.endsWith("lasa"));
+
+ scanner.scan(CR);
+ scanner.scan(LF);
+ scanner.scan('t');
+ scanner.scan('e');
+ scanner.scan(9);
+ res = byteOut.toString();
+ Assert.assertTrue("Expected completion suggestions are not contained in the output", res.contains("test testMethod"));
+ }
+
+ private static void addLine(ConsoleInputScanner scanner, byte[] line) throws Exception {
+ for (byte b : line) {
+ try {
+ scanner.scan(b);
+ } catch (Exception e) {
+ System.out.println("Error scanning symbol " + b);
+ throw new Exception("Error scanning symbol" + b);
+ }
+ }
+
+ try {
+ scanner.scan(CR);
+ } catch (Exception e) {
+ System.out.println("Error scanning symbol " + CR);
+ throw new Exception("Error scanning symbol " + CR);
+ }
+
+ try {
+ scanner.scan(LF);
+ } catch (Exception e) {
+ System.out.println("Error scanning symbol " + LF);
+ throw new Exception("Error scanning symbol " + LF);
+ }
+ }
+
+ private void add(ConsoleInputScanner scanner, byte[] sequence) throws Exception {
+ scanner.scan(ESC);
+ for (byte b : sequence) {
+ scanner.scan(b);
+ }
+ }
+
+ private void checkInpusStream(ConsoleInputStream in, byte[] expected) throws Exception {
+ // the actual number of bytes in the stream is two more than the bytes in the array, because of the CR and LF
+ // symbols, added after the array
+ byte[] read = new byte[expected.length + 2];
+ for (int i = 0; i < expected.length; i++) {
+ in.read(read, i, 1);
+ Assert.assertEquals("Incorrect char read. Position " + i + ", expected " + expected[i] + ", read " + read[i], expected[i], read[i]);
+ }
+ in.read(read, expected.length, 1);
+ in.read(read, expected.length + 1, 1);
+ }
+
+ class TestCommandProvider implements CommandProvider {
+
+ @Override
+ public String getHelp() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void _test() {
+
+ }
+
+ public void _testMethod() {
+
+ }
+
+ public void _dummy() {
+
+ }
+
+ public void _fake() {
+
+ }
+
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/GrepTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/GrepTests.java
new file mode 100644
index 00000000..0cbbfe30
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/supportability/GrepTests.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.supportability;
+
+import java.io.ByteArrayOutputStream;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GrepTests {
+
+ private static final int CR = 13;
+
+ private static final int LF = 10;
+
+ @Test
+ public void testGrep() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ ConsoleOutputStream consoleOut = new ConsoleOutputStream(output);
+ byte[] expression = "test".getBytes();
+ Grep grep = new Grep(expression, consoleOut);
+ grep.start();
+ byte[] line1 = new byte[] { 't', 'e', 's', 't' };
+ byte[] line2 = new byte[] { 'a', 'b', 'c', 'd' };
+ byte[] line3 = new byte[] { 't', 'e', 's', 't', 'e', 'r' };
+ byte[] line4 = new byte[] { 'k', 'l', 'm', 'n' };
+ byte[] line5 = new byte[] { 't', 'e', 's', 't', 'i', 'n', 'g' };
+ byte[] line6 = new byte[] { 'o', 's', 'g', 'i', '>' };
+
+ addLine(consoleOut, line1);
+ addLine(consoleOut, line2);
+ addLine(consoleOut, line3);
+ addLine(consoleOut, line4);
+ addLine(consoleOut, line5);
+
+ for (byte b : line6) {
+ consoleOut.write(b);
+ }
+ consoleOut.flush();
+
+ grep.join();
+
+ byte[] expectedResult = new byte[] { 't', 'e', 's', 't', CR, LF, 't', 'e', 's', 't', 'e', 'r', CR, LF, 't', 'e', 's', 't', 'i', 'n', 'g', CR,
+ LF, 'o', 's', 'g', 'i', '>', ' ' };
+ byte[] result = output.toByteArray();
+
+ Assert.assertNotNull("Bytes not written; result null", result);
+ Assert.assertFalse("Bytes not written; result empty", result.length == 0);
+ Assert.assertTrue("Bytes written to output differ in number from expected", result.length == expectedResult.length);
+
+ for (int i = 0; i < result.length; i++) {
+ Assert.assertEquals("Wrong char read. Position " + i + ", expected " + expectedResult[i] + ", read " + result[i], expectedResult[i],
+ result[i]);
+ }
+ }
+
+ private static void addLine(ConsoleOutputStream out, byte[] line) throws Exception {
+ for (byte b : line) {
+ try {
+ out.write(b);
+ } catch (Exception e) {
+ System.out.println("Error writing symbol " + b);
+ throw new Exception("Error writing symbol" + b);
+ }
+ }
+
+ try {
+ out.write(CR);
+ } catch (Exception e) {
+ System.out.println("Error writing symbol " + CR);
+ throw new Exception("Error writing symbol " + CR);
+ }
+
+ try {
+ out.write(LF);
+ } catch (Exception e) {
+ System.out.println("Error writing symbol " + LF);
+ throw new Exception("Error writing symbol " + LF);
+ }
+
+ out.flush();
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallbackTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallbackTests.java
new file mode 100644
index 00000000..c0658408
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/NegotiationFinishedCallbackTests.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class NegotiationFinishedCallbackTests {
+
+ @Test
+ public void finishTest() throws Exception {
+ ServerSocket servSocket = null;
+ Socket socketClient = null;
+ Socket socketServer = null;
+ TelnetConsoleSession consoleSession = null;
+ try {
+ servSocket = new ServerSocket(0);
+ socketClient = new Socket("localhost", servSocket.getLocalPort());
+ socketServer = servSocket.accept();
+
+ consoleSession = new TelnetConsoleSession(socketServer, null);
+ NegotiationFinishedCallback callback = new NegotiationFinishedCallback(consoleSession);
+ callback.finished();
+ Assert.assertTrue("Finished not called on console session", consoleSession.isTelnetNegotiationFinished);
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ if (consoleSession != null) {
+ consoleSession.doClose();
+ }
+
+ try {
+ if (socketServer != null) {
+ Assert.assertTrue("Server telnet socket is not closed.", socketServer.isClosed());
+ }
+ } finally {
+ if (servSocket != null) {
+ servSocket.close();
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSessionTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSessionTests.java
new file mode 100644
index 00000000..ca7ca886
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetConsoleSessionTests.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+public class TelnetConsoleSessionTests {
+
+ private static final int TEST_CONTENT = 100;
+
+ private static final int IAC = 255;
+
+ @Test
+ public void testConsoleSession() throws Exception {
+ ServerSocket servSocket = null;
+ Socket socketClient = null;
+ Socket socketServer = null;
+ TelnetConsoleSession consoleServer = null;
+ OutputStream outClient = null;
+ OutputStream outServer = null;
+
+ try {
+ servSocket = new ServerSocket(0);
+ socketClient = new Socket("localhost", servSocket.getLocalPort());
+ socketServer = servSocket.accept();
+
+ consoleServer = new TelnetConsoleSession(socketServer, null);
+ consoleServer.start(2000);
+
+ outClient = socketClient.getOutputStream();
+ outClient.write(TEST_CONTENT);
+ outClient.write('\n');
+ outClient.flush();
+
+ InputStream input = consoleServer.getInput();
+ int in = input.read();
+ Assert.assertTrue("Server received [" + in + "] instead of [" + TEST_CONTENT + "] from the telnet client.", in == TEST_CONTENT);
+
+ input = socketClient.getInputStream();
+ in = input.read();
+ // here IAC is expected, since when the output stream in TelnetConsoleSession is created, several telnet
+ // commands are written to it, each of them starting with IAC
+ Assert.assertTrue("Client receive telnet responses from the server unexpected value [" + in + "] instead of [" + IAC + "].", in == IAC);
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ if (consoleServer != null) {
+ consoleServer.doClose();
+ }
+ if (outClient != null) {
+ outClient.close();
+ }
+ if (outServer != null) {
+ outServer.close();
+ }
+
+ try {
+ if (socketServer != null) {
+ Assert.assertTrue("Server telnet socket is not closed.", socketServer.isClosed());
+ }
+ } finally {
+ if (servSocket != null) {
+ servSocket.close();
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testConsoleSessionVoidWrapper() throws Exception {
+ ServerSocket servSocket = null;
+ Socket socketClient = null;
+ Socket socketServer = null;
+ TelnetConsoleSession consoleServer = null;
+
+ try {
+ servSocket = new ServerSocket(0);
+ socketClient = new Socket("localhost", servSocket.getLocalPort());
+ socketServer = servSocket.accept();
+
+ consoleServer = new TelnetConsoleSession(socketServer, null);
+ consoleServer.start(2000);
+
+ OutputStream outClient = socketClient.getOutputStream();
+ outClient.write(TEST_CONTENT);
+ outClient.write('\n');
+ outClient.flush();
+
+ InputStream input = consoleServer.getInput();
+ int in = input.read();
+
+ Assert.assertTrue("Server received [" + in + "] instead of " + TEST_CONTENT + " from the telnet client.", in == TEST_CONTENT);
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ if (consoleServer != null) {
+ consoleServer.doClose();
+ }
+
+ try {
+ if (socketServer != null) {
+ Assert.assertTrue("Server telnet socket is not closed.", socketServer.isClosed());
+ }
+ } finally {
+ if (servSocket != null) {
+ servSocket.close();
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandlerTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandlerTests.java
new file mode 100644
index 00000000..e7be090c
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputHandlerTests.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.StringBufferInputStream;
+
+public class TelnetInputHandlerTests {
+
+ private static final long WAIT_TIME = 2000;
+
+ @Test
+ public void testHandler() throws Exception {
+ StringBufferInputStream input = new StringBufferInputStream("abcde");
+ ConsoleInputStream in = new ConsoleInputStream();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleOutputStream out = new ConsoleOutputStream(byteOut);
+ Callback callback = createMock(Callback.class);
+ TelnetInputHandler handler = new TelnetInputHandler(input, in, out, callback);
+ handler.start();
+
+ // wait for the accept thread to start execution
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException ie) {
+ // do nothing
+ }
+
+ String res = byteOut.toString();
+ Assert.assertTrue("Wrong input. Expected abcde, read " + res, res.equals("abcde"));
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScannerTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScannerTests.java
new file mode 100644
index 00000000..feda304d
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetInputScannerTests.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.eclipse.virgo.osgi.console.common.ConsoleInputStream;
+import org.eclipse.virgo.osgi.console.common.ConsoleOutputStream;
+import org.eclipse.virgo.osgi.console.common.KEYS;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TelnetInputScannerTests {
+
+ private static final int IAC = 255;
+
+ private static final int DO = 253;
+
+ private static final int TTYPE = 24;
+
+ private static final int WILL = 251;
+
+ private static final int SB = 250;
+
+ private static final int SE = 240;
+
+ private static final int SEND = 1;
+
+ private static final int IS = 0;
+
+ protected static final byte ESC = 27;
+
+ @Test
+ public void testScan() throws Exception {
+ ConsoleInputStream in = new ConsoleInputStream();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleOutputStream out = new ConsoleOutputStream(byteOut);
+ Callback callback = createMock(Callback.class);
+ TelnetInputScanner scanner = new TelnetInputScanner(in, out, callback);
+ try {
+ scanner.scan((byte) 240);
+ scanner.scan((byte) 248);
+ scanner.scan((byte) 250);
+ scanner.scan((byte) 251);
+ scanner.scan((byte) 252);
+ scanner.scan((byte) 253);
+ scanner.scan((byte) 254);
+ scanner.scan((byte) 'a');
+ scanner.scan((byte) 'b');
+ scanner.scan((byte) 'c');
+ } catch (IOException e) {
+ System.out.println("Error while scanning: " + e.getMessage());
+ e.printStackTrace();
+ throw e;
+ }
+
+ String output = byteOut.toString();
+ Assert.assertTrue("Output incorrect. Expected abc, but read " + output, output.equals("abc"));
+ }
+
+ @Test
+ public void testScanESC() throws Exception {
+ ConsoleInputStream in = new ConsoleInputStream();
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ConsoleOutputStream out = new ConsoleOutputStream(byteOut);
+ Callback callback = createMock(Callback.class);
+ TelnetInputScanner scanner = new TelnetInputScanner(in, out, callback);
+
+ try {
+ scanner.scan((byte) 'a');
+ scanner.scan((byte) ESC);
+ scanner.scan((byte) 'b');
+ } catch (IOException e) {
+ System.out.println("Error while scanning: " + e.getMessage());
+ e.printStackTrace();
+ throw e;
+ }
+
+ String output = byteOut.toString();
+ Assert.assertTrue("Output incorrect. Expected abc, but read " + output, output.equals("ab"));
+ }
+
+ @Test
+ public void testTTNegotiations() throws Exception {
+ Map<byte[], TerminalTypeMappings> ttMappings = new HashMap<byte[], TerminalTypeMappings>();
+ ttMappings.put(new byte[] { 'A', 'N', 'S', 'I' }, new ANSITerminalTypeMappings());
+ ttMappings.put(new byte[] { 'V', 'T', '1', '0', '0' }, new VT100TerminalTypeMappings());
+ ttMappings.put(new byte[] { 'V', 'T', '2', '2', '0' }, new VT220TerminalTypeMappings());
+ ttMappings.put(new byte[] { 'X', 'T', 'E', 'R', 'M' }, new VT220TerminalTypeMappings());
+ ttMappings.put(new byte[] { 'V', 'T', '3', '2', '0' }, new VT320TerminalTypeMappings());
+ ttMappings.put(new byte[] { 'S', 'C', 'O' }, new SCOTerminalTypeMappings());
+
+ for (byte[] ttype : ttMappings.keySet()) {
+ testTerminalTypeNegotiation(ttype, ttMappings.get(ttype));
+ }
+ }
+
+ private void testTerminalTypeNegotiation(byte[] terminalType, TerminalTypeMappings mappings) throws Exception {
+ PipedInputStream clientIn = new PipedInputStream();
+ PipedOutputStream serverOut = new PipedOutputStream(clientIn);
+
+ byte[] requestNegotiation = { (byte) IAC, (byte) DO, (byte) TTYPE };
+
+ TestCallback testCallback = new TestCallback();
+ TelnetOutputStream out = new TelnetOutputStream(serverOut);
+ TelnetInputScanner scanner = new TelnetInputScanner(new ConsoleInputStream(), out, testCallback);
+ out.write(requestNegotiation);
+ out.flush();
+
+ int read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", IAC, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", DO, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", TTYPE, read);
+
+ scanner.scan(IAC);
+ scanner.scan(WILL);
+ scanner.scan(TTYPE);
+
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", IAC, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SB, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", TTYPE, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SEND, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", IAC, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SE, read);
+
+ scanner.scan(IAC);
+ scanner.scan(SB);
+ scanner.scan(TTYPE);
+ scanner.scan(IS);
+ scanner.scan('A');
+ scanner.scan('B');
+ scanner.scan('C');
+ scanner.scan('D');
+ scanner.scan('E');
+ scanner.scan(IAC);
+ scanner.scan(SE);
+
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", IAC, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SB, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", TTYPE, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SEND, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", IAC, read);
+ read = clientIn.read();
+ Assert.assertEquals("Unexpected input ", SE, read);
+
+ scanner.scan(IAC);
+ scanner.scan(SB);
+ scanner.scan(TTYPE);
+ scanner.scan(IS);
+ for (byte symbol : terminalType) {
+ scanner.scan(symbol);
+ }
+ scanner.scan(IAC);
+ scanner.scan(SE);
+
+ Assert.assertEquals("Incorrect BACKSPACE: ", mappings.getBackspace(), scanner.getBackspace());
+ Assert.assertEquals("Incorrect DELL: ", mappings.getDel(), scanner.getDel());
+
+ Map<String, KEYS> currentEscapesToKey = scanner.getCurrentEscapesToKey();
+ Map<String, KEYS> expectedEscapesToKey = mappings.getEscapesToKey();
+ for (String escape : expectedEscapesToKey.keySet()) {
+ KEYS key = expectedEscapesToKey.get(escape);
+ Assert.assertEquals("Incorrect " + key.name(), key, currentEscapesToKey.get(escape));
+ }
+
+ Assert.assertTrue("Callback not called ", testCallback.getState());
+ }
+
+ class TestCallback implements Callback {
+
+ private boolean isCalled = false;
+
+ @Override
+ public void finished() {
+ isCalled = true;
+ }
+
+ public boolean getState() {
+ return isCalled;
+ }
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetManagerTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetManagerTests.java
new file mode 100644
index 00000000..4ecf3d16
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetManagerTests.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.Socket;
+
+import static org.easymock.EasyMock.*;
+
+public class TelnetManagerTests {
+
+ private static final String PROP_CONSOLE = "osgi.console";
+
+ private static final String PROP_CONSOLE_VALUE_POSITIVE = "localhost:38888";
+
+ private static final String PROP_CONSOLE_VALUE_NEGATIVE = "localhost38889";
+
+ private static final int PORT_POSITIVE_TEST = 38888;
+
+ private static final int PORT_NEGATIVE_TEST = 38889;
+
+ private static final long WAIT_TIME = 2000;
+
+ private static final int TEST_CONTENT = 100;
+
+ @Test
+ public void testTelnetManager() throws Exception {
+
+ BundleContext bundleContext = createMock(BundleContext.class);
+
+ expect(bundleContext.getProperty(PROP_CONSOLE)).andReturn(PROP_CONSOLE_VALUE_POSITIVE);
+
+ replay(bundleContext);
+
+ TelnetManager telnetMngr = new TelnetManager(bundleContext);
+ telnetMngr.startConsoleListener();
+ Socket socketClient = null;
+
+ try {
+ socketClient = new Socket("localhost", PORT_POSITIVE_TEST);
+ OutputStream outClient = socketClient.getOutputStream();
+ outClient.write(TEST_CONTENT);
+ outClient.write('\n');
+ outClient.flush();
+
+ // wait for the accept thread to finish execution
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException ie) {
+ // do nothing
+ }
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ telnetMngr.stop();
+ }
+
+ verify(bundleContext);
+ }
+
+ @Test
+ public void testTelnetManagerNegative() throws Exception {
+ BundleContext bundleContext = createMock(BundleContext.class);
+
+ expect(bundleContext.getProperty(PROP_CONSOLE)).andReturn(PROP_CONSOLE_VALUE_NEGATIVE);
+
+ replay(bundleContext);
+
+ TelnetManager telnetMngr = new TelnetManager(bundleContext);
+ telnetMngr.startConsoleListener();
+
+ boolean serverSocketNotCreated = false;
+ try {
+ Socket socketClient = new Socket("localhost", PORT_NEGATIVE_TEST);
+ socketClient.close();
+ } catch (ConnectException ec) {
+ serverSocketNotCreated = true;
+ }
+
+ telnetMngr.stop();
+ verify(bundleContext);
+
+ Assert.assertTrue("Telnet console socket getter is created on localhost", serverSocketNotCreated);
+ }
+
+ @Test
+ public void testTelnetManagerWithoutHost() throws Exception {
+ BundleContext bundleContext = createMock(BundleContext.class);
+
+ expect(bundleContext.getProperty(PROP_CONSOLE)).andReturn(String.valueOf(PORT_POSITIVE_TEST));
+
+ replay(bundleContext);
+
+ TelnetManager telnetMngr = new TelnetManager(bundleContext);
+ telnetMngr.startConsoleListener();
+ Socket socketClient = null;
+
+ try {
+ socketClient = new Socket("localhost", PORT_POSITIVE_TEST);
+ OutputStream outClient = socketClient.getOutputStream();
+ outClient.write(TEST_CONTENT);
+ outClient.write('\n');
+ outClient.flush();
+
+ // wait for the accept thread to finish execution
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException ie) {
+ // do nothing
+ }
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ telnetMngr.stop();
+ }
+
+ verify(bundleContext);
+ }
+
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStreamTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStreamTests.java
new file mode 100644
index 00000000..7753e4ab
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/TelnetOutputStreamTests.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+
+public class TelnetOutputStreamTests {
+
+ @Test
+ public void testAutoSend() throws Exception {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ TelnetOutputStream out = new TelnetOutputStream(byteOut);
+ out.autoSend();
+ out.flush();
+ byte[] message = byteOut.toByteArray();
+
+ Assert.assertNotNull("Auto message not sent", message);
+ Assert.assertFalse("Auto message not sent", message.length == 0);
+ Assert.assertTrue("Error sending auto message. Expected length: " + TelnetOutputStream.autoMessage.length + ", actual length: "
+ + message.length, message.length == TelnetOutputStream.autoMessage.length);
+
+ for (int i = 0; i < message.length; i++) {
+ Assert.assertEquals("Wrong char in auto message. Position: " + i + ", expected: " + TelnetOutputStream.autoMessage[i] + ", read: "
+ + message[i], TelnetOutputStream.autoMessage[i], message[i]);
+ }
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookTests.java b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookTests.java
new file mode 100644
index 00000000..5d53d2fe
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/src/test/java/org/eclipse/virgo/management/shell/telnet/hook/TelnetHookTests.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG
+ * 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:
+ * Lazar Kirchev, SAP AG - initial contribution
+ ******************************************************************************/
+
+package org.eclipse.virgo.osgi.console.telnet.hook;
+
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.Socket;
+
+import org.eclipse.core.runtime.adaptor.EclipseStarter;
+import org.eclipse.osgi.baseadaptor.BaseAdaptor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+import static org.easymock.EasyMock.*;
+
+public class TelnetHookTests {
+
+ @Test
+ public void testHostAndPort() throws Exception {
+ System.setProperty(EclipseStarter.PROP_CONSOLE, "localhost:3333");
+ System.setProperty("osgi.configuration.area", ".");
+ BaseAdaptor adaptor = new BaseAdaptor(null);
+ TelnetHook telnetHook = new TelnetHook();
+ telnetHook.initialize(adaptor);
+ String consoleProp = System.getProperty(EclipseStarter.PROP_CONSOLE);
+ Assert.assertNull("Console port should not be present in the properties", consoleProp);
+
+ BundleContext bundleContext = createMock(BundleContext.class);
+
+ expect(bundleContext.getProperty(EclipseStarter.PROP_CONSOLE)).andReturn("localhost:3333");
+ replay(bundleContext);
+
+ telnetHook.frameworkStart(bundleContext);
+
+ consoleProp = System.getProperty(EclipseStarter.PROP_CONSOLE);
+ Assert.assertEquals("Console port should not be present in the properties", "localhost:3333", consoleProp);
+
+ telnetHook.frameworkStop(bundleContext);
+
+ telnetHook.frameworkStopping(bundleContext);
+ telnetHook.addProperties(null);
+ telnetHook.mapLocationToURLConnection(null);
+ telnetHook.handleRuntimeError(null);
+ Assert.assertNull(telnetHook.createFrameworkLog());
+
+ Socket socketClient = null;
+ try {
+ socketClient = new Socket("localhost", 3333);
+ OutputStream outClient = socketClient.getOutputStream();
+ outClient.write(100);
+ outClient.write('\n');
+ outClient.flush();
+ Assert.fail("Server socket should be closed, no connection should be established");
+ } catch (ConnectException ex) {
+ // this is expected
+ } finally {
+ if (socketClient != null) {
+ socketClient.close();
+ }
+ }
+
+ verify(bundleContext);
+ }
+
+ @Test
+ public void testPort() {
+ BaseAdaptor adaptor = new BaseAdaptor(null);
+ TelnetHook telnetHook = new TelnetHook();
+ System.setProperty(EclipseStarter.PROP_CONSOLE, "3333");
+ telnetHook.initialize(adaptor);
+ String consoleProp = System.getProperty(EclipseStarter.PROP_CONSOLE);
+ Assert.assertNull("Console port should not be present in the properties", consoleProp);
+ }
+}
diff --git a/org.eclipse.virgo.management.shell/template.mf b/org.eclipse.virgo.management.shell/template.mf
new file mode 100644
index 00000000..4be29bb0
--- /dev/null
+++ b/org.eclipse.virgo.management.shell/template.mf
@@ -0,0 +1,18 @@
+Bundle-ManifestVersion: 2
+Bundle-Name: Console
+Bundle-SymbolicName: org.eclipse.virgo.osgi.console
+Bundle-Version: ${version}
+Fragment-Host: org.eclipse.osgi; extension:=framework
+Excluded-Exports:
+ *.internal.*,
+ org.eclipse.core.*,
+ org.eclipse.osgi.*,
+ org.osgi.framework.*,
+ org.osgi.service.*
+Excluded-Imports:
+ org.eclipse.core.*;version="0",
+ org.eclipse.osgi.*;version="0",
+ org.osgi.framework.*;version="0",
+ org.osgi.service.*;version="0",
+ org.osgi.util.*;version="0"
+

Back to the top