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.servicemix.jbi.logging;
018    
019    import java.net.URL;
020    import java.util.Timer;
021    
022    import javax.jbi.JBIException;
023    import javax.management.JMException;
024    import javax.management.MBeanAttributeInfo;
025    import javax.management.MBeanOperationInfo;
026    
027    import org.apache.log4j.Logger;
028    import org.apache.servicemix.jbi.container.JBIContainer;
029    import org.apache.servicemix.jbi.management.AttributeInfoHelper;
030    import org.apache.servicemix.jbi.management.BaseSystemService;
031    import org.apache.servicemix.jbi.management.OperationInfoHelper;
032    import org.springframework.beans.factory.InitializingBean;
033    
034    /**
035     * 
036     * @org.apache.xbean.XBean element="logService"
037     * 
038     * TODO add methods to change one or more specific LogLevels at runtime
039     */
040    public class LogService extends BaseSystemService implements InitializingBean, LogServiceMBean {
041    
042        private static final String DEFAULT_LOG_FILE_NAME = "log4j.xml";
043    
044        private static final Logger LOG = Logger.getLogger(LogService.class);
045    
046        private boolean autoStart = true;
047    
048        private boolean initialized;
049    
050        private int refreshPeriod = 60; // 60sec
051    
052        private URL configFileUrl;
053    
054        private String configUrl = "file:conf/log4j.xml";
055    
056        private LogTask logTask;
057    
058        // timer in daemon mode
059        private Timer timer;
060    
061        public void afterPropertiesSet() throws Exception {
062            if (this.container == null) {
063                throw new IllegalArgumentException("container should not be null");
064            }
065            init(getContainer());
066            if (autoStart) {
067                start();
068            }
069        }
070    
071        public JBIContainer getContainer() {
072            return container;
073        }
074    
075        public void setContainer(JBIContainer container) {
076            this.container = container;
077        }
078    
079        public String getDescription() {
080            return "Log4j Service which periodicaly scan the config file";
081        }
082    
083        /**
084         * 
085         * @param seconds
086         *            Refresh period for the log4j system.
087         */
088        public void setRefreshPeriod(int seconds) {
089            this.refreshPeriod = seconds;
090            try {
091                if (isStarted()) {
092                    stop();
093                    start();
094                }
095            } catch (JBIException ex) {
096                LOG.error("Error occured!", ex);
097            }
098        }
099    
100        /**
101         * 
102         * @return returns the time in seconds for the refresh period
103         */
104        public int getRefreshPeriod() {
105            return this.refreshPeriod;
106        }
107    
108        /**
109         * set new location for log4j config
110         * 
111         * @param url
112         *            Location for log4j config file example: file:conf/log4j.xml
113         */
114        public void setConfigUrl(String url) {
115            this.configUrl = url;
116            try {
117                if (isStarted()) {
118                    stop();
119                    start();
120                }
121            } catch (JBIException ex) {
122                LOG.error("Error occured!", ex);
123            }
124    
125        }
126    
127        public String getConfigUrl() {
128            return this.configUrl;
129        }
130    
131        public void setAutoStart(boolean autoStart) {
132            this.autoStart = autoStart;
133        }
134    
135        public boolean getAutoStart() {
136            return this.autoStart;
137        }
138    
139        /**
140         * reconfigure the log4j system if something has changed in the config file
141         */
142        public void reconfigureLogSystem() {
143            if (LOG.isDebugEnabled()) {
144                LOG.debug("try to reconfigure the log4j system");
145            }
146            if (logTask != null) {
147                logTask.reconfigure();
148            }
149        }
150    
151        protected Class getServiceMBean() {
152            return LogServiceMBean.class;
153        }
154    
155        public void start() throws JBIException {
156            setUp();
157            super.start();
158        }
159    
160        public void stop() throws JBIException {
161            if (logTask != null) {
162                logTask.cancel();
163                logTask = null;
164            }
165            if (timer != null) {
166                timer.cancel();
167                timer = null;
168            }
169            initialized = false;
170            super.stop();
171        }
172    
173        public void setUp() throws JBIException {
174            if (!initialized) {
175                configFileUrl = locateLoggingConfig();
176    
177                if (configFileUrl != null) {
178                    // daemon mode
179                    timer = new Timer(true);
180                    logTask = new LogTask(configFileUrl);
181                    logTask.run();
182                    timer.schedule(logTask, 1000 * refreshPeriod, 1000 * refreshPeriod);
183                    initialized = true;
184                }
185            }
186        }
187    
188        /**
189         * Grab the log4j.xml from the CLASSPATH
190         * 
191         * @return URL of the log4j.xml file
192         */
193        private URL locateLoggingConfig() {
194            URL log4jConfigUrl = ClassLoader.getSystemResource(DEFAULT_LOG_FILE_NAME);
195    
196            if (LOG.isDebugEnabled()) {
197                LOG.debug("Located logging configuration: " + log4jConfigUrl.toString());
198            }
199    
200            return log4jConfigUrl;
201        }
202    
203        public MBeanOperationInfo[] getOperationInfos() throws JMException {
204            OperationInfoHelper helper = new OperationInfoHelper();
205            helper.addOperation(getObjectToManage(), "reconfigureLogSystem", 0, "Reconfigure the log4j system");
206            return OperationInfoHelper.join(super.getOperationInfos(), helper.getOperationInfos());
207        }
208    
209        public MBeanAttributeInfo[] getAttributeInfos() throws JMException {
210            AttributeInfoHelper helper = new AttributeInfoHelper();
211            helper.addAttribute(getObjectToManage(), "configUrl", "the url for the log4j.xml config file");
212            helper.addAttribute(getObjectToManage(), "refreshPeriod", "schedule time for scanning the log4j config file");
213            return AttributeInfoHelper.join(super.getAttributeInfos(), helper.getAttributeInfos());
214        }
215    }