Processor allows only primitive types and String as its values model
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 20 Feb 2013 18:14:59 +0100
branchmodel
changeset 7690c0fe97fe0c7
parent 768 e320d8156140
child 770 26513bd377b9
Processor allows only primitive types and String as its values
javaquery/api/pom.xml
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java
javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageTest.java
     1.1 --- a/javaquery/api/pom.xml	Tue Feb 19 16:16:22 2013 +0100
     1.2 +++ b/javaquery/api/pom.xml	Wed Feb 20 18:14:59 2013 +0100
     1.3 @@ -19,8 +19,8 @@
     1.4                  <artifactId>maven-compiler-plugin</artifactId>
     1.5                  <version>2.3.2</version>
     1.6                  <configuration>
     1.7 -                    <source>1.6</source>
     1.8 -                    <target>1.6</target>
     1.9 +                    <source>1.7</source>
    1.10 +                    <target>1.7</target>
    1.11                  </configuration>
    1.12              </plugin>
    1.13          </plugins>
     2.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Tue Feb 19 16:16:22 2013 +0100
     2.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Wed Feb 20 18:14:59 2013 +0100
     2.3 @@ -501,30 +501,46 @@
     2.4              ret = tm.toString();
     2.5          }
     2.6          if (p.array()) {
     2.7 -            if (ret.equals("byte")) {
     2.8 -                return Byte.class.getName();
     2.9 -            }
    2.10 -            if (ret.equals("short")) {
    2.11 -                return Short.class.getName();
    2.12 -            }
    2.13 -            if (ret.equals("char")) {
    2.14 -                return Character.class.getName();
    2.15 -            }
    2.16 -            if (ret.equals("int")) {
    2.17 -                return Integer.class.getName();
    2.18 -            }
    2.19 -            if (ret.equals("long")) {
    2.20 -                return Long.class.getName();
    2.21 -            }
    2.22 -            if (ret.equals("float")) {
    2.23 -                return Float.class.getName();
    2.24 -            }
    2.25 -            if (ret.equals("double")) {
    2.26 -                return Double.class.getName();
    2.27 +            String bt = findBoxedType(ret);
    2.28 +            if (bt != null) {
    2.29 +                return bt;
    2.30              }
    2.31          }
    2.32 +        if ("java.lang.String".equals(ret)) {
    2.33 +            return ret;
    2.34 +        }
    2.35 +        String bt = findBoxedType(ret);
    2.36 +        if (bt != null) {
    2.37 +            return ret;
    2.38 +        }
    2.39 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Only primitive types supported in the mapping. Not " + ret);
    2.40          return ret;
    2.41      }
    2.42 +    
    2.43 +    private static String findBoxedType(String ret) {
    2.44 +        if (ret.equals("byte")) {
    2.45 +            return Byte.class.getName();
    2.46 +        }
    2.47 +        if (ret.equals("short")) {
    2.48 +            return Short.class.getName();
    2.49 +        }
    2.50 +        if (ret.equals("char")) {
    2.51 +            return Character.class.getName();
    2.52 +        }
    2.53 +        if (ret.equals("int")) {
    2.54 +            return Integer.class.getName();
    2.55 +        }
    2.56 +        if (ret.equals("long")) {
    2.57 +            return Long.class.getName();
    2.58 +        }
    2.59 +        if (ret.equals("float")) {
    2.60 +            return Float.class.getName();
    2.61 +        }
    2.62 +        if (ret.equals("double")) {
    2.63 +            return Double.class.getName();
    2.64 +        }
    2.65 +        return null;
    2.66 +    }
    2.67  
    2.68      private boolean verifyPropName(Element e, String propName, Property[] existingProps) {
    2.69          StringBuilder sb = new StringBuilder();
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java	Wed Feb 20 18:14:59 2013 +0100
     3.3 @@ -0,0 +1,203 @@
     3.4 +/**
     3.5 + * Back 2 Browser Bytecode Translator
     3.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU General Public License
    3.18 + * along with this program. Look for COPYING file in the top folder.
    3.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    3.20 + */
    3.21 +package org.apidesign.bck2brwsr.htmlpage;
    3.22 +
    3.23 +import java.io.ByteArrayInputStream;
    3.24 +import java.io.ByteArrayOutputStream;
    3.25 +import java.io.IOException;
    3.26 +import java.io.InputStream;
    3.27 +import java.io.OutputStream;
    3.28 +import java.net.URI;
    3.29 +import java.net.URISyntaxException;
    3.30 +import java.util.ArrayList;
    3.31 +import java.util.Arrays;
    3.32 +import java.util.HashMap;
    3.33 +import java.util.List;
    3.34 +import java.util.Map;
    3.35 +import java.util.regex.Matcher;
    3.36 +import java.util.regex.Pattern;
    3.37 +import javax.tools.Diagnostic;
    3.38 +import javax.tools.DiagnosticListener;
    3.39 +import javax.tools.FileObject;
    3.40 +import javax.tools.ForwardingJavaFileManager;
    3.41 +import javax.tools.JavaFileManager;
    3.42 +import javax.tools.JavaFileObject;
    3.43 +import javax.tools.JavaFileObject.Kind;
    3.44 +import javax.tools.SimpleJavaFileObject;
    3.45 +import javax.tools.StandardJavaFileManager;
    3.46 +import javax.tools.StandardLocation;
    3.47 +import javax.tools.ToolProvider;
    3.48 +
    3.49 +/**
    3.50 + *
    3.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    3.52 + */
    3.53 +final class Compile implements DiagnosticListener<JavaFileObject> {
    3.54 +    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
    3.55 +    private final Map<String, byte[]> classes;
    3.56 +    private final String pkg;
    3.57 +    private final String cls;
    3.58 +    private final String html;
    3.59 +
    3.60 +    private Compile(String html, String code) throws IOException {
    3.61 +        this.pkg = findPkg(code);
    3.62 +        this.cls = findCls(code);
    3.63 +        this.html = html;
    3.64 +        classes = compile(html, code);
    3.65 +    }
    3.66 +
    3.67 +    /** Performs compilation of given HTML page and associated Java code
    3.68 +     */
    3.69 +    public static Compile create(String html, String code) throws IOException {
    3.70 +        return new Compile(html, code);
    3.71 +    }
    3.72 +    
    3.73 +    /** Checks for given class among compiled resources */
    3.74 +    public byte[] get(String res) {
    3.75 +        return classes.get(res);
    3.76 +    }
    3.77 +    
    3.78 +    /** Obtains errors created during compilation.
    3.79 +     */
    3.80 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
    3.81 +        List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
    3.82 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
    3.83 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
    3.84 +                err.add(diagnostic);
    3.85 +            }
    3.86 +        }
    3.87 +        return err;
    3.88 +    }
    3.89 +    
    3.90 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
    3.91 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
    3.92 +
    3.93 +        final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
    3.94 +
    3.95 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
    3.96 +            @Override
    3.97 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
    3.98 +                return code;
    3.99 +            }
   3.100 +        };
   3.101 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
   3.102 +            @Override
   3.103 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   3.104 +                return html;
   3.105 +            }
   3.106 +
   3.107 +            @Override
   3.108 +            public InputStream openInputStream() throws IOException {
   3.109 +                return new ByteArrayInputStream(html.getBytes());
   3.110 +            }
   3.111 +        };
   3.112 +        
   3.113 +        final URI scratch;
   3.114 +        try {
   3.115 +            scratch = new URI("mem://mem3");
   3.116 +        } catch (URISyntaxException ex) {
   3.117 +            throw new IOException(ex);
   3.118 +        }
   3.119 +        
   3.120 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
   3.121 +            @Override
   3.122 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
   3.123 +                if (kind  == Kind.CLASS) {
   3.124 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
   3.125 +
   3.126 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
   3.127 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
   3.128 +                        @Override
   3.129 +                        public OutputStream openOutputStream() throws IOException {
   3.130 +                            return buffer;
   3.131 +                        }
   3.132 +                    };
   3.133 +                }
   3.134 +                
   3.135 +                if (kind == Kind.SOURCE) {
   3.136 +                    return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
   3.137 +                        private final ByteArrayOutputStream data = new ByteArrayOutputStream();
   3.138 +                        @Override
   3.139 +                        public OutputStream openOutputStream() throws IOException {
   3.140 +                            return data;
   3.141 +                        }
   3.142 +
   3.143 +                        @Override
   3.144 +                        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   3.145 +                            data.close();
   3.146 +                            return new String(data.toByteArray());
   3.147 +                        }
   3.148 +                    };
   3.149 +                }
   3.150 +                
   3.151 +                throw new IllegalStateException();
   3.152 +            }
   3.153 +
   3.154 +            @Override
   3.155 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
   3.156 +                if (location == StandardLocation.SOURCE_PATH) {
   3.157 +                    if (packageName.equals(pkg)) {
   3.158 +                        return htmlFile;
   3.159 +                    }
   3.160 +                }
   3.161 +                
   3.162 +                return null;
   3.163 +            }
   3.164 +            
   3.165 +        };
   3.166 +
   3.167 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
   3.168 +
   3.169 +        Map<String, byte[]> result = new HashMap<>();
   3.170 +
   3.171 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
   3.172 +            result.put(e.getKey(), e.getValue().toByteArray());
   3.173 +        }
   3.174 +
   3.175 +        return result;
   3.176 +    }
   3.177 +
   3.178 +
   3.179 +    @Override
   3.180 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   3.181 +        errors.add(diagnostic);
   3.182 +    }
   3.183 +    private static String findPkg(String java) throws IOException {
   3.184 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
   3.185 +        Matcher m = p.matcher(java);
   3.186 +        if (!m.find()) {
   3.187 +            throw new IOException("Can't find package declaration in the java file");
   3.188 +        }
   3.189 +        String pkg = m.group(1);
   3.190 +        return pkg;
   3.191 +    }
   3.192 +    private static String findCls(String java) throws IOException {
   3.193 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
   3.194 +        Matcher m = p.matcher(java);
   3.195 +        if (!m.find()) {
   3.196 +            throw new IOException("Can't find package declaration in the java file");
   3.197 +        }
   3.198 +        String cls = m.group(1);
   3.199 +        return cls;
   3.200 +    }
   3.201 +
   3.202 +    String getHtml() {
   3.203 +        String fqn = "'" + pkg + '.' + cls + "'";
   3.204 +        return html.replace("'${fqn}'", fqn);
   3.205 +    }
   3.206 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageTest.java	Wed Feb 20 18:14:59 2013 +0100
     4.3 @@ -0,0 +1,50 @@
     4.4 +/**
     4.5 + * Back 2 Browser Bytecode Translator
     4.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 + *
     4.8 + * This program is free software: you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License as published by
    4.10 + * the Free Software Foundation, version 2 of the License.
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU General Public License
    4.18 + * along with this program. Look for COPYING file in the top folder.
    4.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    4.20 + */
    4.21 +package org.apidesign.bck2brwsr.htmlpage;
    4.22 +
    4.23 +import java.io.IOException;
    4.24 +import java.util.Locale;
    4.25 +import static org.testng.Assert.*;
    4.26 +import org.testng.annotations.Test;
    4.27 +
    4.28 +/** Verify errors emitted by the processor.
    4.29 + *
    4.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.31 + */
    4.32 +public class PageTest {
    4.33 +    @Test public void verifyWrongType() throws IOException {
    4.34 +        String html = "<html><body>"
    4.35 +            + "</body></html>";
    4.36 +        String code = "package x.y.z;\n"
    4.37 +            + "import org.apidesign.bck2brwsr.htmlpage.api.*;\n"
    4.38 +            + "@Page(xhtml=\"index.xhtml\", className=\"Model\", properties={\n"
    4.39 +            + "  @Property(name=\"prop\", type=Runnable.class)\n"
    4.40 +            + "})\n"
    4.41 +            + "class X {\n"
    4.42 +            + "}\n";
    4.43 +        
    4.44 +        Compile c = Compile.create(html, code);
    4.45 +        assertEquals(c.getErrors().size(), 1, "One error: " + c.getErrors());
    4.46 +        
    4.47 +        String msg = c.getErrors().get(0).getMessage(Locale.ENGLISH);
    4.48 +        if (!msg.contains("Runnable")) {
    4.49 +            fail("Should contain warning about Runnable: " + msg);
    4.50 +        }
    4.51 +    }
    4.52 +    
    4.53 +}