blob: d23c4b96c40477edc032c5ca34c3ec71c6cece2f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) Feb. 2, 2019 Liferay, Inc.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Liferay, Inc. - initial API and implementation and/or initial
* documentation
******************************************************************************/
package org.eclipse.equinox.http.servlet.internal;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_PREPROCESSOR_INIT_PARAM_PREFIX;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import org.eclipse.equinox.http.servlet.internal.context.ServiceHolder;
import org.eclipse.equinox.http.servlet.internal.error.HttpWhiteboardFailureException;
import org.eclipse.equinox.http.servlet.internal.registration.PreprocessorRegistration;
import org.eclipse.equinox.http.servlet.internal.servlet.FilterConfigImpl;
import org.eclipse.equinox.http.servlet.internal.util.ServiceProperties;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.runtime.dto.*;
import org.osgi.service.http.whiteboard.Preprocessor;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* @author Raymond Augé
*/
public class PreprocessorCustomizer
implements ServiceTrackerCustomizer<Preprocessor, AtomicReference<PreprocessorRegistration>> {
public PreprocessorCustomizer(HttpServiceRuntimeImpl httpServiceRuntime) {
this.httpServiceRuntime = httpServiceRuntime;
}
@Override
public AtomicReference<PreprocessorRegistration> addingService(
ServiceReference<Preprocessor> serviceReference) {
AtomicReference<PreprocessorRegistration> result = new AtomicReference<PreprocessorRegistration>();
if (!httpServiceRuntime.matches(serviceReference)) {
return result;
}
try {
removeFailed(serviceReference);
result.set(addPreprocessorRegistration(serviceReference));
}
catch (HttpWhiteboardFailureException hwfe) {
httpServiceRuntime.debug(hwfe.getMessage(), hwfe);
recordFailed(serviceReference, hwfe.getFailureReason());
}
catch (Exception e) {
httpServiceRuntime.error(e.getMessage(), e);
recordFailed(serviceReference, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT);
}
finally {
httpServiceRuntime.incrementServiceChangecount();
}
return result;
}
@Override
public void modifiedService(
ServiceReference<Preprocessor> serviceReference, AtomicReference<PreprocessorRegistration> reference) {
removedService(serviceReference, reference);
AtomicReference<PreprocessorRegistration> added = addingService(serviceReference);
reference.set(added.get());
}
@Override
public void removedService(
ServiceReference<Preprocessor> serviceReference, AtomicReference<PreprocessorRegistration> reference) {
try {
PreprocessorRegistration registration = reference.get();
if (registration != null) {
registration.destroy();
}
removeFailed(serviceReference);
}
finally {
httpServiceRuntime.incrementServiceChangecount();
}
}
void removeFailed(ServiceReference<Preprocessor> serviceReference) {
httpServiceRuntime.removeFailedPreprocessorDTO(serviceReference);
}
private void recordFailed(
ServiceReference<Preprocessor> serviceReference, int failureReason) {
FailedPreprocessorDTO failedPreprocessorDTO = new FailedPreprocessorDTO();
failedPreprocessorDTO.failureReason = failureReason;
failedPreprocessorDTO.initParams = ServiceProperties.parseInitParams(
serviceReference, HTTP_WHITEBOARD_PREPROCESSOR_INIT_PARAM_PREFIX);
failedPreprocessorDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID);
httpServiceRuntime.recordFailedPreprocessorDTO(serviceReference, failedPreprocessorDTO);
}
private PreprocessorRegistration addPreprocessorRegistration(
ServiceReference<Preprocessor> preprocessorRef) throws ServletException {
ServiceHolder<Preprocessor> preprocessorHolder = new ServiceHolder<Preprocessor>(httpServiceRuntime.getConsumingContext().getServiceObjects(preprocessorRef));
Preprocessor preprocessor = preprocessorHolder.get();
PreprocessorRegistration registration = null;
boolean addedRegisteredObject = false;
try {
if (preprocessor == null) {
throw new IllegalArgumentException("Preprocessor cannot be null"); //$NON-NLS-1$
}
addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(preprocessor);
if (!addedRegisteredObject) {
throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + preprocessorRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$
}
registration = doAddPreprocessorRegistration(preprocessorHolder, preprocessorRef);
} finally {
if (registration == null) {
preprocessorHolder.release();
if (addedRegisteredObject) {
httpServiceRuntime.getRegisteredObjects().remove(preprocessor);
}
}
}
return registration;
}
private PreprocessorRegistration doAddPreprocessorRegistration(
ServiceHolder<Preprocessor> preprocessorHolder,
ServiceReference<Preprocessor> preprocessorRef) throws ServletException {
PreprocessorDTO preprocessorDTO = new PreprocessorDTO();
preprocessorDTO.initParams = ServiceProperties.parseInitParams(
preprocessorRef, HTTP_WHITEBOARD_PREPROCESSOR_INIT_PARAM_PREFIX);
preprocessorDTO.serviceId = preprocessorHolder.getServiceId();
PreprocessorRegistration newRegistration = new PreprocessorRegistration(
preprocessorHolder, preprocessorDTO, httpServiceRuntime);
FilterConfig filterConfig = new FilterConfigImpl(
preprocessorHolder.get().getClass().getCanonicalName(),
preprocessorDTO.initParams,
httpServiceRuntime.getParentServletContext());
newRegistration.init(filterConfig);
httpServiceRuntime.getPreprocessorRegistrations().put(preprocessorHolder.getServiceReference(), newRegistration);
return newRegistration;
}
private final HttpServiceRuntimeImpl httpServiceRuntime;
}