You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2007/12/17 12:42:20 UTC

svn commit: r604842 - in /incubator/sling/trunk/scripting/resolver: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/scripting/ src/main/java/org/apache/sling/s...

Author: fmeschbe
Date: Mon Dec 17 03:42:17 2007
New Revision: 604842

URL: http://svn.apache.org/viewvc?rev=604842&view=rev
Log:
SLING-137 Create new ScriptResolver implementation project
SLING-110 Support Java Scripting in the ScriptResolver

Added:
    incubator/sling/trunk/scripting/resolver/   (with props)
    incubator/sling/trunk/scripting/resolver/pom.xml   (with props)
    incubator/sling/trunk/scripting/resolver/src/
    incubator/sling/trunk/scripting/resolver/src/main/
    incubator/sling/trunk/scripting/resolver/src/main/java/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java   (with props)
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java   (with props)
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java   (with props)
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java   (with props)
    incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java   (with props)
    incubator/sling/trunk/scripting/resolver/src/main/resources/
    incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/
    incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/LICENSE
    incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/NOTICE
    incubator/sling/trunk/scripting/resolver/src/test/
    incubator/sling/trunk/scripting/resolver/src/test/java/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/
    incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java   (with props)

Propchange: incubator/sling/trunk/scripting/resolver/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Dec 17 03:42:17 2007
@@ -0,0 +1,3 @@
+.classpath
+.project
+target

Added: incubator/sling/trunk/scripting/resolver/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/pom.xml?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/pom.xml (added)
+++ incubator/sling/trunk/scripting/resolver/pom.xml Mon Dec 17 03:42:17 2007
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+    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.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>1-incubator-SNAPSHOT</version>
+        <relativePath>../../parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>org.apache.sling.scripting.resolver</artifactId>
+    <version>2.0.0-incubator-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <name>Sling - ScriptResolver implementation</name>
+    <description>
+        This bundle implements the Sling API ScriptResolver interface
+    </description>
+
+    <scm>
+        <connection>
+            scm:svn:http://svn.apache.org/repos/asf/incubator/sling/trunk/scripting/resolver
+        </connection>
+        <developerConnection>
+            scm:svn:https://svn.apache.org/repos/asf/incubator/sling/trunk/scripting/resolver
+        </developerConnection>
+        <url>
+            http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver
+        </url>
+    </scm>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.sling.scripting.resolver;version=${pom.version}
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.sling.scripting.resolver.impl
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.jcr.api</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.scripting.api</artifactId>
+            <version>2.0.0-incubator-SNAPSHOT</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi_R4_core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi_R4_compendium</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+
+    </dependencies>
+</project>

Propchange: incubator/sling/trunk/scripting/resolver/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,187 @@
+/*
+ * 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.sling.scripting.resolver;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.scripting.SlingScript;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
+
+/**
+ * Simple script helper providing access to the (wrapped) response, the
+ * on-demand writer and a simple API for request inclusion. Instances of this
+ * class are made available to the scripts as the global <code>sling</code>
+ * variable.
+ */
+public class ScriptHelper implements SlingScriptHelper {
+
+    private final SlingScript script;
+
+    private final SlingHttpServletRequest request;
+
+    private final SlingHttpServletResponse response;
+
+    public ScriptHelper(SlingScript script, SlingHttpServletRequest request,
+            SlingHttpServletResponse response) {
+        this.script = script;
+        this.request = request;
+        this.response = new OnDemandWriterResponse(response);
+    }
+
+    public SlingScript getScript() {
+        return script;
+    }
+
+    public SlingHttpServletRequest getRequest() {
+        return request;
+    }
+
+    public SlingHttpServletResponse getResponse() {
+        return response;
+    }
+
+    public void include(String path) throws ServletException, IOException {
+        include(path, null);
+    }
+
+    public void include(String path, RequestDispatcherOptions options)
+            throws ServletException, IOException {
+        // TODO: Implement for options !!
+        RequestDispatcher dispatcher = getRequest().getRequestDispatcher(path);
+        if (dispatcher != null) {
+            dispatcher.include(getRequest(), getResponse());
+        }
+    }
+
+    /**
+     * Simple Response wrapper returning an on-demand writer when asked for a
+     * writer.
+     */
+    private static class OnDemandWriterResponse extends
+            SlingHttpServletResponseWrapper {
+
+        private PrintWriter writer;
+
+        OnDemandWriterResponse(SlingHttpServletResponse delegatee) {
+            super(delegatee);
+        }
+
+        @Override
+        public PrintWriter getWriter() {
+            if (writer == null) {
+                writer = new PrintWriter(new OnDemandWriter(getResponse()));
+            }
+
+            return writer;
+        }
+    }
+
+    /**
+     * A writer acquiring the actual writer to delegate to on demand when the
+     * first data is to be written.
+     */
+    private static class OnDemandWriter extends Writer {
+
+        private final ServletResponse response;
+
+        private Writer delegatee;
+
+        OnDemandWriter(ServletResponse response) {
+            this.response = response;
+        }
+
+        private Writer getWriter() throws IOException {
+            if (delegatee == null) {
+                delegatee = response.getWriter();
+            }
+
+            return delegatee;
+        }
+
+        @Override
+        public void write(int c) throws IOException {
+            synchronized (lock) {
+                getWriter().write(c);
+            }
+        }
+
+        @Override
+        public void write(char[] cbuf) throws IOException {
+            synchronized (lock) {
+                getWriter().write(cbuf);
+            }
+        }
+
+        @Override
+        public void write(char[] cbuf, int off, int len) throws IOException {
+            synchronized (lock) {
+                getWriter().write(cbuf, off, len);
+            }
+        }
+
+        @Override
+        public void write(String str) throws IOException {
+            synchronized (lock) {
+                getWriter().write(str);
+            }
+        }
+
+        @Override
+        public void write(String str, int off, int len) throws IOException {
+            synchronized (lock) {
+                getWriter().write(str, off, len);
+            }
+        }
+
+        @Override
+        public void flush() throws IOException {
+            synchronized (lock) {
+                Writer writer = delegatee;
+                if (writer != null) {
+                    writer.flush();
+                }
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            synchronized (lock) {
+                // flush and close the delegatee if existing, otherwise ignore
+                Writer writer = delegatee;
+                if (writer != null) {
+                    writer.flush();
+                    writer.close();
+
+                    // drop the delegatee now
+                    delegatee = null;
+                }
+            }
+        }
+    }
+}

Propchange: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,146 @@
+/*
+ * 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.sling.scripting.resolver;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.HttpConstants;
+
+public class ScriptPathSupport {
+
+    public static String getScriptBaseName(SlingHttpServletRequest request) {
+        String methodName = request.getMethod();
+        String extension = request.getRequestPathInfo().getExtension();
+
+        if (methodName == null || methodName.length() == 0) {
+            
+            throw new IllegalArgumentException(
+                "HTTP Method name must not be empty");
+
+        } else if (HttpConstants.METHOD_GET.equalsIgnoreCase(methodName)
+            && extension != null && extension.length() > 0) {
+
+            // for GET, we use the request extension
+            return extension;
+
+        } else {
+
+            // for other methods use the method name
+            return methodName.toUpperCase();
+        }
+    }
+
+    public static Iterator<String> getPathIterator(
+            SlingHttpServletRequest request, String[] path) {
+        return new ScriptPathIterator(request, path);
+    }
+
+    private static class ScriptPathIterator implements Iterator<String> {
+        private final String resourceTypePath;
+
+        private final String selectorsPath;
+
+        private String[] path;
+
+        private int pathIdx;
+
+        private int minPathLength;
+
+        private String nextPath;
+
+        private ScriptPathIterator(SlingHttpServletRequest request,
+                String[] path) {
+
+            this.resourceTypePath = request.getResource().getResourceType().replaceAll(
+                "\\:", "/");
+
+            String selectors = request.getRequestPathInfo().getSelectorString();
+            if (selectors == null) {
+                this.selectorsPath = null;
+            } else {
+                this.selectorsPath = "/"
+                    + selectors.toLowerCase().replace('.', '/');
+            }
+
+            // path prefixes
+            this.path = path;
+            this.pathIdx = -1;
+
+            // prepare the first entry
+            this.nextPath = "";
+            seek();
+        }
+
+        public boolean hasNext() {
+            return nextPath != null;
+        }
+
+        public String next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            String result = nextPath;
+            seek();
+            return result;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("remove");
+        }
+
+        private void seek() {
+
+            int lastSlash = nextPath.lastIndexOf('/');
+            if (lastSlash >= minPathLength) {
+
+                nextPath = nextPath.substring(0, lastSlash);
+
+            } else {
+
+                pathIdx++;
+                if (pathIdx < path.length) {
+                    final StringBuffer sb = new StringBuffer();
+
+                    // the default path root
+                    sb.append(path[pathIdx]).append('/');
+
+                    // append the resource type derived path
+                    sb.append(resourceTypePath);
+
+                    minPathLength = sb.length();
+
+                    // add selectors in front of the filename if any, replacing
+                    // dots
+                    // in them
+                    // by slashes so that print.a4 becomes print/a4/
+                    if (selectorsPath != null) {
+                        sb.append(selectorsPath);
+                    }
+
+                    nextPath = sb.toString();
+                } else {
+                    nextPath = null;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/ScriptPathSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,225 @@
+/*
+ * 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.sling.scripting.resolver.impl;
+
+import static org.apache.sling.api.scripting.SlingBindings.LOG;
+import static org.apache.sling.api.scripting.SlingBindings.OUT;
+import static org.apache.sling.api.scripting.SlingBindings.REQUEST;
+import static org.apache.sling.api.scripting.SlingBindings.RESOURCE;
+import static org.apache.sling.api.scripting.SlingBindings.RESPONSE;
+import static org.apache.sling.api.scripting.SlingBindings.SLING;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import javax.script.SimpleScriptContext;
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScript;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.resolver.ScriptHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class DefaultSlingScript implements SlingScript {
+
+    private Resource scriptResource;
+
+    private ScriptEngine scriptEngine;
+
+    DefaultSlingScript(Resource scriptResource, ScriptEngine scriptEngine) {
+        this.scriptResource = scriptResource;
+        this.scriptEngine = scriptEngine;
+    }
+
+    public Resource getScriptResource() {
+        return scriptResource;
+    }
+
+    public void eval(SlingBindings props) throws IOException, ServletException {
+
+        Bindings bindings = verifySlingBindings(props);
+
+        ScriptContext ctx = new SimpleScriptContext();
+        ctx.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
+        ctx.setReader(((SlingHttpServletRequest) bindings.get(REQUEST)).getReader());
+        ctx.setWriter((Writer) bindings.get(OUT));
+        ctx.setErrorWriter(new LogWriter((Logger) bindings.get(LOG)));
+
+        Reader reader = getScriptReader();
+
+        try {
+            // evaluate the script
+            scriptEngine.eval(reader, ctx);
+            
+            // optionall flush the output channel
+            Object flushObject = bindings.get(SlingBindings.FLUSH);
+            if (flushObject instanceof Boolean && ((Boolean) flushObject).booleanValue()) {
+                ctx.getWriter().flush();
+            }
+            
+            // allways flush the error channel
+            ctx.getErrorWriter().flush();
+            
+        } catch (ScriptException se) {
+            throw new ServletException(se.getMessage(), se);
+        }
+    }
+
+    private Reader getScriptReader() throws IOException {
+
+        InputStream input = getScriptResource().adaptTo(InputStream.class);
+        if (input == null) {
+            throw new IOException("Cannot get a stream to the script resource "
+                + getScriptResource());
+        }
+
+        // Now know how to get the input stream, we still have to decide
+        // on the encoding of the stream's data. Primarily we assume it is
+        // UTF-8, which is a default in many places in JCR. Secondarily
+        // we try to get a jcr:encoding property besides the data property
+        // to provide a possible encoding
+        ResourceMetadata meta = getScriptResource().getResourceMetadata();
+        String encoding = (String) meta.get(ResourceMetadata.CHARACTER_ENCODING);
+        if (encoding == null) {
+            encoding = "UTF-8";
+        }
+
+        // access the value as a stream and return a buffered reader
+        // converting the stream data using UTF-8 encoding, which is
+        // the default encoding used
+        return new BufferedReader(new InputStreamReader(input, encoding));
+    }
+
+    private Bindings verifySlingBindings(SlingBindings slingBindings)
+            throws IOException, ServletException {
+        Object requestObject = slingBindings.get(REQUEST);
+        if (!(requestObject instanceof SlingHttpServletRequest)) {
+            throw fail(REQUEST, "Missing or wrong type");
+        }
+
+        Object responseObject = slingBindings.get(RESPONSE);
+        if (!(responseObject instanceof SlingHttpServletResponse)) {
+            throw fail(RESPONSE, "Missing or wrong type");
+        }
+
+        Object resourceObject = slingBindings.get(RESOURCE);
+        if (resourceObject != null && !(resourceObject instanceof Resource)) {
+            throw fail(RESOURCE, "Wrong type");
+        }
+
+        Object writerObject = slingBindings.get(OUT);
+        if (writerObject != null && !(writerObject instanceof PrintWriter)) {
+            throw fail(OUT, "Wrong type");
+        }
+
+        Bindings bindings = new SimpleBindings();
+        SlingScriptHelper sling;
+
+        Object slingObject = slingBindings.get(SLING);
+        if (slingObject == null) {
+
+            sling = new ScriptHelper(this,
+                (SlingHttpServletRequest) requestObject,
+                (SlingHttpServletResponse) responseObject);
+
+        } else if (slingObject instanceof SlingScriptHelper) {
+
+            sling = (SlingScriptHelper) slingObject;
+
+            if (sling.getRequest() != requestObject) {
+                throw fail(REQUEST,
+                    "Not the same as request field of SlingScriptHelper");
+            }
+
+            if (sling.getResponse() != responseObject) {
+                throw fail(RESPONSE,
+                    "Not the same as response field of SlingScriptHelper");
+            }
+
+            if (resourceObject != null
+                && sling.getRequest().getResource() != resourceObject) {
+                throw fail(RESOURCE,
+                    "Not the same as resource of the SlingScriptHelper request");
+            }
+
+            if (writerObject != null
+                && sling.getResponse().getWriter() != writerObject) {
+                throw fail(OUT,
+                    "Not the same as writer of the SlingScriptHelper response");
+            }
+
+        } else {
+
+            throw fail(SLING, "Wrong type");
+
+        }
+
+        Object logObject = slingBindings.get(LOG);
+        if (logObject == null) {
+            logObject = LoggerFactory.getLogger(getLoggerName());
+        } else if (!(logObject instanceof Logger)) {
+            throw fail(LOG, "Wrong type");
+        }
+
+        // set base variables
+        bindings.put(SLING, sling);
+        bindings.put(REQUEST, sling.getRequest());
+        bindings.put(RESPONSE, sling.getResponse());
+        bindings.put(RESOURCE, sling.getRequest().getResource());
+        bindings.put(OUT, sling.getResponse().getWriter());
+        bindings.put(LOG, logObject);
+
+        // copy non-base variables
+        for (Map.Entry<String, Object> entry : slingBindings.entrySet()) {
+            if (!bindings.containsKey(entry.getKey())) {
+                bindings.put(entry.getKey(), entry.getValue());
+            }
+        }
+        
+        return bindings;
+    }
+
+    private ServletException fail(String variableName, String message) {
+        return new ServletException(variableName + ": " + message);
+    }
+
+    private String getLoggerName() {
+        String name = getScriptResource().getURI();
+        name = name.replace('.', '$');
+        name = name.replace('/', '.');
+        return name;
+    }
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScript.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,288 @@
+/*
+ * 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.sling.scripting.resolver.impl;
+
+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.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
+import org.apache.sling.api.SlingException;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.scripting.SlingScript;
+import org.apache.sling.api.scripting.SlingScriptResolver;
+import org.apache.sling.api.servlets.HttpConstants;
+import org.apache.sling.scripting.resolver.ScriptPathSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Find scripts in the repository, based on the current Resource type. The
+ * script filename is built using the current HTTP request method name, followed
+ * by the extension of the current request and the desired script extension. For
+ * example, a "js" script for a GET request on a Resource of type some/type with
+ * request extension "html" should be stored as
+ * 
+ * <pre>
+ *      /sling/scripts/some/type/get.html.js
+ * </pre>
+ * 
+ * in the repository.
+ * 
+ * @scr.component metatype="no"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.property name="service.description" value="Default SlingScriptResolver"
+ * @scr.service
+ */
+public class DefaultSlingScriptResolver implements SlingScriptResolver,
+        BundleListener {
+
+    private static final Logger log = LoggerFactory.getLogger(DefaultSlingScriptResolver.class);
+
+    /**
+     * jcr:encoding
+     */
+    public static final String JCR_ENCODING = "jcr:encoding";
+
+    /** @scr.property values.1="/apps" values.2="/libs" */
+    public static final String PROP_SCRIPT_PATH = "path";
+
+    private static final String ENGINE_FACTORY_SERVICE = "META-INF/services/"
+        + ScriptEngineFactory.class.getName();
+
+    private ScriptEngineManager scriptEngineManager;
+
+    private String[] scriptPath;
+
+    /**
+     * Try to find a script Node that can process the given request, based on
+     * the rules defined above.
+     * 
+     * @return null if not found.
+     */
+    public SlingScript resolveScript(final SlingHttpServletRequest request)
+            throws SlingException {
+
+        ResourceResolver resolver = request.getResourceResolver();
+
+        String baseName = ScriptPathSupport.getScriptBaseName(request) + ".";
+
+        SlingScript result = null;
+        Iterator<String> pathIterator = ScriptPathSupport.getPathIterator(
+            request, scriptPath);
+        while (result == null && pathIterator.hasNext()) {
+
+            Resource scriptRoot = resolver.getResource(pathIterator.next());
+            if (scriptRoot != null) {
+
+                log.debug("Looking for script with filename={} under {}",
+                    baseName, scriptRoot.getURI());
+
+                // get the item and ensure it is a node
+                Iterator<Resource> children = resolver.listChildren(scriptRoot);
+                while (result == null && children.hasNext()) {
+                    Resource resource = children.next();
+                    result = getScript(resource, baseName);
+                }
+            }
+        }
+
+        if (result != null) {
+            log.info("Script {} found for Resource={}",
+                result.getScriptResource().getURI(), request.getResource());
+        } else {
+            log.debug("No script found for Resource={}", request.getResource());
+        }
+
+        return result;
+    }
+
+    public SlingScript findScript(ResourceResolver resourceResolver, String path)
+            throws SlingException {
+        Resource scriptResource;
+        if (path.startsWith("/")) {
+            scriptResource = resourceResolver.getResource(path);
+        } else {
+            scriptResource = null;
+            for (int i = 0; scriptResource == null && i < scriptPath.length; i++) {
+                String testPath = scriptPath[i] + "/" + path;
+                scriptResource = resourceResolver.getResource(testPath);
+            }
+        }
+
+        if (scriptResource != null) {
+            SlingScript script = getScript(scriptResource, null);
+            if (script == null) {
+                log.error("Cannot handle script {} for path {}",
+                    scriptResource.getURI(), path);
+            } else {
+                log.debug("Returning script {} for path {}",
+                    scriptResource.getURI(), path);
+            }
+        } else {
+            log.error("No resource found at " + path);
+        }
+
+        return null;
+    }
+
+    private ScriptEngineManager getScriptEngineManager() {
+        if (scriptEngineManager == null) {
+            ScriptEngineManager tmp = new ScriptEngineManager();
+            for (Bundle bundle : engineSpiBundles) {
+                addFactories(tmp, bundle);
+            }
+            scriptEngineManager = tmp;
+        }
+        return scriptEngineManager;
+    }
+
+    private void addFactories(ScriptEngineManager mgr, Bundle bundle) {
+        URL url = bundle.getEntry(ENGINE_FACTORY_SERVICE);
+        InputStream ins = null;
+        try {
+            ins = url.openStream();
+            BufferedReader reader = new BufferedReader(new InputStreamReader(
+                ins));
+            String line;
+            while ((line = reader.readLine()) != null) {
+                try {
+                    @SuppressWarnings("unchecked")
+                    Class<ScriptEngineFactory> clazz = bundle.loadClass(line);
+                    ScriptEngineFactory spi = clazz.newInstance();
+
+                    log.info("Adding ScriptEngine {}, {} for language {}, {}",
+                        new Object[] { spi.getEngineName(),
+                            spi.getEngineVersion(), spi.getLanguageName(),
+                            spi.getLanguageVersion() });
+
+                    for (Object ext : spi.getExtensions()) {
+                        mgr.registerEngineExtension((String) ext, spi);
+                    }
+                    for (Object mime : spi.getMimeTypes()) {
+                        mgr.registerEngineMimeType((String) mime, spi);
+                    }
+                    for (Object name : spi.getNames()) {
+                        mgr.registerEngineName((String) name, spi);
+                    }
+
+                } catch (Throwable t) {
+                    log.error("Cannot register ScriptEngineFactory " + line, t);
+                }
+            }
+        } catch (IOException ioe) {
+        } finally {
+            if (ins != null) {
+                try {
+                    ins.close();
+                } catch (IOException ioe) {
+                }
+            }
+        }
+    }
+
+    // ---------- BundleListener interface -------------------------------------
+
+    private List<Bundle> engineSpiBundles = new LinkedList<Bundle>();
+
+    public void bundleChanged(BundleEvent event) {
+        if (event.getType() == BundleEvent.STARTED
+            && event.getBundle().getEntry(ENGINE_FACTORY_SERVICE) != null) {
+
+            engineSpiBundles.add(event.getBundle());
+            scriptEngineManager = null;
+
+        } else if (event.getType() == BundleEvent.STOPPED
+            && engineSpiBundles.remove(event.getBundle())) {
+
+            scriptEngineManager = null;
+
+        }
+    }
+
+    // ---------- SCR integration ----------------------------------------------
+
+    protected void activate(ComponentContext context) {
+
+        Object pathProp = context.getProperties().get(PROP_SCRIPT_PATH);
+        if (pathProp instanceof String[]) {
+            scriptPath = (String[]) pathProp;
+        } else if (pathProp instanceof Vector<?>) {
+            Vector<?> pathVector = (Vector<?>) pathProp;
+            List<String> pathList = new ArrayList<String>();
+            for (Object entry : pathVector) {
+                if (entry != null) {
+                    pathList.add(entry.toString());
+                }
+            }
+            scriptPath = pathList.toArray(new String[pathList.size()]);
+        } else {
+            scriptPath = new String[] { "/" };
+        }
+
+        context.getBundleContext().addBundleListener(this);
+
+        Bundle[] bundles = context.getBundleContext().getBundles();
+        for (Bundle bundle : bundles) {
+            if (bundle.getState() == Bundle.ACTIVE
+                && bundle.getEntry(ENGINE_FACTORY_SERVICE) != null) {
+                engineSpiBundles.add(bundle);
+            }
+        }
+    }
+
+    protected void deactivate(ComponentContext context) {
+        context.getBundleContext().removeBundleListener(this);
+
+        engineSpiBundles.clear();
+        scriptEngineManager = null;
+    }
+
+    // ---------- inner class --------------------------------------------------
+
+    private SlingScript getScript(Resource resource, String baseName) {
+        String path = resource.getURI();
+        String name = path.substring(path.lastIndexOf('/') + 1);
+
+        if (baseName == null || name.startsWith(baseName)) {
+            String ext = name.substring(baseName.length());
+            ScriptEngine engine = getScriptEngineManager().getEngineByExtension(
+                ext);
+            if (engine != null) {
+                return new DefaultSlingScript(resource, engine);
+            }
+        }
+
+        return null;
+    }
+}

Propchange: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/DefaultSlingScriptResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,130 @@
+/*
+ * 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.sling.scripting.resolver.impl;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.slf4j.Logger;
+
+/**
+ * The <code>LogWriter</code> is a simple <code>Writer</code> which writes
+ * lines of data to a given SLF4J 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.
+ */
+public 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 StringBuffer lineBuffer;
+
+    /**
+     * Creates a writer based on the given logger.
+     */
+    public LogWriter(Logger logger) {
+        this.logger = logger;
+        this.lineBuffer = new StringBuffer();
+    }
+
+    /**
+     * 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.error(message);
+    }
+
+    /**
+     * Just calls {@link #flush()}
+     */
+    @Override
+    public void close() {
+        flush();
+    }
+
+}

Propchange: incubator/sling/trunk/scripting/resolver/src/main/java/org/apache/sling/scripting/resolver/impl/LogWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/LICENSE
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/LICENSE?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/LICENSE (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/LICENSE Mon Dec 17 03:42:17 2007
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.

Added: incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/NOTICE
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/NOTICE?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/NOTICE (added)
+++ incubator/sling/trunk/scripting/resolver/src/main/resources/META-INF/NOTICE Mon Dec 17 03:42:17 2007
@@ -0,0 +1,5 @@
+Apache Sling Script Resolver
+Copyright 2007 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).

Added: incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java?rev=604842&view=auto
==============================================================================
--- incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java (added)
+++ incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java Mon Dec 17 03:42:17 2007
@@ -0,0 +1,477 @@
+/*
+ * 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.sling.scripting.resolver.impl;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.slf4j.Logger;
+import org.slf4j.Marker;
+
+public class LogWriterTest extends TestCase {
+
+    public void testCharacter() {
+        MockLogger logger = new MockLogger();
+        LogWriter logWriter = new LogWriter(logger);
+
+        // ensure logger is empty
+        logger.getLastMessage();
+
+        // empty flush
+        logWriter.flush();
+        String msg = logger.getLastMessage();
+        assertNull(msg);
+
+        // write a single character, message only after flush
+        logWriter.write('a');
+        assertNull(logger.getLastMessage());
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals("a", msg);
+
+        // write a single CR, no message
+        logWriter.write('\r');
+        assertNull(logger.getLastMessage());
+
+        // write a single LF, no message
+        logWriter.write('\n');
+        assertNull(logger.getLastMessage());
+
+        // write three characters (one is CR)
+        logWriter.write('a');
+        logWriter.write('\r');
+        logWriter.write('b');
+
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals("a", msg);
+
+        logWriter.flush();
+
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals("b", msg);
+
+        // write three characters (one is LF)
+        logWriter.write('a');
+        logWriter.write('\n');
+        logWriter.write('b');
+
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals("a", msg);
+
+        logWriter.flush();
+
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals("b", msg);
+    }
+
+    public void testStringCR() throws IOException {
+        MockLogger logger = new MockLogger();
+        LogWriter logWriter = new LogWriter(logger);
+        
+        // ensure logger is empty
+        logger.getLastMessage();
+        
+        // empty flush
+        logWriter.flush();
+        String msg = logger.getLastMessage();
+        assertNull(msg);
+        
+        // intermediate CR
+        String tMsg1 = "Ein";
+        String tMsg2 = "Text";
+        String tMsg = tMsg1 + "\r" + tMsg2;
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1, msg);
+        
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg2, msg);
+        
+        // initial CR
+        tMsg = "\r" + tMsg1 + tMsg2;
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNull(msg);
+        
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1 + tMsg2, msg);
+        
+        // terminating CR
+        tMsg = tMsg1 + tMsg2 + "\r";
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1+tMsg2, msg);
+        
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNull(msg);
+    }
+    
+    public void testStringLF() throws IOException {
+        MockLogger logger = new MockLogger();
+        LogWriter logWriter = new LogWriter(logger);
+
+        // ensure logger is empty
+        logger.getLastMessage();
+
+        // empty flush
+        logWriter.flush();
+        String msg = logger.getLastMessage();
+        assertNull(msg);
+
+        // intermediate LF
+        String tMsg1 = "Ein";
+        String tMsg2 = "Text";
+        String tMsg = tMsg1 + "\n" + tMsg2;
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1, msg);
+
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg2, msg);
+
+        // initial LF
+        tMsg = "\n" + tMsg1 + tMsg2;
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNull(msg);
+
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1 + tMsg2, msg);
+
+        // terminating LF
+        tMsg = tMsg1 + tMsg2 + "\n";
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg1+tMsg2, msg);
+
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNull(msg);
+    }
+
+    public void testString() throws IOException {
+        MockLogger logger = new MockLogger();
+        LogWriter logWriter = new LogWriter(logger);
+
+        // ensure logger is empty
+        logger.getLastMessage();
+
+        // empty flush
+        logWriter.flush();
+        String msg = logger.getLastMessage();
+        assertNull(msg);
+
+        // flushed line
+        String tMsg = "Ein Text";
+        logWriter.write(tMsg);
+        msg = logger.getLastMessage();
+        assertNull(msg);
+
+        logWriter.flush();
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg, msg);
+
+        // CR terminated line
+        logWriter.write(tMsg + "\r");
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg, msg);
+
+        // LF terminated line
+        logWriter.write(tMsg + "\n");
+        msg = logger.getLastMessage();
+        assertNotNull(msg);
+        assertEquals(tMsg, msg);
+    }
+
+    private static class MockLogger implements Logger {
+
+        private String lastMessage;
+
+        String getLastMessage() {
+            String msg = lastMessage;
+            lastMessage = null;
+            return msg;
+        }
+
+        public void debug(String msg) {
+            fail("Unexpected call");
+        }
+
+        public void debug(String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void debug(String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void debug(String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void debug(Marker marker, String msg) {
+            fail("Unexpected call");
+        }
+
+        public void debug(String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void debug(Marker marker, String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void debug(Marker marker, String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void debug(Marker marker, String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void debug(Marker marker, String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void error(String msg) {
+            lastMessage = msg;
+        }
+
+        public void error(String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void error(String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void error(String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void error(Marker marker, String msg) {
+            fail("Unexpected call");
+        }
+
+        public void error(String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void error(Marker marker, String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void error(Marker marker, String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void error(Marker marker, String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void error(Marker marker, String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public String getName() {
+            return "mock";
+        }
+
+        public void info(String msg) {
+            fail("Unexpected call");
+        }
+
+        public void info(String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void info(String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void info(String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void info(Marker marker, String msg) {
+            fail("Unexpected call");
+        }
+
+        public void info(String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void info(Marker marker, String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void info(Marker marker, String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void info(Marker marker, String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void info(Marker marker, String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public boolean isDebugEnabled() {
+            return false;
+        }
+
+        public boolean isDebugEnabled(Marker marker) {
+            return false;
+        }
+
+        public boolean isErrorEnabled() {
+            return true;
+        }
+
+        public boolean isErrorEnabled(Marker marker) {
+            return true;
+        }
+
+        public boolean isInfoEnabled() {
+            return false;
+        }
+
+        public boolean isInfoEnabled(Marker marker) {
+            return false;
+        }
+
+        public boolean isTraceEnabled() {
+            return false;
+        }
+
+        public boolean isTraceEnabled(Marker marker) {
+            return false;
+        }
+
+        public boolean isWarnEnabled() {
+            return false;
+        }
+
+        public boolean isWarnEnabled(Marker marker) {
+            return false;
+        }
+
+        public void trace(String msg) {
+            fail("Unexpected call");
+        }
+
+        public void trace(String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void trace(String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void trace(String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void trace(Marker marker, String msg) {
+            fail("Unexpected call");
+        }
+
+        public void trace(String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void trace(Marker marker, String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void trace(Marker marker, String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void trace(Marker marker, String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void trace(Marker marker, String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void warn(String msg) {
+            fail("Unexpected call");
+        }
+
+        public void warn(String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void warn(String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void warn(String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void warn(Marker marker, String msg) {
+            fail("Unexpected call");
+        }
+
+        public void warn(String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+
+        public void warn(Marker marker, String format, Object arg) {
+            fail("Unexpected call");
+        }
+
+        public void warn(Marker marker, String format, Object[] argArray) {
+            fail("Unexpected call");
+        }
+
+        public void warn(Marker marker, String msg, Throwable t) {
+            fail("Unexpected call");
+        }
+
+        public void warn(Marker marker, String format, Object arg1, Object arg2) {
+            fail("Unexpected call");
+        }
+    }
+}

Propchange: incubator/sling/trunk/scripting/resolver/src/test/java/org/apache/sling/scripting/resolver/impl/LogWriterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native