1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender.db.jpa;
18
19 import java.lang.reflect.Constructor;
20 import javax.persistence.EntityManager;
21 import javax.persistence.EntityManagerFactory;
22 import javax.persistence.EntityTransaction;
23 import javax.persistence.Persistence;
24
25 import org.apache.logging.log4j.core.LogEvent;
26 import org.apache.logging.log4j.core.appender.ManagerFactory;
27 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
28
29
30
31
32 public final class JPADatabaseManager extends AbstractDatabaseManager {
33 private static final JPADatabaseManagerFactory FACTORY = new JPADatabaseManagerFactory();
34
35 private final String entityClassName;
36 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
37 private final String persistenceUnitName;
38
39 private EntityManager entityManager;
40 private EntityManagerFactory entityManagerFactory;
41 private EntityTransaction transaction;
42
43 private JPADatabaseManager(final String name, final int bufferSize,
44 final Class<? extends AbstractLogEventWrapperEntity> entityClass,
45 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
46 final String persistenceUnitName) {
47 super(name, bufferSize);
48 this.entityClassName = entityClass.getName();
49 this.entityConstructor = entityConstructor;
50 this.persistenceUnitName = persistenceUnitName;
51 }
52
53 @Override
54 protected void connectInternal() {
55 this.entityManagerFactory = Persistence.createEntityManagerFactory(this.persistenceUnitName);
56 this.entityManager = this.entityManagerFactory.createEntityManager();
57 this.transaction = this.entityManager.getTransaction();
58 }
59
60 @Override
61 protected void disconnectInternal() {
62 this.transaction = null;
63
64 if (this.entityManager != null && this.entityManager.isOpen()) {
65 this.entityManager.close();
66 }
67
68 if (this.entityManagerFactory != null && this.entityManagerFactory.isOpen()) {
69 this.entityManagerFactory.close();
70 }
71 }
72
73 @Override
74 protected void writeInternal(final LogEvent event) {
75 if (!this.isConnected() || this.transaction == null || this.entityManager == null
76 || this.entityManagerFactory == null) {
77 LOGGER.error("Cannot write logging event; manager [{}] not connected to the database.", this.getName());
78 return;
79 }
80
81 AbstractLogEventWrapperEntity entity;
82 try {
83 entity = this.entityConstructor.newInstance(event);
84 } catch (final Exception e) {
85 LOGGER.error("Failed to instantiate entity class {}.", this.entityClassName, e);
86 return;
87 }
88
89 try {
90 this.transaction.begin();
91 this.entityManager.persist(entity);
92 this.transaction.commit();
93 } catch (final Exception e) {
94 LOGGER.error("Failed to persist log event entity.", e);
95 this.transaction.rollback();
96 }
97 }
98
99
100
101
102
103
104
105
106
107
108
109
110 public static JPADatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
111 final Class<? extends AbstractLogEventWrapperEntity>
112 entityClass,
113 final Constructor<? extends AbstractLogEventWrapperEntity>
114 entityConstructor,
115 final String persistenceUnitName) {
116
117 return AbstractDatabaseManager.getManager(
118 name, new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY
119 );
120 }
121
122
123
124
125 private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
126 private final Class<? extends AbstractLogEventWrapperEntity> entityClass;
127 private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
128 private final String persistenceUnitName;
129
130 protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
131 final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
132 final String persistenceUnitName) {
133 super(bufferSize);
134
135 this.entityClass = entityClass;
136 this.entityConstructor = entityConstructor;
137 this.persistenceUnitName = persistenceUnitName;
138 }
139 }
140
141
142
143
144 private static final class JPADatabaseManagerFactory implements ManagerFactory<JPADatabaseManager, FactoryData> {
145 @Override
146 public JPADatabaseManager createManager(final String name, final FactoryData data) {
147 return new JPADatabaseManager(
148 name, data.getBufferSize(), data.entityClass, data.entityConstructor, data.persistenceUnitName
149 );
150 }
151 }
152 }