SLING-2229 - applying Felix's patch to rationalize ScriptEngineManager implementations

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1179019 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index 19c19ec..24a0eb9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,9 +59,6 @@
                             org.apache.sling.scripting.api;version=2.1.0,
                             javax.script
                         </Export-Package>
-                        <Private-Package>
-                            sun.misc
-                        </Private-Package>
                     </instructions>
                 </configuration>
             </plugin>
diff --git a/src/main/java/javax/script/ScriptEngineManager.java b/src/main/java/javax/script/ScriptEngineManager.java
new file mode 100644
index 0000000..8bf6b31
--- /dev/null
+++ b/src/main/java/javax/script/ScriptEngineManager.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2006 - 2008 (C) The original author or authors
+ *
+ * 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 javax.script;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is copied from the Livetribe 2.0.6 source with one important
+ * extension: The Livetribe implementation has the
+ * {@link #setGlobalScope(Bindings)} and {@link #getGlobalScope()} methods,
+ * which the Sun implementation of this class has {@link #setBindings(Bindings)}
+ * and {@link #getBindings()} methods.
+ * <p>
+ * Another change is to not scan the class loader initially when creating the
+ * ScriptEngineManager -- the assumption is that the ScriptEngine registrations
+ * are managed inside the framework.
+ */
+public class ScriptEngineManager {
+
+    private final Map<String, ScriptEngineFactory> registeredByName = new HashMap<String, ScriptEngineFactory>();
+
+    private final Map<String, ScriptEngineFactory> registeredByExtension = new HashMap<String, ScriptEngineFactory>();
+
+    private final Map<String, ScriptEngineFactory> registeredByMimeType = new HashMap<String, ScriptEngineFactory>();
+
+    private Bindings globalScope;
+
+    public ScriptEngineManager() {
+        this.globalScope = new SimpleBindings();
+    }
+
+    public ScriptEngineManager(
+            @SuppressWarnings("unused") ClassLoader classLoader) {
+        this();
+
+        // nothing more, we just have this method for API compatibility,
+        // but we don't want to read anything from the class loader
+    }
+
+    public Bindings getBindings() {
+        return globalScope;
+    }
+
+    public void setBindings(Bindings globalScope) {
+        if (globalScope == null) {
+            throw new IllegalArgumentException("Global scope cannot be null.");
+        }
+
+        this.globalScope = globalScope;
+    }
+
+    /**
+     * @deprecated use {@link #getBindings()} instaed. This method is introduced
+     *             by the Livetribe JSR-223 implementation and is wrong.
+     */
+    @Deprecated
+    public Bindings getGlobalScope() {
+        return getBindings();
+    }
+
+    /**
+     * @deprecated use {@link #setBindings(Bindings)} instaed. This method is
+     *             introduced by the Livetribe JSR-223 implementation and is
+     *             wrong.
+     */
+    @Deprecated
+    public void setGlobalScope(Bindings globalScope) {
+        setBindings(globalScope);
+    }
+
+    public void put(String key, Object value) {
+        globalScope.put(key, value);
+    }
+
+    public Object get(String key) {
+        return globalScope.get(key);
+    }
+
+    public ScriptEngine getEngineByName(String shortName) {
+        ScriptEngineFactory factory = registeredByName.get(shortName);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public ScriptEngine getEngineByExtension(String extension) {
+        ScriptEngineFactory factory = registeredByExtension.get(extension);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public ScriptEngine getEngineByMimeType(String mimeType) {
+        ScriptEngineFactory factory = registeredByMimeType.get(mimeType);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public List<ScriptEngineFactory> getEngineFactories() {
+        // we don't apply discovery, so nothing is returned here !
+        return Collections.emptyList();
+    }
+
+    public void registerEngineName(String name, ScriptEngineFactory factory) {
+        registeredByName.put(name, factory);
+    }
+
+    public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
+        registeredByMimeType.put(type, factory);
+    }
+
+    public void registerEngineExtension(String extension,
+            ScriptEngineFactory factory) {
+        registeredByExtension.put(extension, factory);
+    }
+}
+/*
+ * Copyright 2006 - 2008 (C) The original author or authors
+ *
+ * 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 javax.script;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is copied from the Livetribe 2.0.6 source with one important
+ * extension: The Livetribe implementation has the
+ * {@link #setGlobalScope(Bindings)} and {@link #getGlobalScope()} methods,
+ * which the Sun implementation of this class has {@link #setBindings(Bindings)}
+ * and {@link #getBindings()} methods.
+ * <p>
+ * Another change is to not scan the class loader initially when creating the
+ * ScriptEngineManager -- the assumption is that the ScriptEngine registrations
+ * are managed inside the framework.
+ */
+public class ScriptEngineManager {
+
+    private final Map<String, ScriptEngineFactory> registeredByName = new HashMap<String, ScriptEngineFactory>();
+
+    private final Map<String, ScriptEngineFactory> registeredByExtension = new HashMap<String, ScriptEngineFactory>();
+
+    private final Map<String, ScriptEngineFactory> registeredByMimeType = new HashMap<String, ScriptEngineFactory>();
+
+    private Bindings globalScope;
+
+    public ScriptEngineManager() {
+        this.globalScope = new SimpleBindings();
+    }
+
+    public ScriptEngineManager(
+            @SuppressWarnings("unused") ClassLoader classLoader) {
+        this();
+
+        // nothing more, we just have this method for API compatibility,
+        // but we don't want to read anything from the class loader
+    }
+
+    public Bindings getBindings() {
+        return globalScope;
+    }
+
+    public void setBindings(Bindings globalScope) {
+        if (globalScope == null) {
+            throw new IllegalArgumentException("Global scope cannot be null.");
+        }
+
+        this.globalScope = globalScope;
+    }
+
+    public Bindings getGlobalScope() {
+        return getBindings();
+    }
+
+    public void setGlobalScope(Bindings globalScope) {
+        setBindings(globalScope);
+    }
+
+    public void put(String key, Object value) {
+        globalScope.put(key, value);
+    }
+
+    public Object get(String key) {
+        return globalScope.get(key);
+    }
+
+    public ScriptEngine getEngineByName(String shortName) {
+        ScriptEngineFactory factory = registeredByName.get(shortName);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public ScriptEngine getEngineByExtension(String extension) {
+        ScriptEngineFactory factory = registeredByExtension.get(extension);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public ScriptEngine getEngineByMimeType(String mimeType) {
+        ScriptEngineFactory factory = registeredByMimeType.get(mimeType);
+        if (factory == null) return null;
+
+        ScriptEngine engine = factory.getScriptEngine();
+
+        engine.setBindings(globalScope, ScriptContext.GLOBAL_SCOPE);
+
+        return engine;
+    }
+
+    public List<ScriptEngineFactory> getEngineFactories() {
+        // we don't apply discovery, so nothing is returned here !
+        return Collections.emptyList();
+    }
+
+    public void registerEngineName(String name, ScriptEngineFactory factory) {
+        registeredByName.put(name, factory);
+    }
+
+    public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
+        registeredByMimeType.put(type, factory);
+    }
+
+    public void registerEngineExtension(String extension,
+            ScriptEngineFactory factory) {
+        registeredByExtension.put(extension, factory);
+    }
+}
diff --git a/src/main/java/sun/misc/Service.java b/src/main/java/sun/misc/Service.java
deleted file mode 100644
index 189e756..0000000
--- a/src/main/java/sun/misc/Service.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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 sun.misc;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * The <code>Service</code> class is a primitive stub of the original
- * <code>sun.misc.Service</code> class used by the
- * <code>javax.script.ScriptEngineManager</code> to find script engine
- * factories in factory service files.
- * <p>
- * This stub is provided because the original class is not part of the official
- * Java API and may not be available on all platforms. In addition even if the
- * class would be available on the Java platform, it may not be visible inside
- * the OSGi framework. Finally, the <em>org.apache.sling.scripting.resolver</em>
- * bundle implements its own resolution of script engine factories and thus the
- * <code>Service</code> method is not used.
- */
-public class Service {
-
-    private static final String PREFIX = "META-INF/services/";
-
-    /** Returns an empty iterator */
-    public static <ProviderType> Iterator<ProviderType> providers(Class<ProviderType> type, ClassLoader loader) throws IOException {
-        if (loader != null) {
-            try {
-                String name = PREFIX + type.getName();
-                Enumeration<?> files = loader.getResources(name);
-                return new NameIterator<ProviderType>(loader, files);
-            } catch (IOException ignore) {
-            }
-        }
-
-        return Collections.<ProviderType> emptyList().iterator();
-    }
-
-    private static class NameIterator<ProviderType> implements Iterator<ProviderType> {
-
-        private final ClassLoader loader;
-
-        private final Enumeration<?> files;
-
-        private Iterator<String> currentFile;
-
-        private ProviderType nextProvider;
-
-        public NameIterator(ClassLoader loader, Enumeration<?> files) {
-            this.loader = loader;
-            this.files = files;
-            seek();
-        }
-
-        public boolean hasNext() {
-            return nextProvider != null;
-        }
-
-        public ProviderType next() {
-            if (nextProvider == null) {
-                throw new NoSuchElementException();
-            }
-
-            ProviderType result = nextProvider;
-            seek();
-            return result;
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        private void seek() {
-            if (currentFile == null || !currentFile.hasNext()) {
-                currentFile = getNames();
-            }
-
-            nextProvider = getClass(currentFile);
-        }
-
-        private Iterator<String> getNames() {
-            while (files.hasMoreElements()) {
-                URL fileUrl = (URL) files.nextElement();
-                InputStream ins = null;
-                try {
-                    ArrayList<String> names = new ArrayList<String>();
-                    ins = fileUrl.openStream();
-                    BufferedReader br = new BufferedReader(new InputStreamReader(ins));
-                    String name;
-                    while ( (name = br.readLine()) != null) {
-                        int hash = name.indexOf('#');
-                        if (hash >= 0) {
-                            name = name.substring(0, hash);
-                        }
-                        name = name.trim();
-
-                        if (name.length() > 0) {
-                            names.add(name);
-                        }
-                    }
-
-                    return names.iterator();
-                } catch (IOException ioe) {
-
-                } finally {
-                    if (ins != null) {
-                        try {
-                            ins.close();
-                        } catch (IOException ignore) {
-                        }
-                    }
-                }
-            }
-
-            // exhausted search
-            return null;
-        }
-
-        @SuppressWarnings("unchecked")
-        private ProviderType getClass(Iterator<String> currentFile) {
-            if (currentFile != null && currentFile.hasNext()) {
-                String name = currentFile.next();
-                try {
-                    Class<?> clazz = loader.loadClass(name);
-                    return (ProviderType) clazz.newInstance();
-                } catch (Throwable t) {
-                    //
-                }
-            }
-
-            return null;
-        }
-    }
-}