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;
+ }
+}