You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2016/05/09 14:48:49 UTC

[30/35] karaf-boot git commit: Use stax for file generation

Use stax for file generation


Project: http://git-wip-us.apache.org/repos/asf/karaf-boot/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf-boot/commit/af6327ca
Tree: http://git-wip-us.apache.org/repos/asf/karaf-boot/tree/af6327ca
Diff: http://git-wip-us.apache.org/repos/asf/karaf-boot/diff/af6327ca

Branch: refs/heads/master
Commit: af6327ca53b12afc27e573aab9dce0ddc76d9a27
Parents: 5e0846f
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Mon Apr 25 18:30:19 2016 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Mon Apr 25 18:30:19 2016 +0200

----------------------------------------------------------------------
 samples/jpa/pom.xml                             |  33 ++--
 starters/karaf-boot-starter-jpa/pom.xml         |  61 +++---
 .../karaf/boot/jpa/impl/JpaProcessor.java       | 198 +++++++++++--------
 .../karaf/boot/jpa/impl/JpaProcessorTest.java   |  64 ++++++
 .../src/test/resources/expected_persistence.xml |  11 ++
 5 files changed, 241 insertions(+), 126 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/af6327ca/samples/jpa/pom.xml
----------------------------------------------------------------------
diff --git a/samples/jpa/pom.xml b/samples/jpa/pom.xml
index 032396f..1c51404 100644
--- a/samples/jpa/pom.xml
+++ b/samples/jpa/pom.xml
@@ -1,23 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<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/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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/xsd/maven-4.0.0.xsd">
+
+    <!-- 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. -->
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -41,6 +35,7 @@
                 <version>${project.version}</version>
                 <extensions>true</extensions>
             </plugin>
+
         </plugins>
     </build>
 

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/af6327ca/starters/karaf-boot-starter-jpa/pom.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/pom.xml b/starters/karaf-boot-starter-jpa/pom.xml
index c0ce5b8..734714b 100644
--- a/starters/karaf-boot-starter-jpa/pom.xml
+++ b/starters/karaf-boot-starter-jpa/pom.xml
@@ -1,23 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<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/xsd/maven-4.0.0.xsd">
+<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/xsd/maven-4.0.0.xsd">
 
-    <!--
-
-        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.
-    -->
+    <!-- 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. -->
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -32,15 +26,36 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>osgi.cmpn</artifactId>
-            <version>${osgi.version}</version>
-        </dependency>
-        <dependency>
             <groupId>org.apache.geronimo.specs</groupId>
             <artifactId>geronimo-jpa_2.0_spec</artifactId>
             <version>1.1</version>
         </dependency>
+        <!-- 
+        <dependency>
+            <groupId>net.java.dev.stax-utils</groupId>
+            <artifactId>stax-utils</artifactId>
+            <version>20070216</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jsr173-ri</artifactId>
+                    <groupId>com.bea.xml</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+         -->
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.12</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>1.10.19</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/af6327ca/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
index 4becbc2..ed52850 100644
--- a/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
+++ b/starters/karaf-boot-starter-jpa/src/main/java/org/apache/karaf/boot/jpa/impl/JpaProcessor.java
@@ -1,27 +1,26 @@
 package org.apache.karaf.boot.jpa.impl;
 
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Messager;
-import javax.annotation.processing.RoundEnvironment;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic.Kind;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.io.Writer;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
 import org.apache.karaf.boot.jpa.PersistentUnit;
 import org.apache.karaf.boot.jpa.Property;
 import org.apache.karaf.boot.jpa.Provider;
@@ -41,76 +40,93 @@ public class JpaProcessor extends AbstractProcessor {
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         Map<PersistentUnit, List<? extends AnnotationMirror>> units = new HashMap<PersistentUnit, List<? extends AnnotationMirror>>();
-
-
         for (Element elem : roundEnv.getElementsAnnotatedWith(PersistentUnit.class)) {
             PersistentUnit pu = elem.getAnnotation(PersistentUnit.class);
             units.put(pu, elem.getAnnotationMirrors());
         }
         if (!units.isEmpty()) {
             try {
-                Set<String> puNames = new HashSet<String>();
                 FileObject o = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT,
-                        "", "META-INF/persistence.xml");
-                PrintWriter w = new PrintWriter(o.openWriter());
-                w.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
-                w.println("<persistence version=\"2.0\" xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">");
-                for (PersistentUnit pu : units.keySet()) {
-                    if (pu.name() == null || pu.name().isEmpty()) {
-                        throw new IOException("Missing persistent unit name");
-                    }
-                    if (!puNames.add(pu.name())) {
-                        throw new IOException("Duplicate persistent unit name: " + pu.name());
-                    }
-                    w.println("    <persistence-unit name=\"" + pu.name() + "\" transaction-type=\"" + pu.transactionType().toString() + "\">");
-                    if (!pu.description().isEmpty()) {
-                        w.println("        <description>" + pu.description() + "</description>");
-                    }
-                    if (pu.provider() != Provider.Default || !pu.providerName().isEmpty()) {
-                        if (pu.provider() != Provider.Default && !pu.providerName().isEmpty()) {
-                            throw new IOException("At most one of provider and providerName can be used");
-                        }
-                        String name;
-                        if (!pu.providerName().isEmpty()) {
-                            name = pu.providerName();
-                        } else {
-                            switch (pu.provider()) {
-                                case Hibernate:
-                                    name = "org.hibernate.jpa.HibernatePersistenceProvider";
-                                    break;
-                                default:
-                                    // TODO
-                                    throw new IOException("Unsupported provider: " + pu.provider());
-                            }
-                        }
-                        w.println("        <provider>" + name + "</provider>");
-                    }
-                    if (!pu.jtaDataSource().isEmpty()) {
-                        w.println("        <jta-data-source>" + pu.jtaDataSource() + "</jta-data-source>");
-                    }
-                    if (!pu.nonJtaDataSource().isEmpty()) {
-                        w.println("        <non-jta-data-source>" + pu.nonJtaDataSource() + "</non-jta-data-source>");
-                    }
-                    if (pu.properties().length > 0) {
-                        w.println("        <properties>");
-                        for (Property property : pu.properties()) {
-                            w.println("            <property name=\"" + property.name() + "\" value=\"" + property.value() + "\"/>");
-                        }
+                                                                       "", "META-INF/persistence.xml");
+                process(o.openWriter(), units);
+                processingEnv.getMessager().printMessage(Kind.NOTE, "Generated META-INF/persistence.xml");
+            } catch (Exception e) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "Error: " + e.getMessage());
+            }
+        }
+        return true;
+    }
+
+    public void process(Writer writer, Map<PersistentUnit, List<? extends AnnotationMirror>> units) throws Exception {
+        Set<String> puNames = new HashSet<String>();
+        XMLOutputFactory xof =  XMLOutputFactory.newInstance();
+        //XMLStreamWriter w = new IndentingXMLStreamWriter(xof.createXMLStreamWriter(writer));
+        XMLStreamWriter w = xof.createXMLStreamWriter(writer);
+        w.setDefaultNamespace("http://java.sun.com/xml/ns/persistence");
+        w.writeStartDocument();
+        w.writeStartElement("persistence");
+        w.writeAttribute("verson", "2.0");
+        
+        //w.println("<persistence version=\"2.0\" xmlns=\"http://java.sun.com/xml/ns/persistence\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd\">");
+        for (PersistentUnit pu : units.keySet()) {
+            if (pu.name() == null || pu.name().isEmpty()) {
+                throw new IOException("Missing persistent unit name");
+            }
+            if (!puNames.add(pu.name())) {
+                throw new IOException("Duplicate persistent unit name: " + pu.name());
+            }
+            w.writeStartElement("persistence-unit");
+            w.writeAttribute("name", pu.name());
+            w.writeAttribute("transaction-type", pu.transactionType().toString());
+            writeElement(w, "description", pu.description());
+            String providerName = getProvider(pu);
+            writeElement(w, "provider", providerName);
+            writeElement(w, "jta-data-source", pu.jtaDataSource());
+            writeElement(w, "non-jta-data-source", pu.nonJtaDataSource());
+            Map<String, String> props = new HashMap<>();
+            addProperties(pu, props);
+            addAnnProperties(units.get(pu), props);
+            if (props.size() > 0) {
+                w.writeStartElement("properties");
+                for (String key : props.keySet()) {
+                    w.writeEmptyElement("property");
+                    w.writeAttribute("name", key);
+                    w.writeAttribute("value", props.get(key));
+                }
+                w.writeEndElement();
+            }
+            w.writeEndElement();
+        }
+        w.writeEndElement();
+        w.writeEndDocument();
+        w.flush();
+        w.close();
+    }
 
+    private void addProperties(PersistentUnit pu, Map<String, String> props) {
+        if (pu.properties() == null) {
+            return;
+        }
+        for (Property property : pu.properties()) {
+            props.put(property.name(), property.value());
+        }
+    }
 
-                        for (AnnotationMirror annMirror : units.get(pu)) {
+    private void addAnnProperties(List<? extends AnnotationMirror> annotations, Map<String, String> props)
+        throws XMLStreamException {
+        for (AnnotationMirror annMirror : annotations) {
 
-                            String name = null;
-                            for (AnnotationMirror a : processingEnv.getElementUtils().getAllAnnotationMirrors(annMirror.getAnnotationType().asElement())) {
-                                if (a.toString().startsWith("@org.apache.karaf.boot.jpa.PersistentUnit.ProviderProperty")) {
-                                    name = a.getElementValues().values().iterator().next().getValue().toString();
-                                    break;
-                                }
-                            }
-                            if (name != null) {
-                                String value = annMirror.getElementValues().values().iterator().next().getValue().toString();
-                                w.println("            <property name=\"" + name + "\" value=\"" + value + "\"/>");
-                            }
+            String name = null;
+            for (AnnotationMirror a : processingEnv.getElementUtils().getAllAnnotationMirrors(annMirror.getAnnotationType().asElement())) {
+                if (a.toString().startsWith("@org.apache.karaf.boot.jpa.PersistentUnit.ProviderProperty")) {
+                    name = a.getElementValues().values().iterator().next().getValue().toString();
+                    break;
+                }
+            }
+            if (name != null) {
+                String value = annMirror.getElementValues().values().iterator().next().getValue().toString();
+                props.put(name, value);
+            }
 //                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation: " + annMirror);
 //                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation type: " + annMirror.getAnnotationType());
 //                            processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation annot: " + annMirror.getAnnotationType().getAnnotationMirrors());
@@ -121,20 +137,34 @@ public class JpaProcessor extends AbstractProcessor {
 //                            } else {
 //                                processingEnv.getMessager().printMessage(Kind.MANDATORY_WARNING, "Annotation nok");
 //                            }
-                        }
+        }
+    }
 
-                        w.println("        </properties>");
-                    }
-                    w.println("    </persistence-unit>");
-                }
-                w.println("</persistence>");
-                w.close();
-                processingEnv.getMessager().printMessage(Kind.NOTE, "Generated META-INF/persistence.xml");
-            } catch (IOException e) {
-                processingEnv.getMessager().printMessage(Kind.ERROR, "Error: " + e.getMessage());
+    private void writeElement(XMLStreamWriter w, String localName, String content) throws XMLStreamException {
+        if (content != null && !content.isEmpty()) {
+            w.writeStartElement(localName);
+            w.writeCharacters(content);
+            w.writeEndElement();
+        }
+    }
+
+    private String getProvider(PersistentUnit pu) throws IOException {
+        if (pu.provider() != Provider.Default && pu.providerName() != null && !pu.providerName().isEmpty()) {
+            throw new IOException("At most one of provider and providerName can be used");
+        }
+        if (pu.provider() != null) {
+            switch (pu.provider()) {
+            case Hibernate:
+                return "org.hibernate.jpa.HibernatePersistenceProvider";
+            default:
+                // TODO
+                throw new IOException("Unsupported provider: " + pu.provider());
             }
+        } else if (pu.providerName() != null) {
+            return pu.providerName();
+        } else {
+            return null;
         }
-        return true;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/af6327ca/starters/karaf-boot-starter-jpa/src/test/java/org/apache/karaf/boot/jpa/impl/JpaProcessorTest.java
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/test/java/org/apache/karaf/boot/jpa/impl/JpaProcessorTest.java b/starters/karaf-boot-starter-jpa/src/test/java/org/apache/karaf/boot/jpa/impl/JpaProcessorTest.java
new file mode 100644
index 0000000..d3e683a
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/test/java/org/apache/karaf/boot/jpa/impl/JpaProcessorTest.java
@@ -0,0 +1,64 @@
+package org.apache.karaf.boot.jpa.impl;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.StringWriter;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.lang.model.element.AnnotationMirror;
+
+import org.apache.karaf.boot.jpa.PersistentUnit;
+import org.apache.karaf.boot.jpa.Property;
+import org.apache.karaf.boot.jpa.Provider;
+import org.apache.karaf.boot.jpa.TransactionType;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JpaProcessorTest {
+
+    @Ignore
+    @Test
+    public void testProcess() throws Exception {
+        JpaProcessor processor = new JpaProcessor();
+        Map<PersistentUnit, List<? extends AnnotationMirror>> units = new HashMap<>();
+        PersistentUnit pu = getTestPersitentUnit();
+        units.put(pu, Collections.emptyList());
+        URL url = this.getClass().getResource("/expected_persistence.xml");
+        byte[] encoded = Files.readAllBytes(new File(url.toURI()).toPath());
+        String expected = new String(encoded, Charset.forName("utf-8"));
+        StringWriter writer = new StringWriter();
+        processor.process(writer, units);
+        Assert.assertEquals(expected, writer.getBuffer().toString());
+    }
+
+    private PersistentUnit getTestPersitentUnit() {
+        PersistentUnit pu = mock(PersistentUnit.class);
+        when(pu.name()).thenReturn("test-pu");
+        when(pu.provider()).thenReturn(Provider.Hibernate);
+        when(pu.transactionType()).thenReturn(TransactionType.JTA);
+        when(pu.description()).thenReturn("Some description");
+        when(pu.jtaDataSource()).thenReturn("myds");
+        Property dialect = prop("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
+        Property[] props = new Property[] { dialect };
+        when(pu.properties()).thenReturn(props);
+        return pu;
+    }
+
+    private Property prop(String name, String value) {
+        Property dialect = mock(Property.class);
+        when(dialect.name()).thenReturn(name);
+        when(dialect.value()).thenReturn(value);
+        return dialect;
+    }
+    
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf-boot/blob/af6327ca/starters/karaf-boot-starter-jpa/src/test/resources/expected_persistence.xml
----------------------------------------------------------------------
diff --git a/starters/karaf-boot-starter-jpa/src/test/resources/expected_persistence.xml b/starters/karaf-boot-starter-jpa/src/test/resources/expected_persistence.xml
new file mode 100644
index 0000000..8002eba
--- /dev/null
+++ b/starters/karaf-boot-starter-jpa/src/test/resources/expected_persistence.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<persistence verson="2.0">
+  <persistence-unit name="test-pu" transaction-type="JTA">
+    <description>Some description</description>
+    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
+    <jta-data-source>myds</jta-data-source>
+    <properties>
+      <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
+    </properties>
+  </persistence-unit>
+</persistence>