You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ch...@apache.org on 2013/07/22 08:58:04 UTC

svn commit: r1505607 [1/3] - in /felix/trunk/webconsole-plugins/script-console: ./ src/ src/main/ src/main/appended-resources/ src/main/appended-resources/META-INF/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/fe...

Author: chetanm
Date: Mon Jul 22 06:58:03 2013
New Revision: 1505607

URL: http://svn.apache.org/r1505607
Log:
FELIX-4122 - Import new Script Console Plugin

Added:
    felix/trunk/webconsole-plugins/script-console/
    felix/trunk/webconsole-plugins/script-console/pom.xml
    felix/trunk/webconsole-plugins/script-console/src/
    felix/trunk/webconsole-plugins/script-console/src/main/
    felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/
    felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/
    felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES   (with props)
    felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/LICENSE
    felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/NOTICE
    felix/trunk/webconsole-plugins/script-console/src/main/java/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Activator.java
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/LogWriter.java
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Logger.java
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptConsolePlugin.java
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptEngineManager.java
    felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptHelper.java
    felix/trunk/webconsole-plugins/script-console/src/main/resources/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/bundle.properties
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/loadmode.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/runmode.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.css
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/groovy.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/javascript.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.css
    felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.js
    felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/
    felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/script-console.html
    felix/trunk/webconsole-plugins/script-console/src/test/
    felix/trunk/webconsole-plugins/script-console/src/test/java/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ITScriptConsolePlugin.java
    felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ServerConfiguration.java
    felix/trunk/webconsole-plugins/script-console/src/test/resources/
    felix/trunk/webconsole-plugins/script-console/src/test/resources/test.groovy

Added: felix/trunk/webconsole-plugins/script-console/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/pom.xml?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/pom.xml (added)
+++ felix/trunk/webconsole-plugins/script-console/pom.xml Mon Jul 22 06:58:03 2013
@@ -0,0 +1,425 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+    http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.felix</groupId>
+    <artifactId>felix-parent</artifactId>
+    <version>2.1</version>
+    <relativePath>../pom/pom.xml</relativePath>
+  </parent>
+
+  <artifactId>org.apache.felix.webconsole.plugins.scriptconsole</artifactId>
+  <packaging>bundle</packaging>
+  <version>0.0.1-SNAPSHOT</version>
+
+  <name>Apache Felix Script Console Plugin</name>
+  <description>Apache Felix Script Console Plugin allows invocation of script through Felix Web Console UI
+  </description>
+
+  <properties>
+    <pax-exam.version>3.0.0</pax-exam.version>
+    <bundle.build.name>
+      ${basedir}/target
+    </bundle.build.name>
+    <bundle.file.name>
+      ${bundle.build.name}/${project.build.finalName}.jar
+    </bundle.file.name>
+  </properties>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/felix/trunk/webconsole-plugins/script-console</connection>
+    <developerConnection>
+        scm:svn:https://svn.apache.org/repos/asf/felix/trunk/webconsole-plugins/script-console
+    </developerConnection>
+    <url>http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console</url>
+  </scm>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.7</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Category>osgi</Bundle-Category>
+            <Bundle-SymbolicName>
+              ${project.artifactId}
+            </Bundle-SymbolicName>
+            <Import-Package>
+                  org.json.*;version=0,
+                  javax.servlet.*;version=2.3,
+                  org.apache.commons.io; version="[1.4,3)",
+                  *
+            </Import-Package>
+            <Bundle-Activator>
+              org.apache.felix.webconsole.plugins.scriptconsole.internal.Activator
+            </Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <configuration>
+          <includes>
+            <include>src/**</include>
+          </includes>
+          <excludes>
+            <exclude>src/main/appended-resources/**</exclude>
+            <exclude>src/main/resources/res/ui/codemirror/**</exclude>
+            <exclude>src/main/resources/res/ui/*.*</exclude>
+            <exclude>src/main/resources/templates/*.*</exclude>
+            <exclude>src/test/resources/*.*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+      <!-- Required for pax exam-->
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.8</version>
+        <executions>
+          <execution>
+            <id>reserve-network-port</id>
+            <goals>
+              <goal>reserve-network-port</goal>
+            </goals>
+            <phase>pre-integration-test</phase>
+            <configuration>
+              <portNames>
+                <portName>http.port</portName>
+              </portNames>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>properties-maven-plugin</artifactId>
+        <version>1.0-alpha-2</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>set-system-properties</goal>
+            </goals>
+            <phase>pre-integration-test</phase>
+            <configuration>
+              <properties>
+                <property>
+                  <name>project.bundle.file</name>
+                  <value>${bundle.file.name}</value>
+                </property>
+                <property>
+                  <name>http.port</name>
+                  <value>${http.port}</value>
+                </property>
+              </properties>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.ops4j.pax.exam</groupId>
+        <artifactId>exam-maven-plugin</artifactId>
+        <version>3.0.3</version>
+        <configuration>
+          <configClass>org.apache.felix.webconsole.plugins.scriptconsole.integration.ServerConfiguration</configClass>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>start-container</goal>
+              <goal>stop-container</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.servicemix.tooling</groupId>
+        <artifactId>depends-maven-plugin</artifactId>
+        <version>1.2</version>
+        <executions>
+          <execution>
+            <id>generate-depends-file</id>
+            <goals>
+              <goal>generate-depends-file</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <!-- integration tests run with pax-exam -->
+      <plugin>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <version>2.12</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>integration-test</goal>
+              <goal>verify</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <systemPropertyVariables>
+            <coverage.command>${coverage.command}</coverage.command>
+            <http.port>${http.port}</http.port>
+          </systemPropertyVariables>
+          <forkMode>always</forkMode>
+          <parallel>none</parallel>
+          <threadCount>1</threadCount>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <version>4.2.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <version>4.2.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.webconsole</artifactId>
+      <version>3.1.8</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.json</groupId>
+      <artifactId>json</artifactId>
+      <version>20070829</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-fileupload</groupId>
+      <artifactId>commons-fileupload</artifactId>
+      <version>1.2.1</version>
+      <scope>provided</scope>
+    </dependency>
+
+
+    <!-- testing -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+      <version>4.10</version>
+    </dependency>
+    <!-- Pax Exam Dependencies -->
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-container-forked</artifactId>
+      <version>${pax-exam.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-junit4</artifactId>
+      <version>${pax-exam.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.ops4j.pax.exam</groupId>
+      <artifactId>pax-exam-link-mvn</artifactId>
+      <version>${pax-exam.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.ops4j.pax.url</groupId>
+      <artifactId>pax-url-wrap</artifactId>
+      <version>1.5.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+      <version>1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>1.6.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.configadmin</artifactId>
+      <version>1.6.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.http.jetty</artifactId>
+      <version>2.2.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.testing.tools</artifactId>
+      <version>1.0.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+
+  <profiles>
+    <!--
+        copy the package such that IDEs may easily use it without
+        setting the system property
+    -->
+    <profile>
+      <id>ide</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>scr-file-create</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>run</goal>
+                </goals>
+                <configuration>
+                  <target>
+                    <copy file="${project.build.directory}/${project.build.finalName}.jar"
+                          tofile="${project.build.directory}/scriptconsole.jar" />
+                  </target>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>coverage</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <version>0.6.2.201302030002</version>
+            <executions>
+              <execution>
+                <id>prepare-agent</id>
+                <goals>
+                  <goal>prepare-agent</goal>
+                </goals>
+                <configuration>
+                  <propertyName>coverage.command</propertyName>
+                  <includes>
+                    <include>org.apache.felix.jaas.*</include>
+                  </includes>
+                  <excludes>
+                    <exclude>org.apache.felix.jaas.integration.*</exclude>
+                  </excludes>
+                </configuration>
+              </execution>
+              <execution>
+                <id>report</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>report</goal>
+                </goals>
+              </execution>
+              <execution>
+                <id>check</id>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+                <configuration>
+                  <check>
+                    <classRatio>100</classRatio>
+                    <instructionRatio>90</instructionRatio>
+                    <methodRatio>95</methodRatio>
+                    <branchRatio>85</branchRatio>
+                    <complexityRatio>85</complexityRatio>
+                    <lineRatio>90</lineRatio>
+                  </check>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>felix</id>
+      <activation>
+        <activeByDefault>true</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.felix</groupId>
+          <artifactId>org.apache.felix.framework</artifactId>
+          <version>4.0.2</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>equinox</id>
+      <dependencies>
+        <dependency>
+          <groupId>org.eclipse</groupId>
+          <artifactId>org.eclipse.osgi</artifactId>
+          <version>3.8.0.v20120529-1548</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+</project>

Added: felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES Mon Jul 22 06:58:03 2013
@@ -0,0 +1,20 @@
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://codemirror.net/
+Copyright (C) 2013 by Marijn Haverbeke <ma...@gmail.com>
+Licensed under the MIT License
+
+II. Used Software
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2012).
+Licensed under the Apache License 2.0.
+
+III. License Summary
+- Apache License 2.0
+- MIT License

Propchange: felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/DEPENDENCIES
------------------------------------------------------------------------------
    svn:executable = *

Added: felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/LICENSE
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/LICENSE?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/LICENSE (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/LICENSE Mon Jul 22 06:58:03 2013
@@ -0,0 +1,34 @@
+
+
+APACHE FELIX SCRIPT CONSOLE SUBCOMPONENTS:
+
+The Apache Felix Script Console Plugin includes a number of subcomponents
+with separate copyright notices and license terms. Your use of the source
+code for the these subcomponents is subject to the terms and conditions
+of the following licenses. 
+
+For the CodeMirror library
+
+Copyright (C) 2013 by Marijn Haverbeke <ma...@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Please note that some subdirectories of the CodeMirror distribution
+include their own LICENSE files, and are released under different
+licences.

Added: felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/NOTICE
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/NOTICE?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/NOTICE (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/appended-resources/META-INF/NOTICE Mon Jul 22 06:58:03 2013
@@ -0,0 +1,6 @@
+This product includes software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2012).
+Licensed under the Apache License 2.0. 
+
+

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Activator.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Activator.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Activator.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator
+{
+    private Logger logger;
+    private ScriptConsolePlugin consolePlugin;
+    private ScriptEngineManager scriptEngineManager;
+
+    public void start(BundleContext context) throws Exception
+    {
+        logger = new Logger(context);
+        scriptEngineManager = new ScriptEngineManager(context, logger);
+        consolePlugin = new ScriptConsolePlugin(context, logger, scriptEngineManager);
+    }
+
+    public void stop(BundleContext context) throws Exception
+    {
+
+        if (consolePlugin != null)
+        {
+            consolePlugin.dispose();
+        }
+
+        if (scriptEngineManager != null)
+        {
+            scriptEngineManager.dispose();
+        }
+
+        if (logger != null)
+        {
+            logger.close();
+        }
+    }
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/LogWriter.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/LogWriter.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/LogWriter.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/LogWriter.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.osgi.service.log.LogService;
+
+import java.io.Writer;
+
+/**
+ * The <code>LogWriter</code> is a simple <code>Writer</code> which writes
+ * lines of data to a given Logger. Data is gathered in an internal buffer
+ * until the {@link #flush()} method is called or until a CR or LF character is
+ * encountered in the data to be written.
+ */
+class LogWriter extends Writer
+{
+
+    /** The logger to which the error messages are written */
+    private Logger logger;
+
+    /**
+     * The internal buffer to gather message data until being flushed or a CR or
+     * LF is encountered in the message data.
+     */
+    private final StringBuilder lineBuffer = new StringBuilder();
+
+    /**
+     * Creates a writer based on the given logger.
+     */
+    public LogWriter(Logger logger)
+    {
+        this.logger = logger;
+    }
+
+    /**
+     * Writes the character to the internal buffer unless the character is a CR
+     * or LF in which case the buffer is written to the logger as an error
+     * message.
+     */
+    @Override
+    public void write(int c)
+    {
+        if (c == '\n' || c == '\r')
+        {
+            flush();
+        }
+        else
+        {
+            synchronized (lineBuffer)
+            {
+                lineBuffer.append((char) c);
+            }
+        }
+    }
+
+    /**
+     * Writes the indicated characters to the internal buffer, flushing the
+     * buffer on any occurrence of a CR of LF.
+     */
+    @Override
+    public void write(char[] cbuf, int off, int len)
+    {
+        int i = off;
+        for (int n = 0; n < len; n++, i++)
+        {
+            char c = cbuf[i];
+
+            // if CR/LF flush the line
+            if (c == '\n' || c == '\r')
+            {
+
+                // append upto the CR/LF
+                int subLen = i - off;
+                if (subLen > 0)
+                {
+                    synchronized (lineBuffer)
+                    {
+                        lineBuffer.append(cbuf, off, subLen);
+                    }
+                }
+
+                // and flush
+                flush();
+
+                // new offset is after the CR/LF
+                off = i + 1;
+            }
+        }
+
+        // remaining data in the buffer is just appended
+        if (off < i)
+        {
+            synchronized (lineBuffer)
+            {
+                lineBuffer.append(cbuf, off, i - off);
+            }
+        }
+    }
+
+    /**
+     * Writes any data conained in the buffer to the logger as an error message.
+     */
+    @Override
+    public void flush()
+    {
+
+        String message;
+        synchronized (lineBuffer)
+        {
+            if (lineBuffer.length() == 0)
+            {
+                return;
+            }
+            message = lineBuffer.toString();
+            lineBuffer.setLength(0);
+        }
+
+        logger.log(LogService.LOG_ERROR,message);
+    }
+
+    /**
+     * Just calls {@link #flush()}
+     */
+    @Override
+    public void close()
+    {
+        flush();
+    }
+
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Logger.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Logger.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Logger.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/Logger.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+class Logger extends ServiceTracker
+{
+
+    public Logger(BundleContext context)
+    {
+        super(context, LogService.class.getName(), null);
+        super.open();
+    }
+
+    public void log(int level, String message)
+    {
+        LogService log = getLog();
+        if (log != null)
+        {
+            log.log(level, message);
+        }
+
+    }
+
+    public void log(int level, String message, Throwable exception)
+    {
+        LogService log = getLog();
+        if (log != null)
+        {
+            log.log(level, message, exception);
+        }
+    }
+
+    private LogService getLog()
+    {
+        return (LogService) getService();
+    }
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptConsolePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptConsolePlugin.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptConsolePlugin.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptConsolePlugin.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.io.IOUtils;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.DefaultVariableResolver;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleUtil;
+import org.json.JSONException;
+import org.json.JSONWriter;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
+
+import javax.script.*;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+class ScriptConsolePlugin extends SimpleWebConsolePlugin
+{
+
+    public static final String NAME = "sc";
+    private static final String TITLE = "%script.title";
+    private static final String[] CSS = { "/res/ui/codemirror/lib/codemirror.css",
+            "/res/ui/script-console.css" };
+    private final String TEMPLATE;
+    private final Logger log;
+    private final ScriptEngineManager scriptEngineManager;
+    private final ServiceRegistration registration;
+
+    public ScriptConsolePlugin(BundleContext bundleContext, Logger logger, ScriptEngineManager scriptEngineManager)
+    {
+        super(NAME, TITLE, processFileNames(CSS));
+        this.log = logger;
+        this.scriptEngineManager = scriptEngineManager;
+        TEMPLATE = readTemplateFile("/templates/script-console.html");
+        super.activate(bundleContext);
+
+        Properties props = new Properties();
+        props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
+        props.put(Constants.SERVICE_DESCRIPTION, "Script Console Web Console Plugin");
+        props.put("felix.webconsole.label", ScriptConsolePlugin.NAME);
+        props.put("felix.webconsole.title", "Script Console");
+
+        registration = getBundleContext().registerService(Servlet.class.getName(), this,
+            props);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void renderContent(HttpServletRequest request, HttpServletResponse response)
+        throws ServletException, IOException
+    {
+        final PrintWriter pw = response.getWriter();
+        DefaultVariableResolver varResolver = (DefaultVariableResolver) WebConsoleUtil.getVariableResolver(request);
+        varResolver.put("__scriptConfig__", getScriptConfig());
+        pw.println(TEMPLATE);
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException
+    {
+        final String contentType = getContentType(req);
+        resp.setContentType(contentType);
+        if (contentType.startsWith("text/"))
+        {
+            resp.setCharacterEncoding("UTF-8");
+        }
+        final String script = getCodeValue(req);
+        final Bindings bindings = new SimpleBindings();
+        final PrintWriter pw = resp.getWriter();
+        final ScriptHelper osgi = new ScriptHelper(getBundleContext());
+        final Writer errorWriter = new LogWriter(log);
+        final Reader reader = new StringReader(script)
+                ;
+        //Populate bindings
+        bindings.put("request", req);
+        bindings.put("reader", reader);
+        bindings.put("response", resp);
+        bindings.put("out", pw);
+        bindings.put("osgi", osgi);
+
+        //Also expose the bundleContext to simplify scripts interaction with the
+        //enclosing OSGi container
+        bindings.put("bundleContext", getBundleContext());
+
+        final String lang = WebConsoleUtil.getParameter(req, "lang");
+        final boolean webClient = "webconsole".equals(WebConsoleUtil.getParameter(req,
+            "client"));
+
+
+        SimpleScriptContext sc = new SimpleScriptContext();
+        sc.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
+        sc.setWriter(pw);
+        sc.setErrorWriter(errorWriter);
+        sc.setReader(reader);
+
+        try
+        {
+            log.log(LogService.LOG_DEBUG, "Executing script" + script);
+           eval(script, lang, sc);
+        }
+        catch (Throwable t)
+        {
+            if (!webClient)
+            {
+                resp.setStatus(500);
+            }
+            pw.println(exceptionToString(t));
+            log.log(LogService.LOG_ERROR, "Error in executing script", t);
+        }
+        finally
+        {
+            osgi.cleanup();
+        }
+    }
+
+
+    private void eval(String script, String lang,ScriptContext ctx) throws ScriptException, IOException {
+        ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension(lang);
+        if(scriptEngine == null)
+        {
+            throw new IllegalArgumentException("No ScriptEngineFactory found for extension "+ lang);
+        }
+
+        // evaluate the script
+        //Currently we do not make use of returned object
+        final Object ignored = scriptEngine.eval(script, ctx);
+
+        // allways flush the error channel
+        ctx.getErrorWriter().flush();
+
+    }
+
+    private String getCodeValue(HttpServletRequest req) throws IOException
+    {
+        String script = WebConsoleUtil.getParameter(req, "code");
+        if (script == null)
+        {
+            script = getContentFromFilePart(req, "code");
+        }
+        if (script == null)
+        {
+            throw new IllegalArgumentException("'code' parameter not passed");
+        }
+        return script;
+    }
+
+    private String getContentType(HttpServletRequest req)
+    {
+        String passedContentType = WebConsoleUtil.getParameter(req, "responseContentType");
+        if (passedContentType != null)
+        {
+            return passedContentType;
+        }
+        return req.getPathInfo().endsWith(".json") ? "application/json" : "text/plain";
+    }
+
+    private String exceptionToString(Throwable t)
+    {
+        StringWriter sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw));
+        return sw.toString();
+    }
+
+    private static String[] processFileNames(String[] cssFiles)
+    {
+        String[] css = new String[cssFiles.length];
+        for (int i = 0; i < cssFiles.length; i++)
+        {
+            css[i] = '/' + NAME + CSS[i];
+        }
+        return css;
+    }
+
+    private String getScriptConfig()
+    {
+        try
+        {
+            return getScriptConfig0();
+        }
+        catch (JSONException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String getScriptConfig0() throws JSONException
+    {
+        StringWriter sw = new StringWriter();
+        JSONWriter jw = new JSONWriter(sw);
+        jw.array();
+
+        for (ScriptEngineFactory sef : scriptEngineManager.getEngineFactories())
+        {
+            jw.object();
+            if (sef.getExtensions().isEmpty())
+            {
+                continue;
+            }
+            jw.key("langName").value(sef.getLanguageName());
+            jw.key("langCode").value(sef.getExtensions().get(0));
+
+            //Language mode as per CodeMirror names
+            String mode = determineMode(sef.getExtensions());
+            if (mode != null)
+            {
+                jw.key("mode").value(mode);
+            }
+
+            jw.endObject();
+        }
+
+        jw.endArray();
+        return sw.toString();
+    }
+
+    private String determineMode(List<String> extensions)
+    {
+        if (extensions.contains("groovy"))
+        {
+            return "groovy";
+        }
+        else if (extensions.contains("esp"))
+        {
+            return "javascript";
+        }
+        return null;
+    }
+
+    private String getContentFromFilePart(HttpServletRequest req, String paramName)
+        throws IOException
+    {
+        String value = WebConsoleUtil.getParameter(req, paramName);
+        if (value != null)
+        {
+            return value;
+        }
+        final Map params = (Map) req.getAttribute(AbstractWebConsolePlugin.ATTR_FILEUPLOAD);
+        if (params == null)
+        {
+            return null;
+        }
+        FileItem[] codeFile = getFileItems(params, paramName);
+        if (codeFile.length == 0)
+        {
+            return null;
+        }
+        InputStream is = null;
+        try
+        {
+            is = codeFile[0].getInputStream();
+            StringWriter sw = new StringWriter();
+            IOUtils.copy(is, sw, "utf-8");
+            return sw.toString();
+        }
+        finally
+        {
+            IOUtils.closeQuietly(is);
+        }
+    }
+
+    private FileItem[] getFileItems(Map params, String name)
+    {
+        final List<FileItem> files = new ArrayList<FileItem>();
+        FileItem[] items = (FileItem[]) params.get(name);
+        if (items != null)
+        {
+            for (int i = 0; i < items.length; i++)
+            {
+                if (!items[i].isFormField() && items[i].getSize() > 0)
+                {
+                    files.add(items[i]);
+                }
+            }
+        }
+        return files.toArray(new FileItem[files.size()]);
+    }
+
+    public void dispose()
+    {
+        super.deactivate();
+        if (registration != null)
+        {
+            registration.unregister();
+        }
+    }
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptEngineManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptEngineManager.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptEngineManager.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptEngineManager.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.apache.commons.io.IOUtils;
+import org.osgi.framework.*;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * It is based on org.apache.sling.scripting.core.impl.ScriptEngineManagerFactory
+ */
+class ScriptEngineManager implements BundleListener, ServiceTrackerCustomizer
+{
+    private static final String ENGINE_FACTORY_SERVICE = "META-INF/services/"
+        + ScriptEngineFactory.class.getName();
+    private final Set<Bundle> engineSpiBundles = new HashSet<Bundle>();
+    private final Map<ServiceReference, ScriptEngineFactoryState> engineSpiServices
+            = new ConcurrentHashMap<ServiceReference, ScriptEngineFactoryState>();
+
+    private final Logger log;
+    private EngineManagerState state = new EngineManagerState();
+
+    /**
+     * ServiceTracker for ScriptEngineFactory
+     */
+    private ServiceTracker scriptFactoryTracker;
+    private final BundleContext context;
+
+    public ScriptEngineManager(BundleContext context, Logger logger)
+    {
+        this.log = logger;
+        this.context = context;
+
+        this.context.addBundleListener(this);
+
+        Bundle[] bundles = this.context.getBundles();
+        synchronized (this.engineSpiBundles) {
+            for (Bundle bundle : bundles) {
+                if (bundle.getState() == Bundle.ACTIVE
+                        && bundle.getEntry(ENGINE_FACTORY_SERVICE) != null) {
+                    this.engineSpiBundles.add(bundle);
+                }
+            }
+        }
+
+        // create a script engine manager
+        this.refreshScriptEngineManager();
+
+        this.scriptFactoryTracker = new ServiceTracker(context,
+            ScriptEngineFactory.class.getName(), this);
+        this.scriptFactoryTracker.open();
+    }
+
+    public List<ScriptEngineFactory> getEngineFactories()
+    {
+        return state.factories;
+    }
+
+    public ScriptEngine getEngineByExtension(String extension) {
+        ScriptEngineFactory factory = state.extensionAssociations.get(extension);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        //We do not support global scope for now
+        //engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    // ---------- BundleListener interface -------------------------------------
+
+    public void bundleChanged(BundleEvent event)
+    {
+        if (event.getType() == BundleEvent.STARTED
+            && event.getBundle().getEntry(ENGINE_FACTORY_SERVICE) != null)
+        {
+            synchronized (this.engineSpiBundles)
+            {
+                this.engineSpiBundles.add(event.getBundle());
+            }
+            this.refreshScriptEngineManager();
+        }
+        else if (event.getType() == BundleEvent.STOPPED)
+        {
+            boolean refresh;
+            synchronized (this.engineSpiBundles)
+            {
+                refresh = this.engineSpiBundles.remove(event.getBundle());
+            }
+            if (refresh)
+            {
+                this.refreshScriptEngineManager();
+            }
+        }
+    }
+
+    // ---------- ServiceTrackerCustomizer interface -------------------------------------
+
+    public Object addingService(ServiceReference reference) {
+        ScriptEngineFactory service = (ScriptEngineFactory) context.getService(reference);
+        engineSpiServices.put(reference,new ScriptEngineFactoryState(service,getServiceProperties(reference)));
+        refreshScriptEngineManager();
+        return service;
+    }
+
+    public void modifiedService(ServiceReference reference, Object service)
+    {
+        ScriptEngineFactoryState state = engineSpiServices.get(reference);
+        state.properties = getServiceProperties(reference);
+        refreshScriptEngineManager();
+    }
+
+    public void removedService(ServiceReference reference, Object service)
+    {
+        context.ungetService(reference);
+        engineSpiServices.remove(reference);
+        refreshScriptEngineManager();
+
+    }
+
+    private void refreshScriptEngineManager()
+    {
+        EngineManagerState tmp = new EngineManagerState();
+        // register script engines from bundles
+        final SortedSet<Object> extensions = new TreeSet<Object>();
+        synchronized (this.engineSpiBundles)
+        {
+            for (final Bundle bundle : this.engineSpiBundles)
+            {
+                extensions.addAll(registerFactories(tmp, bundle));
+            }
+        }
+
+        // register script engines from registered services
+        synchronized (this.engineSpiServices)
+        {
+            for (final ScriptEngineFactoryState state : this.engineSpiServices.values())
+            {
+                extensions.addAll(registerFactory(tmp, state.scriptEngineFactory,
+                    state.properties));
+            }
+        }
+
+        synchronized (this){
+            this.state = tmp;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private Collection<?> registerFactories(final EngineManagerState mgr,
+        final Bundle bundle)
+    {
+        URL url = bundle.getEntry(ENGINE_FACTORY_SERVICE);
+        InputStream ins = null;
+        final SortedSet<String> extensions = new TreeSet<String>();
+        try
+        {
+            ins = url.openStream();
+            BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
+            String line;
+            while ((line = reader.readLine()) != null)
+            {
+                if (!line.startsWith("#") && line.trim().length() > 0)
+                {
+                    try
+                    {
+                        Class<ScriptEngineFactory> clazz = bundle.loadClass(line);
+                        ScriptEngineFactory spi = clazz.newInstance();
+                        registerFactory(mgr, spi, null);
+                        extensions.addAll(spi.getExtensions());
+                    }
+                    catch (Throwable t)
+                    {
+                        log.log(LogService.LOG_ERROR,
+                            "Cannot register ScriptEngineFactory " + line, t);
+                    }
+                }
+            }
+        }
+        catch (IOException ioe)
+        {
+            // ignore
+        }
+        finally
+        {
+            IOUtils.closeQuietly(ins);
+        }
+
+        return extensions;
+    }
+
+    private Collection<?> registerFactory(final EngineManagerState mgr,
+        final ScriptEngineFactory factory, final Map<Object, Object> props)
+    {
+        log.log(
+            LogService.LOG_INFO,
+            String.format("Adding ScriptEngine %s, %s for language %s, %s",
+                factory.getEngineName(), factory.getEngineVersion(),
+                factory.getLanguageName(), factory.getLanguageVersion()));
+
+        mgr.factories.add(factory);
+        mgr.factoryProperties.put(factory, props);
+        for (Object ext : factory.getExtensions()) {
+            mgr.extensionAssociations.put((String) ext, factory);
+        }
+        return factory.getExtensions();
+    }
+
+    public void dispose()
+    {
+        if (scriptFactoryTracker != null)
+        {
+            scriptFactoryTracker.close();
+        }
+    }
+
+    private static Map<Object, Object> getServiceProperties(ServiceReference reference)
+    {
+        Map<Object, Object> props = new HashMap<Object, Object>();
+        for (String key : reference.getPropertyKeys())
+        {
+            props.put(key, reference.getProperty(key));
+        }
+        return props;
+    }
+
+    private static class ScriptEngineFactoryState
+    {
+        final ScriptEngineFactory scriptEngineFactory;
+        Map<Object, Object> properties;
+
+        private ScriptEngineFactoryState(ScriptEngineFactory scriptEngineFactory, Map<Object, Object> properties)
+        {
+            this.scriptEngineFactory = scriptEngineFactory;
+            this.properties = properties;
+        }
+    }
+
+    private static class EngineManagerState
+    {
+        private final List<ScriptEngineFactory> factories = new ArrayList<ScriptEngineFactory>();
+        private final Map<ScriptEngineFactory, Map<Object, Object>> factoryProperties
+                            = new HashMap<ScriptEngineFactory, Map<Object, Object>>();
+        private final Map<String, ScriptEngineFactory> extensionAssociations
+                            = new HashMap<String, ScriptEngineFactory>();
+
+    }
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptHelper.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptHelper.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptHelper.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/java/org/apache/felix/webconsole/plugins/scriptconsole/internal/ScriptHelper.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.internal;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import java.lang.reflect.Array;
+import java.util.*;
+
+class ScriptHelper
+{
+    /** The bundle context. */
+    private final BundleContext bundleContext;
+
+    /**
+     * The list of references - we don't need to synchronize this as we are
+     * running in one single request.
+     */
+    private List<ServiceReference> references;
+
+    /** A map of found services. */
+    private Map<String, Object> services;
+
+    public ScriptHelper(BundleContext bundleContext)
+    {
+        this.bundleContext = bundleContext;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <ServiceType> ServiceType getService(Class<ServiceType> type)
+    {
+        ServiceType service = (this.services == null ? null
+            : (ServiceType) this.services.get(type.getName()));
+        if (service == null)
+        {
+            final ServiceReference ref = this.bundleContext.getServiceReference(type.getName());
+            if (ref != null)
+            {
+                service = (ServiceType) this.bundleContext.getService(ref);
+                if (service != null)
+                {
+                    if (this.services == null)
+                    {
+                        this.services = new HashMap<String, Object>();
+                    }
+                    if (this.references == null)
+                    {
+                        this.references = new ArrayList<ServiceReference>();
+                    }
+                    this.references.add(ref);
+                    this.services.put(type.getName(), service);
+                }
+            }
+        }
+        return service;
+    }
+
+    public <ServiceType> ServiceType[] getServices(Class<ServiceType> serviceType,
+        String filter) throws InvalidSyntaxException
+    {
+        final ServiceReference[] refs = this.bundleContext.getServiceReferences(
+            serviceType.getName(), filter);
+        ServiceType[] result = null;
+        if (refs != null)
+        {
+            final List<ServiceType> objects = new ArrayList<ServiceType>();
+            for (int i = 0; i < refs.length; i++)
+            {
+                @SuppressWarnings("unchecked")
+                final ServiceType service = (ServiceType) this.bundleContext.getService(refs[i]);
+                if (service != null)
+                {
+                    if (this.references == null)
+                    {
+                        this.references = new ArrayList<ServiceReference>();
+                    }
+                    this.references.add(refs[i]);
+                    objects.add(service);
+                }
+            }
+            if (objects.size() > 0)
+            {
+                @SuppressWarnings("unchecked")
+                ServiceType[] srv = (ServiceType[]) Array.newInstance(serviceType,
+                    objects.size());
+                result = objects.toArray(srv);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Clean up this instance.
+     */
+    public void cleanup()
+    {
+        if (this.references != null)
+        {
+            final Iterator<ServiceReference> i = this.references.iterator();
+            while (i.hasNext())
+            {
+                final ServiceReference ref = i.next();
+                this.bundleContext.ungetService(ref);
+            }
+            this.references.clear();
+        }
+        if (this.services != null)
+        {
+            this.services.clear();
+        }
+    }
+}

Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/bundle.properties
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/bundle.properties?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/bundle.properties (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/OSGI-INF/l10n/bundle.properties Mon Jul 22 06:58:03 2013
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+script.title=Script Console
+console.execute=Execute
+console.lang=Language
\ No newline at end of file

Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/loadmode.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/loadmode.js?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/loadmode.js (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/mode/loadmode.js Mon Jul 22 06:58:03 2013
@@ -0,0 +1,51 @@
+(function() {
+  if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
+
+  var loading = {};
+  function splitCallback(cont, n) {
+    var countDown = n;
+    return function() { if (--countDown == 0) cont(); };
+  }
+  function ensureDeps(mode, cont) {
+    var deps = CodeMirror.modes[mode].dependencies;
+    if (!deps) return cont();
+    var missing = [];
+    for (var i = 0; i < deps.length; ++i) {
+      if (!CodeMirror.modes.hasOwnProperty(deps[i]))
+        missing.push(deps[i]);
+    }
+    if (!missing.length) return cont();
+    var split = splitCallback(cont, missing.length);
+    for (var i = 0; i < missing.length; ++i)
+      CodeMirror.requireMode(missing[i], split);
+  }
+
+  CodeMirror.requireMode = function(mode, cont) {
+    if (typeof mode != "string") mode = mode.name;
+    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
+    if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
+
+    var script = document.createElement("script");
+    script.src = CodeMirror.modeURL.replace(/%N/g, mode);
+    var others = document.getElementsByTagName("script")[0];
+    others.parentNode.insertBefore(script, others);
+    var list = loading[mode] = [cont];
+    var count = 0, poll = setInterval(function() {
+      if (++count > 100) return clearInterval(poll);
+      if (CodeMirror.modes.hasOwnProperty(mode)) {
+        clearInterval(poll);
+        loading[mode] = null;
+        ensureDeps(mode, function() {
+          for (var i = 0; i < list.length; ++i) list[i]();
+        });
+      }
+    }, 200);
+  };
+
+  CodeMirror.autoLoadMode = function(instance, mode) {
+    if (!CodeMirror.modes.hasOwnProperty(mode))
+      CodeMirror.requireMode(mode, function() {
+        instance.setOption("mode", instance.getOption("mode"));
+      });
+  };
+}());

Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/runmode.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/runmode.js?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/runmode.js (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/addon/runmode/runmode.js Mon Jul 22 06:58:03 2013
@@ -0,0 +1,56 @@
+CodeMirror.runMode = function(string, modespec, callback, options) {
+  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
+  var ie = /MSIE \d/.test(navigator.userAgent);
+  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+
+  if (callback.nodeType == 1) {
+    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+    var node = callback, col = 0;
+    node.innerHTML = "";
+    callback = function(text, style) {
+      if (text == "\n") {
+        // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
+        // Emitting a carriage return makes everything ok.
+        node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
+        col = 0;
+        return;
+      }
+      var content = "";
+      // replace tabs
+      for (var pos = 0;;) {
+        var idx = text.indexOf("\t", pos);
+        if (idx == -1) {
+          content += text.slice(pos);
+          col += text.length - pos;
+          break;
+        } else {
+          col += idx - pos;
+          content += text.slice(pos, idx);
+          var size = tabSize - col % tabSize;
+          col += size;
+          for (var i = 0; i < size; ++i) content += " ";
+          pos = idx + 1;
+        }
+      }
+
+      if (style) {
+        var sp = node.appendChild(document.createElement("span"));
+        sp.className = "cm-" + style.replace(/ +/g, " cm-");
+        sp.appendChild(document.createTextNode(content));
+      } else {
+        node.appendChild(document.createTextNode(content));
+      }
+    };
+  }
+
+  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
+  for (var i = 0, e = lines.length; i < e; ++i) {
+    if (i) callback("\n");
+    var stream = new CodeMirror.StringStream(lines[i]);
+    while (!stream.eol()) {
+      var style = mode.token(stream, state);
+      callback(stream.current(), style, i, stream.start);
+      stream.start = stream.pos;
+    }
+  }
+};

Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.css
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.css?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.css (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/lib/codemirror.css Mon Jul 22 06:58:03 2013
@@ -0,0 +1,248 @@
+/* BASICS */
+
+.CodeMirror {
+  /* Set height, width, borders, and global font properties here */
+  font-family: monospace;
+  height: 300px;
+}
+.CodeMirror-scroll {
+  /* Set scrolling behaviour here */
+  overflow: auto;
+}
+
+/* PADDING */
+
+.CodeMirror-lines {
+  padding: 4px 0; /* Vertical padding around content */
+}
+.CodeMirror pre {
+  padding: 0 4px; /* Horizontal padding of content */
+}
+
+.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+  background-color: white; /* The little square between H and V scrollbars */
+}
+
+/* GUTTER */
+
+.CodeMirror-gutters {
+  border-right: 1px solid #ddd;
+  background-color: #f7f7f7;
+  white-space: nowrap;
+}
+.CodeMirror-linenumbers {}
+.CodeMirror-linenumber {
+  padding: 0 3px 0 5px;
+  min-width: 20px;
+  text-align: right;
+  color: #999;
+}
+
+/* CURSOR */
+
+.CodeMirror div.CodeMirror-cursor {
+  border-left: 1px solid black;
+  z-index: 3;
+}
+/* Shown when moving in bi-directional text */
+.CodeMirror div.CodeMirror-secondarycursor {
+  border-left: 1px solid silver;
+}
+.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
+  width: auto;
+  border: 0;
+  background: #7e7;
+  z-index: 1;
+}
+/* Can style cursor different in overwrite (non-insert) mode */
+.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
+
+.cm-tab { display: inline-block; }
+
+/* DEFAULT THEME */
+
+.cm-s-default .cm-keyword {color: #708;}
+.cm-s-default .cm-atom {color: #219;}
+.cm-s-default .cm-number {color: #164;}
+.cm-s-default .cm-def {color: #00f;}
+.cm-s-default .cm-variable {color: black;}
+.cm-s-default .cm-variable-2 {color: #05a;}
+.cm-s-default .cm-variable-3 {color: #085;}
+.cm-s-default .cm-property {color: black;}
+.cm-s-default .cm-operator {color: black;}
+.cm-s-default .cm-comment {color: #a50;}
+.cm-s-default .cm-string {color: #a11;}
+.cm-s-default .cm-string-2 {color: #f50;}
+.cm-s-default .cm-meta {color: #555;}
+.cm-s-default .cm-error {color: #f00;}
+.cm-s-default .cm-qualifier {color: #555;}
+.cm-s-default .cm-builtin {color: #30a;}
+.cm-s-default .cm-bracket {color: #997;}
+.cm-s-default .cm-tag {color: #170;}
+.cm-s-default .cm-attribute {color: #00c;}
+.cm-s-default .cm-header {color: blue;}
+.cm-s-default .cm-quote {color: #090;}
+.cm-s-default .cm-hr {color: #999;}
+.cm-s-default .cm-link {color: #00c;}
+
+.cm-negative {color: #d44;}
+.cm-positive {color: #292;}
+.cm-header, .cm-strong {font-weight: bold;}
+.cm-em {font-style: italic;}
+.cm-link {text-decoration: underline;}
+
+.cm-invalidchar {color: #f00;}
+
+div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
+div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+
+/* STOP */
+
+/* The rest of this file contains styles related to the mechanics of
+   the editor. You probably shouldn't touch them. */
+
+.CodeMirror {
+  line-height: 1;
+  position: relative;
+  overflow: hidden;
+  background: white;
+  color: black;
+}
+
+.CodeMirror-scroll {
+  /* 30px is the magic margin used to hide the element's real scrollbars */
+  /* See overflow: hidden in .CodeMirror */
+  margin-bottom: -30px; margin-right: -30px;
+  padding-bottom: 30px; padding-right: 30px;
+  height: 100%;
+  outline: none; /* Prevent dragging from highlighting the element */
+  position: relative;
+}
+.CodeMirror-sizer {
+  position: relative;
+}
+
+/* The fake, visible scrollbars. Used to force redraw during scrolling
+   before actuall scrolling happens, thus preventing shaking and
+   flickering artifacts. */
+.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
+  position: absolute;
+  z-index: 6;
+  display: none;
+}
+.CodeMirror-vscrollbar {
+  right: 0; top: 0;
+  overflow-x: hidden;
+  overflow-y: scroll;
+}
+.CodeMirror-hscrollbar {
+  bottom: 0; left: 0;
+  overflow-y: hidden;
+  overflow-x: scroll;
+}
+.CodeMirror-scrollbar-filler {
+  right: 0; bottom: 0;
+}
+.CodeMirror-gutter-filler {
+  left: 0; bottom: 0;
+}
+
+.CodeMirror-gutters {
+  position: absolute; left: 0; top: 0;
+  padding-bottom: 30px;
+  z-index: 3;
+}
+.CodeMirror-gutter {
+  white-space: normal;
+  height: 100%;
+  padding-bottom: 30px;
+  margin-bottom: -32px;
+  display: inline-block;
+  /* Hack to make IE7 behave */
+  *zoom:1;
+  *display:inline;
+}
+.CodeMirror-gutter-elt {
+  position: absolute;
+  cursor: default;
+  z-index: 4;
+}
+
+.CodeMirror-lines {
+  cursor: text;
+}
+.CodeMirror pre {
+  /* Reset some styles that the rest of the page might have set */
+  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
+  border-width: 0;
+  background: transparent;
+  font-family: inherit;
+  font-size: inherit;
+  margin: 0;
+  white-space: pre;
+  word-wrap: normal;
+  line-height: inherit;
+  color: inherit;
+  z-index: 2;
+  position: relative;
+  overflow: visible;
+}
+.CodeMirror-wrap pre {
+  word-wrap: break-word;
+  white-space: pre-wrap;
+  word-break: normal;
+}
+.CodeMirror-linebackground {
+  position: absolute;
+  left: 0; right: 0; top: 0; bottom: 0;
+  z-index: 0;
+}
+
+.CodeMirror-linewidget {
+  position: relative;
+  z-index: 2;
+  overflow: auto;
+}
+
+.CodeMirror-widget {
+}
+
+.CodeMirror-wrap .CodeMirror-scroll {
+  overflow-x: hidden;
+}
+
+.CodeMirror-measure {
+  position: absolute;
+  width: 100%; height: 0px;
+  overflow: hidden;
+  visibility: hidden;
+}
+.CodeMirror-measure pre { position: static; }
+
+.CodeMirror div.CodeMirror-cursor {
+  position: absolute;
+  visibility: hidden;
+  border-right: none;
+  width: 0;
+}
+.CodeMirror-focused div.CodeMirror-cursor {
+  visibility: visible;
+}
+
+.CodeMirror-selected { background: #d9d9d9; }
+.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+
+.cm-searching {
+  background: #ffa;
+  background: rgba(255, 255, 0, .4);
+}
+
+/* IE7 hack to prevent it from returning funny offsetTops on the spans */
+.CodeMirror span { *vertical-align: text-bottom; }
+
+@media print {
+  /* Hide the cursor when printing */
+  .CodeMirror div.CodeMirror-cursor {
+    visibility: hidden;
+  }
+}