/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sling.engine.impl.log; import org.apache.sling.engine.RequestLog; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.util.tracker.ServiceTracker; /** * The <code>RequestLogServiceFacade</code> is a <code>RequestLog</code> * implementation used to redirect output requests to <code>RequestLog</code> * services registered with a specific logger name. Each service thus registered * is called with the message by the {@link #write(String)} method. * <p> * This class is initialized with the service name which is used to find request * log services to send log messages to. Such services are selected as follows: * <ol> * <li>The service must be registered with service interface * <code>org.apache.sling.engine.RequestLog</code>.</li> * <li>The service must be registered with a service property * <code>requestlog.name</code> (defined in the * {@link RequestLog#REQUEST_LOG_NAME} constant whose value (or one of its * values, if multi-valued) must be the service name.</li> * </ol> */ class RequestLogServiceFacade implements RequestLog { // The service tracker used to access the service(s) private final ServiceTracker requestLogTracker; // private copy of services currently available. We cache them to gain some // milliseconds, as each call to ServiceTracker.getServices() looks the // services up in the service registry private Object[] loggers; // tracking count of the time when we got the service list, if the // service tracker changes its count, we have to reaquire the services private int trackingCount; /** * Creates an instance of this facade class calling request log services * with the given <code>serviceName</code>. * * @param context The <code>BundleContext</code> used to acquire the request * log services. * @param serviceName The name of the services used for logging. This value * is used to check the {@link RequestLog#REQUEST_LOG_NAME} * service property for service selection. */ public RequestLogServiceFacade(BundleContext context, String serviceName) { String filter = "(&(" + Constants.OBJECTCLASS + "=" + RequestLog.class.getName() + ")(" + RequestLog.REQUEST_LOG_NAME + "=" + serviceName + "))"; this.requestLogTracker = new ServiceTracker(context, filter, null); this.requestLogTracker.open(); // use negative initial tracking count to force acquiry of services this.trackingCount = -1; } /** * @see org.apache.sling.engine.RequestLog#write(java.lang.String) */ public void write(String message) { // acquire the current logger list Object[] tmpLoggers = this.loggers; // if services have been added/removed reacquire from the tracker if (this.trackingCount != this.requestLogTracker.getTrackingCount()) { tmpLoggers = this.requestLogTracker.getServices(); this.loggers = tmpLoggers; } // finally call the loggers with the message if (tmpLoggers != null) { for (int i = 0; i < tmpLoggers.length; i++) { ((RequestLog) tmpLoggers[i]).write(message); } } } public void close() { // drop the service references and reinitialize tracking counter this.loggers = null; this.trackingCount = -1; // terminate using the RequestLog service(s) this.requestLogTracker.close(); } }