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;
018    
019    import java.util.concurrent.ConcurrentHashMap;
020    import java.util.concurrent.ConcurrentMap;
021    
022    
023    /**
024     * Applications create Markers by using the Marker Manager. All Markers created by this Manager are
025     * immutable.
026     */
027    public final class MarkerManager {
028    
029        private static ConcurrentMap<String, Marker> markerMap = new ConcurrentHashMap<String, Marker>();
030    
031        private MarkerManager() {
032        }
033    
034        /**
035         * Retrieve a Marker or create a Marker that has no parent.
036         * @param name The name of the Marker.
037         * @return The Marker with the specified name.
038         */
039        public static Marker getMarker(final String name) {
040            markerMap.putIfAbsent(name, new Log4jMarker(name));
041            return markerMap.get(name);
042        }
043    
044        /**
045         * Retrieves or creates a Marker with the specified parent. The parent must have been previously created.
046         * @param name The name of the Marker.
047         * @param parent The name of the parent Marker.
048         * @return The Marker with the specified name.
049         * @throws IllegalArgumentException if the parent Marker does not exist.
050         */
051        public static Marker getMarker(final String name, final String parent) {
052            final Marker parentMarker = markerMap.get(parent);
053            if (parentMarker == null) {
054                throw new IllegalArgumentException("Parent Marker " + parent + " has not been defined");
055            }
056            return getMarker(name, parentMarker);
057        }
058    
059        /**
060         * Retrieves or creates a Marker with the specified parent.
061         * @param name The name of the Marker.
062         * @param parent The parent Marker.
063         * @return The Marker with the specified name.
064         */
065        public static Marker getMarker(final String name, final Marker parent) {
066            markerMap.putIfAbsent(name, new Log4jMarker(name, parent));
067            return markerMap.get(name);
068        }
069    
070        /**
071         * The actual Marker implementation.
072         */
073        private static class Log4jMarker implements Marker {
074    
075            private static final long serialVersionUID = 100L;
076    
077            private final String name;
078            private final Marker parent;
079    
080            public Log4jMarker(final String name) {
081                this.name = name;
082                this.parent = null;
083            }
084    
085            public Log4jMarker(final String name, final Marker parent) {
086                this.name = name;
087                this.parent = parent;
088            }
089    
090            @Override
091            public String getName() {
092                return this.name;
093            }
094    
095            @Override
096            public Marker getParent() {
097                return this.parent;
098            }
099    
100            @Override
101            public boolean isInstanceOf(final Marker m) {
102                if (m == null) {
103                    throw new IllegalArgumentException("A marker parameter is required");
104                }
105                Marker test = this;
106                do {
107                    if (test == m) {
108                        return true;
109                    }
110                    test = test.getParent();
111                } while (test != null);
112                return false;
113            }
114    
115            @Override
116            public boolean isInstanceOf(final String name) {
117                if (name == null) {
118                    throw new IllegalArgumentException("A marker name is required");
119                }
120                Marker toTest = this;
121                do {
122                    if (name.equals(toTest.getName())) {
123                        return true;
124                    }
125                    toTest = toTest.getParent();
126                } while (toTest != null);
127                return false;
128            }
129    
130            @Override
131            public boolean equals(final Object o) {
132                if (this == o) {
133                    return true;
134                }
135                if (o == null || !(o instanceof Marker)) {
136                    return false;
137                }
138    
139                final Marker marker = (Marker) o;
140    
141                if (name != null ? !name.equals(marker.getName()) : marker.getName() != null) {
142                    return false;
143                }
144    
145                return true;
146            }
147    
148            @Override
149            public int hashCode() {
150                return name != null ? name.hashCode() : 0;
151            }
152    
153            @Override
154            public String toString() {
155                final StringBuilder sb = new StringBuilder(name);
156                if (parent != null) {
157                    Marker m = parent;
158                    sb.append("[ ");
159                    boolean first = true;
160                    while (m != null) {
161                        if (!first) {
162                            sb.append(", ");
163                        }
164                        sb.append(m.getName());
165                        first = false;
166                        m = m.getParent();
167                    }
168                    sb.append(" ]");
169                }
170                return sb.toString();
171            }
172        }
173    }