Bug 433205 - Canonical Model Generator is too verbose, no way to disable output

Signed-off-by: Tomas Kraus <tomas.kraus@oracle.com>
Reviewed-by: Lukas Jungmann <lukas.jungmann@oracle.com>
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogCategory.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogCategory.java
index 61d260c..e4921a6 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogCategory.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogCategory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016  Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018  Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -15,6 +15,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+
 /**
  * EclipseLink categories used for logging name space.
  * The EclipseLink categories for the logging name space are:<br>
@@ -56,14 +58,15 @@ public enum LogCategory {
     METAMODEL(  (byte)0x0A, SessionLog.METAMODEL),
     MISC(       (byte)0x0B, SessionLog.MISC),
     MONITORING( (byte)0x0C, SessionLog.MONITORING),
-    PROPAGATION((byte)0x0D, SessionLog.PROPAGATION),
-    PROPERTIES( (byte)0x0E, SessionLog.PROPERTIES),
-    QUERY(      (byte)0x0F, SessionLog.QUERY),
-    SEQUENCING( (byte)0x10, SessionLog.SEQUENCING),
-    SERVER(     (byte)0x11, SessionLog.SERVER),
-    SQL(        (byte)0x12, SessionLog.SQL),
-    TRANSACTION((byte)0x13, SessionLog.TRANSACTION),
-    WEAVER(     (byte)0x14, SessionLog.WEAVER);
+    PROCESSOR(  (byte)0x0D, SessionLog.PROCESSOR),
+    PROPAGATION((byte)0x0E, SessionLog.PROPAGATION),
+    PROPERTIES( (byte)0x0F, SessionLog.PROPERTIES),
+    QUERY(      (byte)0x10, SessionLog.QUERY),
+    SEQUENCING( (byte)0x11, SessionLog.SEQUENCING),
+    SERVER(     (byte)0x12, SessionLog.SERVER),
+    SQL(        (byte)0x13, SessionLog.SQL),
+    TRANSACTION((byte)0x14, SessionLog.TRANSACTION),
+    WEAVER(     (byte)0x15, SessionLog.WEAVER);
 
     /** Logging categories enumeration length. */
     public static final int length = LogCategory.values().length;
@@ -77,6 +80,9 @@ public enum LogCategory {
     /** Logger name spaces lookup table. */
     private static final String[] nameSpaces = new String[length];
 
+    /** Logger name spaces lookup table. */
+    private static final String[] levelNameSpaces = new String[length];
+
     static {
         // Initialize String to LogCategory case insensitive lookup Map.
         for (LogCategory category : LogCategory.values()) {
@@ -84,7 +90,8 @@ public enum LogCategory {
         }
         // Initialize logger name spaces lookup table.
         for (LogCategory category : LogCategory.values()) {
-            nameSpaces[category.id] = NAMESPACE_PREFIX + category.name;
+            nameSpaces[category.id] = (NAMESPACE_PREFIX + category.name).intern();
+            levelNameSpaces[category.id] = (PersistenceUnitProperties.CATEGORY_LOGGING_LEVEL_ + category.name).intern();
         }
     }
 
@@ -139,4 +146,12 @@ public String getNameSpace() {
         return nameSpaces[id];
     }
 
+    /**
+     * Get log level property name for this logging category.
+     * @return Log level property name for this logging category.
+     */
+    public String getLogLevelProperty() {
+        return levelNameSpaces[id];
+    }
+
 }
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogLevel.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogLevel.java
index 9a0b91b..49e9147 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogLevel.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/LogLevel.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016  Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018  Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -104,6 +104,22 @@ public static final LogLevel toValue(final String name) {
     }
 
     /**
+     * Returns {@link LogLevel} object holding the value of the specified {@link String}.
+     * @param name The {@link String} to be parsed.
+     * @param fallBack {@link LogLevel} object to return on ID lookup failure.
+     * @return {@link LogLevel} object holding the value represented by the string argument or {@code fallBack} when
+     *         there exists no corresponding {@link LogLevel} object to provided argument value.
+     */
+    public static final LogLevel toValue(final String name, final LogLevel fallBack) {
+        if (name != null) {
+            final LogLevel level = stringValuesMap.get(name.toUpperCase());
+            return level != null ? level : fallBack;
+        } else {
+            return fallBack;
+        }
+    }
+
+    /**
      * Returns {@link LogLevel} object holding the value of the specified {@link LogLevel} ID.
      * @param id {@link LogLevel} ID.
      * @return {@link LogLevel} object holding the value represented by the {@code id} argument.
diff --git a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/SessionLog.java b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/SessionLog.java
index 6345713..891e838 100644
--- a/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/SessionLog.java
+++ b/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/logging/SessionLog.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -51,6 +51,7 @@
  * <tr><td>&nbsp;</td><td>{@link #METADATA}</td>      <td>&nbsp;</td><td>= {@value #METADATA} </td></tr>
  * <tr><td>&nbsp;</td><td>{@link #METAMODEL}</td>     <td>&nbsp;</td><td>= {@value #METAMODEL}</td></tr>
  * <tr><td>&nbsp;</td><td>{@link #MOXY}</td>          <td>&nbsp;</td><td>= {@value #MOXY}</td></tr>
+ * <tr><td>&nbsp;</td><td>{@link #PROCESSOR}</td>     <td>&nbsp;</td><td>= {@value #PROCESSOR}</td></tr>
  * <tr><td>&nbsp;</td><td>{@link #PROPAGATION}</td>   <td>&nbsp;</td><td>= {@value #PROPAGATION}</td></tr>
  * <tr><td>&nbsp;</td><td>{@link #PROPERTIES}</td>    <td>&nbsp;</td><td>= {@value #PROPERTIES}</td></tr>
  * <tr><td>&nbsp;</td><td>{@link #QUERY}</td>         <td>&nbsp;</td><td>= {@value #QUERY}</td></tr>
@@ -130,6 +131,8 @@ public interface SessionLog extends Cloneable {
     public static final String DDL = "ddl";
     public static final String DBWS = "dbws";
     public static final String JPARS = "jpars";
+    /** ModelGen logging name space. */
+    public static final String PROCESSOR = "processor";
 
     public final String[] loggerCatagories = new String[] {
         SQL,
@@ -152,7 +155,8 @@ public interface SessionLog extends Cloneable {
         WEAVER,
         PROPERTIES,
         SERVER,
-        DDL
+        DDL,
+        PROCESSOR
     };
 
     /**
@@ -300,6 +304,7 @@ public interface SessionLog extends Cloneable {
      * <tr><td>&nbsp;</td><td>{@link #JPARS}</td>           <td>&nbsp;</td><td>= {@value #JPARS}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #METAMODEL}</td>       <td>&nbsp;</td><td>= {@value #METAMODEL}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #MOXY}</td>            <td>&nbsp;</td><td>= {@value #MOXY}</td></tr>
+     * <tr><td>&nbsp;</td><td>{@link #PROCESSOR}</td>       <td>&nbsp;</td><td>= {@value #PROCESSOR}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPAGATION}</td>     <td>&nbsp;</td><td>= {@value #PROPAGATION}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPERTIES}</td>      <td>&nbsp;</td><td>= {@value #PROPERTIES}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #QUERY}</td>           <td>&nbsp;</td><td>= {@value #QUERY}</td></tr>
@@ -361,6 +366,7 @@ public interface SessionLog extends Cloneable {
      * <tr><td>&nbsp;</td><td>{@link #JPARS}</td>           <td>&nbsp;</td><td>= {@value #JPARS}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #METAMODEL}</td>       <td>&nbsp;</td><td>= {@value #METAMODEL}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #MOXY}</td>            <td>&nbsp;</td><td>= {@value #MOXY}</td></tr>
+     * <tr><td>&nbsp;</td><td>{@link #PROCESSOR}</td>       <td>&nbsp;</td><td>= {@value #PROCESSOR}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPAGATION}</td>     <td>&nbsp;</td><td>= {@value #PROPAGATION}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPERTIES}</td>      <td>&nbsp;</td><td>= {@value #PROPERTIES}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #QUERY}</td>           <td>&nbsp;</td><td>= {@value #QUERY}</td></tr>
@@ -423,6 +429,7 @@ public interface SessionLog extends Cloneable {
      * <tr><td>&nbsp;</td><td>{@link #JPARS}</td>           <td>&nbsp;</td><td>= {@value #JPARS}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #METAMODEL}</td>       <td>&nbsp;</td><td>= {@value #METAMODEL}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #MOXY}</td>            <td>&nbsp;</td><td>= {@value #MOXY}</td></tr>
+     * <tr><td>&nbsp;</td><td>{@link #PROCESSOR}</td>       <td>&nbsp;</td><td>= {@value #PROCESSOR}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPAGATION}</td>     <td>&nbsp;</td><td>= {@value #PROPAGATION}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #PROPERTIES}</td>      <td>&nbsp;</td><td>= {@value #PROPERTIES}</td></tr>
      * <tr><td>&nbsp;</td><td>{@link #QUERY}</td>           <td>&nbsp;</td><td>= {@value #QUERY}</td></tr>
diff --git a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/modelgen/TestProcessor.java b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/modelgen/TestProcessor.java
index c0b3c8c..6fa483f 100644
--- a/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/modelgen/TestProcessor.java
+++ b/jpa/eclipselink.jpa.test.jse/src/org/eclipse/persistence/jpa/test/modelgen/TestProcessor.java
@@ -25,8 +25,10 @@
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.StandardOpenOption;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 import javax.persistence.Entity;
 import javax.tools.Diagnostic;
@@ -88,18 +90,129 @@ public void testProc() throws Exception {
         TestFO generated9 = new TestFO("org.Gen9",
                 "package org; @javax.annotation.processing.Generated(\"com.example.Generator\") public class Gen9 { public  Gen9() {} public int getZ() {return 9*42;}}");
         CompilationTask task = compiler.getTask(new PrintWriter(System.out), sfm, diagnostics,
-                Arrays.asList("-proc:only"), null,
+                Arrays.asList("-proc:only", "-Aeclipselink.logging.level.processor=OFF", "-Aeclipselink.canonicalmodel.use_static_factory=false"), null,
                 Arrays.asList(entity, nonEntity, generated8, generated9));
         CanonicalModelProcessor modelProcessor = new CanonicalModelProcessor();
         task.setProcessors(Collections.singleton(modelProcessor));
         task.call();
-        
+
         for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
             System.out.println(diagnostic);
         }
         Assert.assertTrue("Model file not generated", new File(srcOut, "org/Sample_.java").exists());
     }
 
+    @Test
+    public void testProcessorLoggingOffFromCmdLine() throws Exception {
+        verifyLogging("testProcessorLoggingOffFromCmdLine", PXML, false,
+                "-Aeclipselink.logging.level.processor=OFF");
+    }
+
+    @Test
+    public void testGlobalLoggingOffFromCmdLine() throws Exception {
+        verifyLogging("testGlobalLoggingOffFromCmdLine", PXML, false,
+                "-Aeclipselink.logging.level=OFF");
+    }
+
+    @Test
+    public void testProcessorLoggingOffFromPU() throws Exception {
+        final String pu = buildPU("testProcessorLoggingOffFromPU",
+                new Property("eclipselink.logging.level.processor", "OFF"));
+        // Turning logging off from PU can't remove messages logged before PU properties are processed.
+        verifyLogging("testProcessorLoggingOffFromPU", pu, true);
+    }
+
+    @Test
+    public void testGlobalLoggingOffFromPU() throws Exception {
+        final String pu = buildPU("testGlobalLoggingOffFromPU",
+                new Property("eclipselink.logging.level", "OFF"));
+        // Turning logging off from PU can't remove messages logged before PU properties are processed.
+        verifyLogging("testGlobalLoggingOffFromPU", pu, true);
+    }
+
+    @Test
+    public void testProcessorLoggingFinestFromCmdLine() throws Exception {
+        verifyLogging("testProcessorLoggingFinestFromCmdLine", PXML, true,
+                "-Aeclipselink.logging.level.processor=FINEST");
+    }
+
+    @Test
+    public void testGlobalLoggingFinestFromCmdLine() throws Exception {
+        verifyLogging("testGlobalLoggingFinestFromCmdLine", PXML, true,
+                "-Aeclipselink.logging.level=FINEST");
+    }
+
+    @Test
+    public void testProcessorLoggingFinestFromPU() throws Exception {
+        final String pu = buildPU("testProcessorLoggingFinestFromPU",
+                new Property("eclipselink.logging.level.processor", "FINEST"));
+        verifyLogging("testProcessorLoggingFinestFromPU", pu, true);
+    }
+
+    @Test
+    public void testGlobalLoggingFinestFromPU() throws Exception {
+        final String pu = buildPU("testGlobalLoggingFinestFromPU",
+                new Property("eclipselink.logging.level", "FINEST"));
+        verifyLogging("testGlobalLoggingFinestFromPU", pu, true);
+    }
+
+    /**
+     * Verify logging output suppression
+     * @param testName name of the test
+     * @param pu persistence unit {@code String}
+     * @param whether there should be logging messages in the output or not
+     * @param options compiler options
+     * @throws Exception
+     */
+    private void verifyLogging(final String testName, final String pu, final boolean haveMsgs, final String... options) throws Exception {
+        File runDir = new File(System.getProperty("run.dir"), testName);
+        File srcOut = new File(runDir, "src");
+        srcOut.mkdirs();
+        File cpDir = new File(runDir, "cp");
+        cpDir.mkdirs();
+        File pxml = new File(cpDir, "META-INF/persistence.xml");
+        pxml.getParentFile().mkdirs();
+        try (BufferedWriter writer = Files.newBufferedWriter(pxml.toPath(), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)) {
+            writer.write(pu, 0, pu.length());
+        } catch (IOException x) {
+            throw x;
+        }
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
+
+        StandardJavaFileManager sfm = compiler.getStandardFileManager(diagnostics, null, null);
+        URL apiUrl = Entity.class.getProtectionDomain().getCodeSource().getLocation();
+        sfm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(new File(apiUrl.getFile()), cpDir));
+        sfm.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(srcOut));
+        sfm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(cpDir));
+
+        TestFO entity = new TestFO("org.Sample",
+                "package org; import javax.persistence.Entity; @Entity public class Sample { public  Sample() {} public int getX() {return 1;}}");
+
+        List<String> optionsList = new ArrayList<>(options != null ? options.length + 2 : 2);
+        optionsList.add("-proc:only");
+        optionsList.add("-Aeclipselink.canonicalmodel.use_static_factory=false");
+        for (String option : options) {
+            optionsList.add(option);
+        }
+
+        CompilationTask task = compiler.getTask(
+                new PrintWriter(System.out), sfm, diagnostics, optionsList, null,
+                Arrays.asList(entity));
+        CanonicalModelProcessor modelProcessor = new CanonicalModelProcessor();
+        task.setProcessors(Collections.singleton(modelProcessor));
+        task.call();
+
+        for ( Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
+            System.out.println(diagnostic);
+        }
+        if (haveMsgs) {
+            Assert.assertFalse("Log messages should be generated", diagnostics.getDiagnostics().isEmpty());
+        } else {
+            Assert.assertTrue("No log message should be generated", diagnostics.getDiagnostics().isEmpty());
+        }
+    }
+
     private static class TestFO extends SimpleJavaFileObject {
         private final String text;
 
@@ -117,17 +230,74 @@ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
 
     private static final String PXML = "<persistence xmlns=\"http://xmlns.jcp.org/xml/ns/persistence\"\n" + 
             "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + 
-            "  xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/persistence\n" + 
-            "    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd\"\n" + 
-            "  version=\"2.2\">\n" + 
-            "     <persistence-unit name=\"sample-pu\" transaction-type=\"RESOURCE_LOCAL\">\n" + 
-            "          <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>\n" + 
-            "          <exclude-unlisted-classes>false</exclude-unlisted-classes>\n" + 
-            "          <properties>\n" + 
-            "          </properties>\n" + 
-            "     </persistence-unit>\n" + 
+            "  xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/persistence\n" +
+            "    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd\"\n" +
+            "  version=\"2.2\">\n" +
+            "     <persistence-unit name=\"sample-pu\" transaction-type=\"RESOURCE_LOCAL\">\n" +
+            "          <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>\n" +
+            "          <exclude-unlisted-classes>false</exclude-unlisted-classes>\n" +
+            "          <properties>\n" +
+            "          </properties>\n" +
+            "     </persistence-unit>\n" +
             "</persistence>";
-    
+
+    private static final String PXML_LOG_BEG =
+            "<persistence xmlns=\"http://xmlns.jcp.org/xml/ns/persistence\"\n" +
+            "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+            "  xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/persistence\n" +
+            "    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd\"\n" +
+            "  version=\"2.2\">\n" +
+            "     <persistence-unit name=\"";
+
+    private static final String PXML_LOG_MID =
+            "\" transaction-type=\"RESOURCE_LOCAL\">\n" +
+            "          <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>\n" +
+            "          <exclude-unlisted-classes>false</exclude-unlisted-classes>\n" +
+            "          <properties>\n";
+
+    private static final String PXML_LOG_END =
+            "          </properties>\n" +
+            "     </persistence-unit>\n" +
+            "</persistence>";
+
+    /**
+     * Simple property holding class.
+     */
+    private static final class Property {
+        private final String name;
+        private final String value;
+        private Property(final String name, final String value) {
+            this.name = name;
+            this.value = value;
+        }
+    }
+
+    /**
+     * Builds persistence unit with properties.
+     * @param name persistence unit name
+     * @param properties properties to be added to persistence unit
+     * @return persistence unit with specified properties
+     */
+    private static String buildPU(final String name, Property ... properties) {
+        int len = PXML_LOG_BEG.length() + PXML_LOG_MID.length() + PXML_LOG_END.length() + name.length();
+        for (Property property : properties) {
+            len += property.name.length() + property.value.length() + 43;
+        }
+        final StringBuilder sb = new StringBuilder(len);
+        sb.append(PXML_LOG_BEG);
+        sb.append(name);
+        sb.append(PXML_LOG_MID);
+        for (Property property : properties) {
+            sb.append("              <property name=\"");
+            sb.append(property.name);
+            sb.append("\" value=\"");
+            sb.append(property.value);
+            sb.append("\"/>\n");
+        }
+        sb.append(PXML_LOG_END);
+        return sb.toString();
+    }
+
     private static void delete(File dir) throws IOException {
         Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>() {
             @Override
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProcessor.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProcessor.java
index 6524cea..a4b943b 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProcessor.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProcessor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -25,15 +25,17 @@
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.modelgen;
 
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PREFIX;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUFFIX;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUB_PACKAGE;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_LOAD_XML;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY_DEFAULT;
+import static org.eclipse.persistence.config.PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML;
 import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP;
 import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP_DEFAULT;
-import static org.eclipse.persistence.config.PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_GLOBAL_LOG_LEVEL;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_LOAD_XML;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PREFIX;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PROCESSOR_LOG_LEVEL;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUB_PACKAGE;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUFFIX;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_USE_STATIC_FACTORY_DEFAULT;
 
 import java.io.IOException;
 import java.io.Writer;
@@ -70,6 +72,8 @@
 import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnit;
 import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnitReader;
 import org.eclipse.persistence.internal.jpa.modelgen.visitors.TypeVisitor;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
 import org.eclipse.persistence.sessions.DatabaseLogin;
 import org.eclipse.persistence.sessions.Project;
 import org.eclipse.persistence.sessions.server.ServerSession;
@@ -86,7 +90,9 @@
         CANONICAL_MODEL_LOAD_XML,
         CANONICAL_MODEL_USE_STATIC_FACTORY,
         CANONICAL_MODEL_GENERATE_TIMESTAMP,
-        ECLIPSELINK_PERSISTENCE_XML})
+        ECLIPSELINK_PERSISTENCE_XML,
+        CANONICAL_MODEL_PROCESSOR_LOG_LEVEL,
+        CANONICAL_MODEL_GLOBAL_LOG_LEVEL})
 @SupportedAnnotationTypes({"javax.persistence.*", "org.eclipse.persistence.annotations.*"})
 public class CanonicalModelProcessor extends AbstractProcessor {
     protected enum AttributeType {CollectionAttribute, ListAttribute, MapAttribute, SetAttribute, SingularAttribute }
@@ -240,7 +246,9 @@ protected void generateCanonicalModelClasses(MetadataMirrorFactory factory, Pers
             MetadataClass roundClass = roundElements.get(roundElement);
 
             if (persistenceUnit.containsClass(roundClass)) {
-                //processingEnv.getMessager().printMessage(Kind.NOTE, "Generating class: " + element);
+                if (factory.getLogger().shouldLog(LogLevel.FINEST, LogCategory.PROCESSOR)) {
+                    processingEnv.getMessager().printMessage(Kind.NOTE, "Generating class: " + roundClass.getName());
+                }
                 generateCanonicalModelClass(roundClass, roundElement, persistenceUnit);
             }
         }
@@ -355,9 +363,8 @@ public SourceVersion getSupportedSourceVersion() {
     @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         if (! roundEnv.processingOver() && ! roundEnv.errorRaised()) {
+            MetadataMirrorFactory factory = null;
             try {
-                MetadataMirrorFactory factory;
-
                 if (Boolean.valueOf(CanonicalModelProperties.getOption(CANONICAL_MODEL_USE_STATIC_FACTORY, CANONICAL_MODEL_USE_STATIC_FACTORY_DEFAULT, processingEnv.getOptions()))) {
                     if (staticFactory == null) {
                         // We must remember some state from one round to another.
@@ -369,22 +376,42 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
                         // persistence unit. Doing this is going to need careful
                         // cleanup thoughts though. Adding classes ok, but what
                         // about removing some?
-                        MetadataLogger logger = new MetadataLogger(new ServerSession(new Project(new DatabaseLogin())));
-                        staticFactory = new MetadataMirrorFactory(logger, Thread.currentThread().getContextClassLoader());
-                        processingEnv.getMessager().printMessage(Kind.NOTE, "Creating static metadata factory ...");
+                        final MetadataLogger logger = new MetadataLogger(new ServerSession(new Project(new DatabaseLogin())));
+                        staticFactory = new MetadataMirrorFactory(logger,
+                                LoggerContext.buildContext(processingEnv.getOptions()),
+                                Thread.currentThread().getContextClassLoader());
+                        staticFactory.getLoggerContext().updateMetadataLogger(logger);
+                        if (logger.shouldLog(LogLevel.INFO, LogCategory.PROCESSOR)) {
+                            processingEnv.getMessager().printMessage(Kind.NOTE, "Creating static metadata factory ...");
+                        }
                     }
 
                     factory = staticFactory;
                 } else {
                     if (nonStaticFactory == null) {
-                        MetadataLogger logger = new MetadataLogger(new ServerSession(new Project(new DatabaseLogin())));
-                        nonStaticFactory = new MetadataMirrorFactory(logger, Thread.currentThread().getContextClassLoader());
-                        processingEnv.getMessager().printMessage(Kind.NOTE, "Creating non-static metadata factory ...");
+                        final MetadataLogger logger = new MetadataLogger(new ServerSession(new Project(new DatabaseLogin())));
+                        nonStaticFactory = new MetadataMirrorFactory(logger,
+                                LoggerContext.buildContext(processingEnv.getOptions()),
+                                Thread.currentThread().getContextClassLoader());
+                        nonStaticFactory.getLoggerContext().updateMetadataLogger(logger);
+                        if (logger.shouldLog(LogLevel.INFO, LogCategory.PROCESSOR)) {
+                            processingEnv.getMessager().printMessage(Kind.NOTE, "Creating non-static metadata factory ...");
+                        }
                     }
 
                     factory = nonStaticFactory;
                 }
 
+                final MetadataLogger logger = factory.getLogger();
+                final LoggerContext logCtx = factory.getLoggerContext();
+
+                // Log processing environment options
+                if (logger.shouldLog(LogLevel.CONFIG, LogCategory.PROCESSOR)) {
+                    for (String optionKey : processingEnv.getOptions().keySet()) {
+                        processingEnv.getMessager().printMessage(Kind.OTHER, "Found Option : " + optionKey + ", with value: " + processingEnv.getOptions().get(optionKey));
+                    }
+                }
+
                 // Step 1 - The factory is passed around so those who want the
                 // processing or round env can get it off the factory. This
                 // saves us from having to pass around multiple objects.
@@ -396,11 +423,19 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
                 // created and override existing ones (causing them to be un-
                 // pre-processed. We can never tell what changes in XML so we
                 // have to do this.
-                PersistenceUnitReader puReader = new PersistenceUnitReader(factory);
+                final PersistenceUnitReader puReader = new PersistenceUnitReader(logger, processingEnv);
+                puReader.initPersistenceUnits(factory);
 
                 // Step 3 - iterate over all the persistence units and generate
                 // their canonical model classes.
-                for (PersistenceUnit persistenceUnit : puReader.getPersistenceUnits()) {
+                for (PersistenceUnit persistenceUnit : factory.getPersistenceUnits()) {
+
+                    // Update log level using PU property when no command line logging level option is set
+                    final boolean updateLogger = logger != null && !logCtx.isAny();
+                    if (updateLogger) {
+                        LoggerContext.updateMetadataLogger(logger, persistenceUnit);
+                    }
+
                     // Step 3a - add the Entities not defined in XML that are
                     // being compiled.
                     for (Element element : roundEnv.getElementsAnnotatedWith(Entity.class)) {
@@ -424,9 +459,16 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
 
                     // Step 3e - We're set, generate the canonical model classes.
                     generateCanonicalModelClasses(factory, persistenceUnit);
+
+                    if (updateLogger) {
+                        logCtx.updateMetadataLogger(logger);
+                    }
                 }
             } catch (Exception e) {
-                processingEnv.getMessager().printMessage(Kind.ERROR, e.toString());
+                final MetadataLogger logger = (factory != null) ? factory.getLogger() : null;
+                if (logger == null || logger.shouldLog(LogLevel.SEVERE, LogCategory.PROCESSOR)) {
+                    processingEnv.getMessager().printMessage(Kind.ERROR, e.toString());
+                }
                 throw new RuntimeException(e);
             }
         }
@@ -473,4 +515,5 @@ protected String writeImportStatements(HashMap<String, String> typeImports, Clas
         writer.append("\n");
         return parentCanonicalName;
     }
+
 }
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProperties.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProperties.java
index 5336924..521c8d8 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProperties.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/CanonicalModelProperties.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -87,6 +87,17 @@ public abstract class CanonicalModelProperties {
     public static final String CANONICAL_MODEL_GENERATE_TIMESTAMP = PersistenceUnitProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP;
     public static final String CANONICAL_MODEL_GENERATE_TIMESTAMP_DEFAULT = PersistenceUnitProperties.CANONICAL_MODEL_GENERATE_TIMESTAMP_DEFAULT;
 
+    // This value must match LogCategory.PROCESSOR.getLogLevelProperty()
+    /**
+     * This optional property can be used to set processor logging level of Canonical model generator.
+     */
+    public static final String CANONICAL_MODEL_PROCESSOR_LOG_LEVEL = PersistenceUnitProperties.CATEGORY_LOGGING_LEVEL_ + "processor";
+
+    /**
+     * This optional property can be used to set global logging level of Canonical model generator.
+     */
+    public static final String CANONICAL_MODEL_GLOBAL_LOG_LEVEL = PersistenceUnitProperties.LOGGING_LEVEL;
+
     /**
      * INTERNAL:
      */
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/LoggerContext.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/LoggerContext.java
new file mode 100644
index 0000000..f83bb13
--- /dev/null
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/LoggerContext.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     02/22/2018-3.0 Tomas Kraus
+ *       - 433205: Canonical Model Generator is too verbose, no way to disable output
+ ******************************************************************************/
+package org.eclipse.persistence.internal.jpa.modelgen;
+
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_GLOBAL_LOG_LEVEL;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PROCESSOR_LOG_LEVEL;
+
+import java.util.Map;
+
+import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
+import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnit;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
+
+/**
+ * Logger options context.
+ */
+class LoggerContext {
+
+    /**
+     * Builds logger options context from options {@code Map}.
+     *
+     * @param options options {@code Map} with logging level options
+     * @return logger options context with values based on options {@code Map}
+     */
+    static LoggerContext buildContext(final Map<String,String> options) {
+        final String glob = options.get(CANONICAL_MODEL_GLOBAL_LOG_LEVEL);
+        final String proc = options.get(CANONICAL_MODEL_PROCESSOR_LOG_LEVEL);
+        return new LoggerContext(
+                glob != null, LogLevel.toValue(glob, LogLevel.INFO),
+                proc != null, LogLevel.toValue(proc, LogLevel.INFO));
+    }
+
+    /**
+     * Update provided {@link MetadataLogger} log level settings from PU property.
+     * Logger is updated only when {@code PROCESSOR} logging category level
+     * is set properly in corresponding PU property.
+     *
+     * @param logger logger to be updated
+     * @param persistenceUnit persistence unit with properties
+     */
+    static void updateMetadataLogger(final MetadataLogger logger, final PersistenceUnit persistenceUnit) {
+        String levelStr = persistenceUnit.getPersistenceUnitProperty(LogCategory.PROCESSOR.getLogLevelProperty());
+        if (levelStr == null) {
+            levelStr = persistenceUnit.getPersistenceUnitProperty(CANONICAL_MODEL_GLOBAL_LOG_LEVEL);
+        }
+        if (levelStr != null) {
+            final LogLevel level = LogLevel.toValue(levelStr);
+            if (level != null) {
+                logger.getSession().getSessionLog().setLevel(level.getId(), LogCategory.PROCESSOR.getName());
+            }
+        }
+    }
+
+    /** Holds an information whether global logging level option is set. */
+    private final boolean isGlobal;
+
+    /** Global logging level determined from options. Value from option or default value. */
+    private final LogLevel global;
+
+    /** Holds an information whether processor logging level option is set. */
+    private final boolean isProcessor;
+
+    /** Processor logging level determined from options. Value from option or default value. */
+    private final LogLevel processor;
+
+    /**
+     * Creates an instance of logger options context.
+     *
+     * @param isGlobal whether global logging level option is set
+     * @param global logging level determined from options
+     * @param isProcessor whether processor logging level option is set
+     * @param processor logging level determined from options
+     */
+    private LoggerContext(final boolean isGlobal, final LogLevel global, final boolean isProcessor, final LogLevel processor) {
+        this.isGlobal = isGlobal;
+        this.global = global;
+        this.isProcessor = isProcessor;
+        this.processor = processor;
+    }
+
+    /**
+     * Get an information whether global logging level option is set.
+     *
+     * @return value of {@code true} when global logging level option is set or {@code true} otherwise.
+     */
+    boolean isGlobal() {
+        return isGlobal;
+    }
+
+    /**
+     * Get global logging level.
+     *
+     * @return global logging level determined from options
+     */
+    LogLevel getGlobal() {
+        return global;
+    }
+
+    /**
+     * Get an information whether processor logging level option is set.
+     *
+     * @return value of {@code true} when processor logging level option is set or {@code true} otherwise.
+     */
+    boolean isProcessor() {
+        return isProcessor;
+    }
+
+    /**
+     * Get processor logging level.
+     *
+     * @return processor logging level determined from options
+     */
+    LogLevel getProcessor() {
+        return processor;
+    }
+
+    /**
+     * Get an information whether any logging level option is set (at least one from global and processor).
+     *
+     * @return value of {@code true} when at least one logging level option is set or {@code true} otherwise.
+     */
+    boolean isAny() {
+        return isGlobal || isProcessor;
+    }
+
+    /**
+     * Update {@link MetadataLogger} instance using values from this logger options context.
+     *
+     * @param logger {@link MetadataLogger} instance to update
+     */
+    void updateMetadataLogger(final MetadataLogger logger) {
+        if (isProcessor || !isGlobal) {
+            logger.getSession().getSessionLog().setLevel(processor.getId(), LogCategory.PROCESSOR.getName());
+        } else {
+            logger.getSession().getSessionLog().setLevel(global.getId(), LogCategory.PROCESSOR.getName());
+        }
+        logger.getSession().getSessionLog().setLevel(global.getId());
+    }
+
+}
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/MetadataMirrorFactory.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/MetadataMirrorFactory.java
index 775be2c..58a2ad5 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/MetadataMirrorFactory.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/MetadataMirrorFactory.java
@@ -49,7 +49,8 @@
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataFactory;
 import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnit;
 import org.eclipse.persistence.internal.jpa.modelgen.visitors.ElementVisitor;
-import org.eclipse.persistence.logging.SessionLog;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
 import org.eclipse.persistence.sessions.DatabaseLogin;
 import org.eclipse.persistence.sessions.Project;
 import org.eclipse.persistence.sessions.server.ServerSession;
@@ -80,6 +81,9 @@ public class MetadataMirrorFactory extends MetadataFactory {
 
     private ProcessingEnvironment processingEnv;
 
+    /** Current logger context from command line options. */
+    private final LoggerContext loggerContext;
+
     /**
      * INTERNAL:
      * The factory is kept as a static object to the persistence unit. The first
@@ -89,12 +93,13 @@ public class MetadataMirrorFactory extends MetadataFactory {
      * classes and may not be able to rebuild till individual elements are
      * 'touched' or if the project is rebuilt as a whole.
      */
-    protected MetadataMirrorFactory(MetadataLogger logger, ClassLoader loader) {
+    protected MetadataMirrorFactory(final MetadataLogger logger, final LoggerContext loggerContext, final ClassLoader loader) {
         super(logger, loader);
-        roundElements = new HashMap<Element, MetadataClass>();
-        roundMetadataClasses = new HashSet<MetadataClass>();
-        persistenceUnits = new HashMap<String, PersistenceUnit>();
-        metadataProjects = new HashMap<String, MetadataProject>();
+        this.loggerContext = loggerContext;
+        roundElements = new HashMap<>();
+        roundMetadataClasses = new HashSet<>();
+        persistenceUnits = new HashMap<>();
+        metadataProjects = new HashMap<>();
     }
 
     /**
@@ -124,11 +129,10 @@ public MetadataClass getMetadataClass(Element element) {
 
         if (metadataClass == null) {
             // Only log if logging on finest.
-            boolean shouldLog = getLogger().getSession().getLogLevel() == SessionLog.FINEST;
             // As a performance gain, avoid visiting this class if it is not a
             // round element. We must re-visit round elements.
             if (isRoundElement(element)) {
-                if (shouldLog) {
+                if (m_logger.shouldLog(LogLevel.FINE, LogCategory.PROCESSOR)) {
                     processingEnv.getMessager().printMessage(Kind.NOTE, "Building metadata class for round element: " + element);
                 }
                 metadataClass = new MetadataClass(MetadataMirrorFactory.this, "");
@@ -159,7 +163,7 @@ public MetadataClass getMetadataClass(Element element) {
                 //    with only a name/type from the toString value.
                 if (element instanceof TypeElement || element instanceof TypeParameterElement) {
                     if (element instanceof TypeElement) {
-                        if (shouldLog) {
+                        if (m_logger.shouldLog(LogLevel.FINE, LogCategory.PROCESSOR)) {
                             processingEnv.getMessager().printMessage(Kind.NOTE, "Building metadata class for type element: " + name);
                         }
                         metadataClass = new MetadataClass(MetadataMirrorFactory.this, name);
@@ -170,7 +174,7 @@ public MetadataClass getMetadataClass(Element element) {
                         // Only thing going to get through at this point are
                         // TypeParameterElements (presumably generic ones). Look
                         // at those further since they 'should' be simple visits.
-                        if (shouldLog) {
+                        if (m_logger.shouldLog(LogLevel.FINE, LogCategory.PROCESSOR)) {
                             processingEnv.getMessager().printMessage(Kind.NOTE, "Building type parameter element: " + name);
                         }
                         metadataClass = new MetadataClass(MetadataMirrorFactory.this, name);
@@ -290,6 +294,14 @@ public boolean isRoundElement(MetadataClass cls) {
 
     /**
      * INTERNAL:
+     * Get current logger context from command line options.
+     */
+    public LoggerContext getLoggerContext() {
+        return loggerContext;
+    }
+
+    /**
+     * INTERNAL:
      */
     @Override
     public void resolveGenericTypes(MetadataClass child, List<String> genericTypes, MetadataClass parent, MetadataDescriptor descriptor) {
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnit.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnit.java
index 72dc65f..f8e48b3 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnit.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnit.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -27,6 +27,13 @@
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.modelgen.objects;
 
+import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_EMBEDDABLE;
+import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY;
+import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_MAPPED_SUPERCLASS;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PREFIX;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUB_PACKAGE;
+import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUFFIX;
+
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -51,17 +58,10 @@
 import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
 import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappingsReader;
 import org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory;
-import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnitReader;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
 import org.eclipse.persistence.oxm.XMLContext;
 
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUB_PACKAGE;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_PREFIX;
-import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_SUFFIX;
-
-import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_EMBEDDABLE;
-import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY;
-import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_MAPPED_SUPERCLASS;
-
 /**
  * A representation of a persistence unit definition.
  *
@@ -262,7 +262,9 @@ protected void addXMLEntityMappings(String mappingFile, XMLContext context) {
                 // For eclipselink-orm merging and overriding these need to be set.
                 entityMappings.setIsEclipseLinkORMFile(mappingFile.equals(MetadataHelper.ECLIPSELINK_ORM_FILE));
                 entityMappings.setMappingFile(mappingFile);
-                processingEnv.getMessager().printMessage(Kind.NOTE, "File loaded : " + mappingFile + ", is eclipselink-orm file: " + entityMappings.isEclipseLinkORMFile());
+                if (factory.getLogger().shouldLog(LogLevel.INFO, LogCategory.PROCESSOR)) {
+                    processingEnv.getMessager().printMessage(Kind.NOTE, "File loaded : " + mappingFile + ", is eclipselink-orm file: " + entityMappings.isEclipseLinkORMFile());
+                }
                 xmlEntityMappings.add(entityMappings);
             } finally {
                 persistenceUnitReader.closeInputStream(inputStream);
@@ -357,6 +359,22 @@ public String getQualifiedCanonicalName(String qualifiedName) {
 
     /**
      * INTERNAL:
+     * Get persistence unit property value by name.
+     *
+     * @param name persistence unit property name
+     * @return persistence unit property value
+     */
+    public String getPersistenceUnitProperty(final String name) {
+        Object objVal = persistenceUnitProperties.get(name);
+        if (objVal instanceof String) {
+            return String.class.cast(objVal);
+        } else {
+            return objVal != null ? objVal.toString() : null;
+        }
+    }
+
+    /**
+     * INTERNAL:
      */
     public void initPersistenceUnitProperties() {
         persistenceUnitProperties = new HashMap<String, Object>();
@@ -366,7 +384,9 @@ public void initPersistenceUnitProperties() {
         // named properties.
         for (SEPersistenceUnitProperty property : persistenceUnitInfo.getPersistenceUnitProperties()) {
             if (property.getName() != null) {
-                //processingEnv.getMessager().printMessage(Kind.NOTE, "Key: " + property.getName() + " , value: " + property.getValue());
+                if (factory.getLogger().shouldLog(LogLevel.FINE, LogCategory.PROCESSOR)) {
+                    processingEnv.getMessager().printMessage(Kind.NOTE, "Key: " + property.getName() + " , value: " + property.getValue());
+                }
                 persistenceUnitProperties.put(property.getName(), property.getValue());
             }
         }
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnitReader.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnitReader.java
index a065311..b3b04d5 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnitReader.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/objects/PersistenceUnitReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -21,32 +21,31 @@
  ******************************************************************************/
 package org.eclipse.persistence.internal.jpa.modelgen.objects;
 
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.StringTokenizer;
-
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.tools.FileObject;
-import javax.tools.StandardLocation;
-import javax.tools.Diagnostic.Kind;
-
-import org.eclipse.persistence.config.PersistenceUnitProperties;
-import org.eclipse.persistence.exceptions.ValidationException;
-import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
-import org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties;
-import org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory;
-import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceUnit;
-import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceXML;
-import org.eclipse.persistence.internal.jpa.modelgen.objects.PersistenceXMLMappings;
-
 import static org.eclipse.persistence.config.PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML_DEFAULT;
 import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_LOAD_XML;
 import static org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties.CANONICAL_MODEL_LOAD_XML_DEFAULT;
 
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.eclipse.persistence.exceptions.ValidationException;
+import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
+import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
+import org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProperties;
+import org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
+
 /**
  * Used to read persistence units through the java annotation processing API.
  *
@@ -54,23 +53,18 @@
  * @since EclipseLink 1.2
  */
 public class PersistenceUnitReader {
-    protected MetadataMirrorFactory factory;
-    protected ProcessingEnvironment processingEnv;
+
+    /** Current logger. */
+    protected final MetadataLogger logger;
+    /** Annotation model processing environment. */
+    protected final ProcessingEnvironment processingEnv;
 
     /**
      * INTERNAL:
      */
-    public PersistenceUnitReader(MetadataMirrorFactory factory) throws IOException {
-        this.factory = factory;
-        processingEnv = factory.getProcessingEnvironment();
-
-        // As a performance enhancement to avoid reloading and merging XML
-        // metadata for every compile round, the user may choose to turn off
-        // the XML loading by setting the load XML flag to false.
-        if (Boolean.valueOf(CanonicalModelProperties.getOption(CANONICAL_MODEL_LOAD_XML, CANONICAL_MODEL_LOAD_XML_DEFAULT, processingEnv.getOptions()))) {
-            // after initializing our member variables, initialize the pu's.
-            initPersistenceUnits();
-        }
+    public PersistenceUnitReader(final MetadataLogger logger, final ProcessingEnvironment processingEnv) throws IOException {
+        this.logger = logger;
+        this.processingEnv = processingEnv;
     }
 
     /**
@@ -112,10 +106,15 @@ protected InputStream getInputStream(String filename, boolean loadingPersistence
             } catch (IOException e) {
                 if (loadingPersistenceXML) {
                     // If loading the persistence.xml, log a BIG warning message.
-                    processingEnv.getMessager().printMessage(Kind.NOTE, "The persistence xml file ["+filename+"] was not found. NO GENERATION will occur!! Please ensure a persistence xml file is available either from the CLASS_OUTPUT directory [META-INF/persistence.xml] or using the eclipselink.persistencexml property to specify its location. ");
+                    if (logger.shouldLog(LogLevel.WARNING, LogCategory.PROCESSOR)) {
+                        processingEnv.getMessager().printMessage(Kind.NOTE, "The persistence xml file [" + filename
+                                + "] was not found. NO GENERATION will occur!! Please ensure a persistence xml file is available either from the CLASS_OUTPUT directory [META-INF/persistence.xml] or using the eclipselink.persistencexml property to specify its location.");
+                    }
                 } else {
                     // For any other mapping file log a message.
-                    processingEnv.getMessager().printMessage(Kind.NOTE, "Optional file was not found: " + filename + " continuing with generation.");
+                    if (logger.shouldLog(LogLevel.INFO, LogCategory.PROCESSOR)) {
+                        processingEnv.getMessager().printMessage(Kind.NOTE, "Optional file was not found: " + filename + " continuing with generation.");
+                    }
                 }
             }
         }
@@ -148,53 +147,50 @@ protected HashSet<String> getPersistenceUnitList(ProcessingEnvironment processin
     /**
      * INTERNAL:
      */
-    public Collection<PersistenceUnit> getPersistenceUnits() {
-        return factory.getPersistenceUnits();
-    }
+    public void initPersistenceUnits(final MetadataMirrorFactory factory) {
+        // As a performance enhancement to avoid reloading and merging XML metadata for every compile round,
+        // the user may choose to turn off the XML loading by setting the load XML flag to false.
+        if (Boolean.valueOf(CanonicalModelProperties.getOption(CANONICAL_MODEL_LOAD_XML, CANONICAL_MODEL_LOAD_XML_DEFAULT, processingEnv.getOptions()))) {
+            final String filename = CanonicalModelProperties.getOption(ECLIPSELINK_PERSISTENCE_XML, ECLIPSELINK_PERSISTENCE_XML_DEFAULT, processingEnv.getOptions());
+            HashSet<String> persistenceUnitList = getPersistenceUnitList(processingEnv);
 
-    /**
-     * INTERNAL:
-     */
-    protected void initPersistenceUnits() {
-        for (String optionKey : processingEnv.getOptions().keySet()) {
-            processingEnv.getMessager().printMessage(Kind.OTHER, "Found Option : " + optionKey + ", with value: " + processingEnv.getOptions().get(optionKey));
-        }
+            InputStream inStream1 = null;
+            InputStream inStream2 = null;
 
-        String filename = CanonicalModelProperties.getOption(ECLIPSELINK_PERSISTENCE_XML, ECLIPSELINK_PERSISTENCE_XML_DEFAULT, processingEnv.getOptions());
-        HashSet<String> persistenceUnitList = getPersistenceUnitList(processingEnv);
+            try {
+                inStream1 = getInputStream(filename, true);
 
-        InputStream inStream1 = null;
-        InputStream inStream2 = null;
+                // If the persistence.xml was not found, then there is nothing
+                // to do.
+                if (inStream1 != null) {
+                    PersistenceXML persistenceXML;
 
-        try {
-            inStream1 = getInputStream(filename, true);
+                    try {
+                        // Try a 2.1 context first.
+                        persistenceXML = (PersistenceXML) PersistenceXMLMappings.createXML2_1Context().createUnmarshaller().unmarshal(inStream1);
+                    } catch (Exception e) {
+                        // Catch all exceptions and try a 2.0 context second
+                        // with a new input stream.
+                        inStream2 = getInputStream(filename, true);
+                        persistenceXML = (PersistenceXML) PersistenceXMLMappings.createXML2_0Context().createUnmarshaller().unmarshal(inStream2);
+                    }
 
-            // If the persistence.xml was not found, then there is nothing to do.
-            if (inStream1 != null) {
-                PersistenceXML persistenceXML;
-
-                try {
-                    // Try a 2.1 context first.
-                    persistenceXML = (PersistenceXML) PersistenceXMLMappings.createXML2_1Context().createUnmarshaller().unmarshal(inStream1);
-                } catch (Exception e) {
-                    // Catch all exceptions and try a 2.0 context second with a new input stream.
-                    inStream2 = getInputStream(filename, true);
-                    persistenceXML = (PersistenceXML) PersistenceXMLMappings.createXML2_0Context().createUnmarshaller().unmarshal(inStream2);
-                }
-
-                for (SEPersistenceUnitInfo puInfo : persistenceXML.getPersistenceUnitInfos()) {
-                    // If no persistence unit list has been specified or one
-                    // has been specified and this persistence unit info's name
-                    // appears in that list then add it.
-                    if (persistenceUnitList == null || persistenceUnitList.contains(puInfo.getPersistenceUnitName())) {
-                        factory.addPersistenceUnit(puInfo, new PersistenceUnit(puInfo, factory, this));
+                    for (SEPersistenceUnitInfo puInfo : persistenceXML.getPersistenceUnitInfos()) {
+                        // If no persistence unit list has been specified or one
+                        // has been specified and this persistence unit info's
+                        // name
+                        // appears in that list then add it.
+                        if (persistenceUnitList == null || persistenceUnitList.contains(puInfo.getPersistenceUnitName())) {
+                            factory.addPersistenceUnit(puInfo, new PersistenceUnit(puInfo, factory, this));
+                        }
                     }
                 }
+            } finally {
+                closeInputStream(inStream1);
+                closeInputStream(inStream2);
             }
-        } finally {
-            closeInputStream(inStream1);
-            closeInputStream(inStream2);
         }
     }
+
 }
 
diff --git a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/visitors/ElementVisitor.java b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/visitors/ElementVisitor.java
index e92f9a6..8723631 100644
--- a/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/visitors/ElementVisitor.java
+++ b/jpa/org.eclipse.persistence.jpa.modelgen/src/org/eclipse/persistence/internal/jpa/modelgen/visitors/ElementVisitor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -37,12 +37,15 @@
 import javax.tools.Diagnostic.Kind;
 
 import org.eclipse.persistence.internal.helper.Helper;
+import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotatedElement;
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataField;
 import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataMethod;
 import org.eclipse.persistence.internal.jpa.modelgen.MetadataMirrorFactory;
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
 
 /**
  * An element visitor.
@@ -190,7 +193,10 @@ public MetadataMethod visitExecutable(ExecutableElement executableElement, Metad
      */
     @Override
     public MetadataClass visitPackage(PackageElement packageElement, MetadataClass metadataClass) {
-        processingEnv.getMessager().printMessage(Kind.NOTE, "ElementVisitor Package NOT IMPLEMENTED : " + packageElement);
+        MetadataLogger logger = ((MetadataMirrorFactory) metadataClass.getMetadataFactory()).getLogger();
+        if (logger.shouldLog(LogLevel.FINE, LogCategory.PROCESSOR)) {
+            processingEnv.getMessager().printMessage(Kind.NOTE, "ElementVisitor Package NOT IMPLEMENTED : " + packageElement);
+        }
         return null;
     }
 
@@ -199,8 +205,10 @@ public MetadataClass visitPackage(PackageElement packageElement, MetadataClass m
      */
     @Override
     public MetadataClass visitType(TypeElement typeElement, MetadataClass metadataClass) {
-        //processingEnv.getMessager().printMessage(Kind.NOTE, "Visiting class: " + typeElement);
         MetadataMirrorFactory factory = ((MetadataMirrorFactory) metadataClass.getMetadataFactory());
+        if (factory.getLogger().shouldLog(LogLevel.FINEST, LogCategory.PROCESSOR)) {
+            processingEnv.getMessager().printMessage(Kind.NOTE, "Visiting class: " + typeElement);
+        }
 
         // Set the qualified name.
         metadataClass.setName(typeElement.getQualifiedName().toString());
diff --git a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/MetadataLogger.java b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/MetadataLogger.java
index d8800cc..cdfc25a 100644
--- a/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/MetadataLogger.java
+++ b/jpa/org.eclipse.persistence.jpa/src/org/eclipse/persistence/internal/jpa/metadata/MetadataLogger.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -60,6 +60,8 @@
 
 import org.eclipse.persistence.exceptions.ValidationException;
 
+import org.eclipse.persistence.logging.LogCategory;
+import org.eclipse.persistence.logging.LogLevel;
 import org.eclipse.persistence.logging.SessionLog;
 import org.eclipse.persistence.internal.sessions.AbstractSession;
 
@@ -534,6 +536,18 @@ public AbstractSession getSession() {
 
     /**
      * INTERNAL:
+     * Check if a message of the given {@link LogLevel} and {@link LogCategory} would actually be logged.
+     *
+     * @param level the log request level value
+     * @param category an EclipseLink logging category
+     * @return value of {@code true} if the given message level will be logged or {@code false} otherwise
+     */
+    public boolean shouldLog(final LogLevel level, final LogCategory category) {
+        return m_session.shouldLog(level.getId(), category.getName());
+    }
+
+    /**
+     * INTERNAL:
      * Set the session to log to.
      */
     public void setSession(AbstractSession session) {