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     */
017    package org.apache.logging.log4j.core.impl;
018    
019    import java.io.Serializable;
020    
021    /**
022     * Wraps and extends the concept of the JRE's final class {@link StackTraceElement} by adding more location information.
023     * <p>
024     * Complements a StackTraceElement with:
025     * </p>
026     * <ul>
027     * <li>exact: whether the class was obtained via {@link sun.reflect.Reflection#getCallerClass(int)}</li>
028     * <li>location: a classpath element or a jar</li>
029     * <li>version</li>
030     * </ul>
031     */
032    public final class ExtendedStackTraceElement implements Serializable {
033    
034        private static final long serialVersionUID = -2171069569241280505L;
035    
036        private final ExtendedClassInfo extraClassInfo;
037    
038        private final StackTraceElement stackTraceElement;
039    
040        public ExtendedStackTraceElement(final StackTraceElement stackTraceElement, final ExtendedClassInfo extraClassInfo) {
041            this.stackTraceElement = stackTraceElement;
042            this.extraClassInfo = extraClassInfo;
043        }
044    
045        /**
046         * Called from Jackson for XML and JSON IO.
047         */
048        public ExtendedStackTraceElement(final String declaringClass, final String methodName, final String fileName,
049                final int lineNumber, final boolean exact, final String location, final String version) {
050            this(new StackTraceElement(declaringClass, methodName, fileName, lineNumber), new ExtendedClassInfo(exact,
051                    location, version));
052        }
053    
054        @Override
055        public boolean equals(final Object obj) {
056            if (this == obj) {
057                return true;
058            }
059            if (obj == null) {
060                return false;
061            }
062            if (!(obj instanceof ExtendedStackTraceElement)) {
063                return false;
064            }
065            final ExtendedStackTraceElement other = (ExtendedStackTraceElement) obj;
066            if (this.extraClassInfo == null) {
067                if (other.extraClassInfo != null) {
068                    return false;
069                }
070            } else if (!this.extraClassInfo.equals(other.extraClassInfo)) {
071                return false;
072            }
073            if (this.stackTraceElement == null) {
074                if (other.stackTraceElement != null) {
075                    return false;
076                }
077            } else if (!this.stackTraceElement.equals(other.stackTraceElement)) {
078                return false;
079            }
080            return true;
081        }
082    
083        public String getClassName() {
084            return this.stackTraceElement.getClassName();
085        }
086    
087        public boolean getExact() {
088            return this.extraClassInfo.getExact();
089        }
090    
091        public ExtendedClassInfo getExtraClassInfo() {
092            return this.extraClassInfo;
093        }
094    
095        public String getFileName() {
096            return this.stackTraceElement.getFileName();
097        }
098    
099        public int getLineNumber() {
100            return this.stackTraceElement.getLineNumber();
101        }
102    
103        public String getLocation() {
104            return this.extraClassInfo.getLocation();
105        }
106    
107        public String getMethodName() {
108            return this.stackTraceElement.getMethodName();
109        }
110    
111        public StackTraceElement getStackTraceElement() {
112            return this.stackTraceElement;
113        }
114    
115        public String getVersion() {
116            return this.extraClassInfo.getVersion();
117        }
118    
119        @Override
120        public int hashCode() {
121            final int prime = 31;
122            int result = 1;
123            result = prime * result + ((this.extraClassInfo == null) ? 0 : this.extraClassInfo.hashCode());
124            result = prime * result + ((this.stackTraceElement == null) ? 0 : this.stackTraceElement.hashCode());
125            return result;
126        }
127    
128        public boolean isNativeMethod() {
129            return this.stackTraceElement.isNativeMethod();
130        }
131    
132        @Override
133        public String toString() {
134            final StringBuilder sb = new StringBuilder();
135            sb.append(this.stackTraceElement);
136            sb.append(" ");
137            sb.append(this.extraClassInfo);
138            return sb.toString();
139        }
140    }