com.asual.summer.core.faces.FacesFunctionMapper.java Source code

Java tutorial

Introduction

Here is the source code for com.asual.summer.core.faces.FacesFunctionMapper.java

Source

/*
 * 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.
 */

package com.asual.summer.core.faces;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;

import javax.el.FunctionMapper;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * @author Rostislav Hristov
 *
 */
public class FacesFunctionMapper extends FunctionMapper {

    private final Log logger = LogFactory.getLog(getClass());

    private static HashMap<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>();

    private static ClassLoader classLoader = new ClassLoader() {

        protected Class<?> findClass(String name) throws ClassNotFoundException {
            if (classes.containsKey(name)) {
                byte[] bytes = ((MemoryJavaFileObject) classes.get(name)).baos.toByteArray();
                return defineClass(name, bytes, 0, bytes.length);
            }
            return Class.forName(name, true, getClass().getClassLoader());
        }
    };

    private class JavaObjectFromString extends SimpleJavaFileObject {

        private String contents = null;

        public JavaObjectFromString(String className, String contents) throws Exception {
            super(new URI(className + Kind.SOURCE.extension), Kind.SOURCE);
            this.contents = contents;
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return contents;
        }
    }

    private class MemoryJavaFileObject extends SimpleJavaFileObject {

        ByteArrayOutputStream baos;

        MemoryJavaFileObject(String name, Kind kind) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), kind);
        }

        public CharSequence getCharContent(boolean ignoreEncodingErrors)
                throws IOException, IllegalStateException, UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

        public InputStream openInputStream()
                throws IOException, IllegalStateException, UnsupportedOperationException {
            return new ByteArrayInputStream(baos.toByteArray());
        }

        public OutputStream openOutputStream()
                throws IOException, IllegalStateException, UnsupportedOperationException {
            return baos = new ByteArrayOutputStream();
        }
    }

    private class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {

        MemoryFileManager(JavaCompiler compiler) {
            super(compiler.getStandardFileManager(null, null, null));
        }

        public JavaFileObject getJavaFileForOutput(Location location, String name, Kind kind, FileObject sibling)
                throws java.io.IOException {
            JavaFileObject jfo = new MemoryJavaFileObject(name, kind);
            classes.put(name, jfo);
            return jfo;
        }
    }

    public Method resolveFunction(String namespace, final String fn) {

        try {

            String className = fn + "Script";

            if (!classes.containsKey(className)) {

                StringBuilder out = new StringBuilder();
                out.append("public class " + className + " {");
                out.append("   private static String fn = \"" + fn + "\";");
                out.append("   public static Object call(Object... args) throws Exception {");
                out.append("      return Class.forName(\"com.asual.summer.core.util.ScriptUtils\")");
                out.append(
                        "         .getDeclaredMethod(\"call\", String.class, Object[].class).invoke(null, fn, args);");
                out.append("   }");
                out.append("}");

                JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
                JavaFileManager jfm = new MemoryFileManager(compiler);
                JavaFileObject file = new JavaObjectFromString(className, out.toString());
                compiler.getTask(null, jfm, null, null, null, Arrays.asList(file)).call();
            }

            return Class.forName(className, true, classLoader).getDeclaredMethod("call", Object[].class);

        } catch (Exception e) {

            logger.error(e.getMessage(), e);
        }

        return null;
    }

}