001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.sift; 015 016import java.util.Collection; 017import java.util.Map; 018 019import ch.qos.logback.core.Appender; 020import ch.qos.logback.core.Context; 021import ch.qos.logback.core.joran.JoranConstants; 022import ch.qos.logback.core.joran.ParamModelHandler; 023import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry; 024import ch.qos.logback.core.joran.spi.JoranException; 025import ch.qos.logback.core.model.AppenderModel; 026import ch.qos.logback.core.model.ImplicitModel; 027import ch.qos.logback.core.model.Model; 028import ch.qos.logback.core.model.ParamModel; 029import ch.qos.logback.core.model.PropertyModel; 030import ch.qos.logback.core.model.SiftModel; 031import ch.qos.logback.core.model.processor.AppenderModelHandler; 032import ch.qos.logback.core.model.processor.ImplicitModelHandler; 033import ch.qos.logback.core.model.processor.ModelInterpretationContext; 034import ch.qos.logback.core.model.processor.PropertyModelHandler; 035 036/** 037 * Builds new appenders dynamically by running SiftingJoranConfigurator instance, 038 * a custom configurator tailored for the contents of the sift element. 039 * @param <E> 040 */ 041public class AppenderFactoryUsingSiftModel<E> implements AppenderFactory<E> { 042 043 Context context; 044 final Model siftModel; 045 protected String discriminatingKey; 046 protected ModelInterpretationContext parentMic; 047 protected DefaultNestedComponentRegistry registry; 048 049 public AppenderFactoryUsingSiftModel(ModelInterpretationContext parentMic, Model aSiftModel, String discriminatingKey) { 050 this.siftModel = Model.duplicate(aSiftModel); 051 this.discriminatingKey = discriminatingKey; 052 this.parentMic = parentMic; 053 this.context = parentMic.getContext(); 054 055 } 056 057 058 public SiftProcessor<E> getSiftingModelProcessor(String value) { 059 ModelInterpretationContext smic = new ModelInterpretationContext(parentMic) { 060 @Override 061 public boolean hasDependers(String dependeeName) { 062 return true; 063 } 064 }; 065 SiftProcessor<E> siftProcessor = new SiftProcessor<>(context, smic); 066 siftProcessor.addHandler(ParamModel.class, ParamModelHandler::makeInstance); 067 siftProcessor.addHandler(PropertyModel.class, PropertyModelHandler::makeInstance); 068 siftProcessor.addHandler(ImplicitModel.class, ImplicitModelHandler::makeInstance); 069 siftProcessor.addHandler(AppenderModel.class, AppenderModelHandler::makeInstance); 070 siftProcessor.addHandler(SiftModel.class, NOPSiftModelHandler::makeInstance); 071 072 return siftProcessor; 073 074 } 075 076 public Appender<E> buildAppender(Context context, String discriminatingValue) throws JoranException { 077 078 SiftProcessor<E> sp = getSiftingModelProcessor(discriminatingValue); 079 ModelInterpretationContext mic = sp.getModelInterpretationContext(); 080 sp.setContext(context); 081 Model duplicate = Model.duplicate(siftModel); 082 mic.addSubstitutionProperty(discriminatingKey, discriminatingValue); 083 sp.process(duplicate); 084 @SuppressWarnings("unchecked") 085 Map<String, Appender<E>> appenderBag = (Map<String, Appender<E>>) mic.getObjectMap() 086 .get(JoranConstants.APPENDER_BAG); 087 Collection<Appender<E>> values = appenderBag.values(); 088 if (values.size() == 0) { 089 return null; 090 } 091 return values.iterator().next(); 092 } 093 094 public Model getSiftModel() { 095 return siftModel; 096 } 097 098}