001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.appender.db.jpa;
018
019import java.util.Map;
020import javax.persistence.Basic;
021import javax.persistence.Convert;
022import javax.persistence.MappedSuperclass;
023import javax.persistence.Transient;
024
025import org.apache.logging.log4j.Level;
026import org.apache.logging.log4j.Marker;
027import org.apache.logging.log4j.ThreadContext;
028import org.apache.logging.log4j.core.LogEvent;
029import org.apache.logging.log4j.core.appender.db.jpa.converter.*;
030import org.apache.logging.log4j.core.impl.ThrowableProxy;
031import org.apache.logging.log4j.core.time.Instant;
032import org.apache.logging.log4j.message.Message;
033
034/**
035 * Users of the JPA appender may want to extend this class instead of {@link AbstractLogEventWrapperEntity}. This class
036 * implements all of the required mutator methods but does not implement a mutable entity ID property. In order to
037 * create an entity based on this class, you need only create two constructors matching this class's constructors,
038 * annotate the class {@link javax.persistence.Entity @Entity} and {@link javax.persistence.Table @Table}, and implement
039 * the fully mutable entity ID property annotated with {@link javax.persistence.Id @Id} and
040 * {@link javax.persistence.GeneratedValue @GeneratedValue} to tell the JPA provider how to calculate an ID for new
041 * events.<br>
042 * <br>
043 * The attributes in this entity use the default column names (which, according to the JPA spec, are the property names
044 * minus the "get" and "set" from the accessors/mutators). If you want to use different column names for one or more
045 * columns, override the necessary accessor methods defined in this class with the same annotations plus the
046 * {@link javax.persistence.Column @Column} annotation to specify the column name.<br>
047 * <br>
048 * The {@link #getContextMap()} and {@link #getContextStack()} attributes in this entity use the
049 * {@link ContextMapAttributeConverter} and {@link ContextStackAttributeConverter}, respectively. These convert the
050 * properties to simple strings that cannot be converted back to the properties. If you wish to instead convert these to
051 * a reversible JSON string, override these attributes with the same annotations but use the
052 * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter} and
053 * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter} instead.<br>
054 * <br>
055 * All other attributes in this entity use reversible converters that can be used for both persistence and retrieval. If
056 * there are any attributes you do not want persistent, you should override their accessor methods and annotate with
057 * {@link javax.persistence.Transient @Transient}.
058 *
059 * @see AbstractLogEventWrapperEntity
060 */
061@MappedSuperclass
062public abstract class BasicLogEventEntity extends AbstractLogEventWrapperEntity {
063    private static final long serialVersionUID = 1L;
064
065    /**
066     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
067     * signature. The no-argument constructor is required for a standards-compliant JPA provider to accept this as an
068     * entity.
069     */
070    public BasicLogEventEntity() {
071        super();
072    }
073
074    /**
075     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
076     * signature. This constructor is used for wrapping this entity around a logged event.
077     *
078     * @param wrappedEvent The underlying event from which information is obtained.
079     */
080    public BasicLogEventEntity(final LogEvent wrappedEvent) {
081        super(wrappedEvent);
082    }
083
084    /**
085     * Gets the level. Annotated with {@code @Basic} and {@code @Enumerated(EnumType.STRING)}.
086     *
087     * @return the level.
088     */
089    @Override
090    @Convert(converter = LevelAttributeConverter.class)
091    public Level getLevel() {
092        return this.getWrappedEvent().getLevel();
093    }
094
095    /**
096     * Gets the logger name. Annotated with {@code @Basic}.
097     *
098     * @return the logger name.
099     */
100    @Override
101    @Basic
102    public String getLoggerName() {
103        return this.getWrappedEvent().getLoggerName();
104    }
105
106    /**
107     * Gets the source location information. Annotated with
108     * {@code @Convert(converter = StackTraceElementAttributeConverter.class)}.
109     *
110     * @return the source location information.
111     * @see StackTraceElementAttributeConverter
112     */
113    @Override
114    @Convert(converter = StackTraceElementAttributeConverter.class)
115    public StackTraceElement getSource() {
116        return this.getWrappedEvent().getSource();
117    }
118
119    /**
120     * Gets the message. Annotated with {@code @Convert(converter = MessageAttributeConverter.class)}.
121     *
122     * @return the message.
123     * @see MessageAttributeConverter
124     */
125    @Override
126    @Convert(converter = MessageAttributeConverter.class)
127    public Message getMessage() {
128        return this.getWrappedEvent().getMessage();
129    }
130
131    /**
132     * Gets the marker. Annotated with {@code @Convert(converter = MarkerAttributeConverter.class)}.
133     *
134     * @return the marker.
135     * @see MarkerAttributeConverter
136     */
137    @Override
138    @Convert(converter = MarkerAttributeConverter.class)
139    public Marker getMarker() {
140        return this.getWrappedEvent().getMarker();
141    }
142
143    /**
144     * Gets the thread ID. Annotated with {@code @Basic}.
145     *
146     * @return the thread ID.
147     */
148    @Override
149    @Basic
150    public long getThreadId() {
151        return this.getWrappedEvent().getThreadId();
152    }
153
154    /**
155     * Gets the thread name. Annotated with {@code @Basic}.
156     *
157     * @return the thread name.
158     */
159    @Override
160    @Basic
161    public int getThreadPriority() {
162        return this.getWrappedEvent().getThreadPriority();
163    }
164
165    /**
166     * Gets the thread name. Annotated with {@code @Basic}.
167     *
168     * @return the thread name.
169     */
170    @Override
171    @Basic
172    public String getThreadName() {
173        return this.getWrappedEvent().getThreadName();
174    }
175
176    /**
177     * Gets the number of milliseconds since JVM launch. Annotated with {@code @Basic}.
178     *
179     * @return the number of milliseconds since JVM launch.
180     */
181    @Override
182    @Basic
183    public long getTimeMillis() {
184        return this.getWrappedEvent().getTimeMillis();
185    }
186
187    @Override
188    @Convert(converter = InstantAttributeConverter.class)
189    public Instant getInstant() {
190        return this.getWrappedEvent().getInstant();
191    }
192
193    /**
194     * Returns the value of the running Java Virtual Machine's high-resolution time source when this event was created,
195     * or a dummy value if it is known that this value will not be used downstream.
196     *
197     * @return the JVM nano time
198     */
199    @Override
200    @Basic
201    public long getNanoTime() {
202        return this.getWrappedEvent().getNanoTime();
203    }
204
205    /**
206     * Gets the exception logged. Annotated with {@code @Convert(converter = ThrowableAttributeConverter.class)}.
207     *
208     * @return the exception logged.
209     * @see ThrowableAttributeConverter
210     */
211    @Override
212    @Convert(converter = ThrowableAttributeConverter.class)
213    public Throwable getThrown() {
214        return this.getWrappedEvent().getThrown();
215    }
216
217    /**
218     * Gets the exception logged. Annotated with {@code @Convert(converter = ThrowableAttributeConverter.class)}.
219     *
220     * @return the exception logged.
221     * @see ThrowableAttributeConverter
222     */
223    @Override
224    @Transient
225    public ThrowableProxy getThrownProxy() {
226        return this.getWrappedEvent().getThrownProxy();
227    }
228
229    /**
230     * Gets the context map. Annotated with {@code @Convert(converter = ContextMapAttributeConverter.class)}.
231     *
232     * @return the context map.
233     * @see ContextMapAttributeConverter
234     * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter
235     */
236    @SuppressWarnings("deprecation")
237    @Override
238    @Convert(converter = ContextMapAttributeConverter.class)
239    public Map<String, String> getContextMap() {
240        return this.getWrappedEvent().getContextMap();
241    }
242
243    /**
244     * Gets the context stack. Annotated with {@code @Convert(converter = ContextStackAttributeConverter.class)}.
245     *
246     * @return the context stack.
247     * @see ContextStackAttributeConverter
248     * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter
249     */
250    @Override
251    @Convert(converter = ContextStackAttributeConverter.class)
252    public ThreadContext.ContextStack getContextStack() {
253        return this.getWrappedEvent().getContextStack();
254    }
255
256    /**
257     * Gets the fully qualified class name of the caller of the logger API. Annotated with {@code @Basic}.
258     *
259     * @return the fully qualified class name of the caller of the logger API.
260     */
261    @Override
262    @Basic
263    public String getLoggerFqcn() {
264        return this.getWrappedEvent().getLoggerFqcn();
265    }
266}