All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.commons.servlets.NonExistingDispatcherServlet Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*
 * Copyright 1997-2009 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.commons.servlets;

import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.OptingServlet;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * {@linkplain NonExistingDispatcherServlet} is a solution to dispatch the
 * sling:nonexisting resource type based on dynamic acceptance. With standard
 * Sling it is only possible to register a single servlet for each HTTP method
 * on the nonexisting resource.
 *
 * 

* Please note: This is a temporary solution until Sling provides * a built-in mechanism for this use case. Not to be used by client * implementations! */ @SuppressWarnings("serial") @SlingServlet( paths = { "/apps/sling/nonexisting/GET.servlet", "/apps/sling/nonexisting/POST.servlet", "/apps/sling/nonexisting/PUT.servlet" } ) @Reference( name = "Servlet", referenceInterface = NonExistingResourceServlet.class, policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE ) public class NonExistingDispatcherServlet extends GenericServlet implements OptingServlet { private final Logger log = LoggerFactory.getLogger(NonExistingDispatcherServlet.class); private ComponentContext context; private List unhandledServlets = new ArrayList(); private SortedMap servlets = new TreeMap(new Comparator() { /** * Implementation following the latest OSGi R4 4.1 release: * http://www.osgi.org/javadoc/r4v41/org/osgi/framework/ServiceReference.html#compareTo(java.lang.Object) * * This custom implementation is required because Sling does * not yet use a 4.1 OSGi framework implementation. */ public int compare(ServiceReference ref1, ServiceReference ref2) { // first check for equal references long id1 = getServiceID(ref1); long id2 = getServiceID(ref2); if (id1 == id2) { return 0; } int rank1 = getServiceRanking(ref1); int rank2 = getServiceRanking(ref2); if (rank1 == rank2) { return (int) (id1 - id2); } else { return rank2 - rank1; } } }); private static final String SERVLET_REQUEST_ATTR = NonExistingResourceServlet.class.getName(); public boolean accepts(SlingHttpServletRequest request) { NonExistingResourceServlet servlet = findServlet(request); if (servlet != null) { // store servlet in request attribute to avoid that doGet(), // doPost(), etc. have to call findServlet() again request.setAttribute(SERVLET_REQUEST_ATTR, servlet); request.getRequestProgressTracker().log("{0}: will dispatch to {1}", this.getClass().getSimpleName(), servlet.getClass().getName()); return true; } request.getRequestProgressTracker().log("{0}: no servlet found"); return false; } @Override public void service(ServletRequest request, ServletResponse res) throws ServletException, IOException { SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request; NonExistingResourceServlet servlet = (NonExistingResourceServlet) request.getAttribute(SERVLET_REQUEST_ATTR); if (servlet != null) { slingRequest.getRequestProgressTracker().startTimer(servlet.getClass().getName()); servlet.service(request, res); slingRequest.getRequestProgressTracker().logTimer(servlet.getClass().getName()); } else { // rare case - have to search again servlet = findServlet(slingRequest); if (servlet != null) { slingRequest.getRequestProgressTracker().log("{0}: will dispatch to {1}", this.getClass().getSimpleName(), servlet.getClass().getName()); slingRequest.getRequestProgressTracker().startTimer(servlet.getClass().getName()); servlet.service(request, res); slingRequest.getRequestProgressTracker().logTimer(servlet.getClass().getName()); } else { slingRequest.getRequestProgressTracker().log("{0}: no servlet found"); SlingHttpServletResponse response = (SlingHttpServletResponse) res; response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No " + NonExistingResourceServlet.class.getName() + " found for handling " + "sling:nonexisting case (and no OptingServlet support)"); } } } // ----------------------------------------------< servlet selection > protected NonExistingResourceServlet findServlet(SlingHttpServletRequest request) { synchronized (servlets) { // this iteration is sorted by rank, descending for (NonExistingResourceServlet servlet : servlets.values()) { if (servlet.accepts(request)) { return servlet; } } } return null; } // ----------------------------------------------< osgi handling > protected void activate(ComponentContext context) { synchronized (servlets) { this.context = context; for (ServiceReference reference : unhandledServlets) { registerServlet(reference); } unhandledServlets.clear(); } } protected void deactivate(ComponentContext context) { synchronized (servlets) { this.context = null; } } protected void bindServlet(ServiceReference reference) { synchronized (servlets) { if (context == null) { unhandledServlets.add(reference); } else { registerServlet(reference); } } } protected void unbindServlet(ServiceReference reference) { synchronized (servlets) { unregisterServlet(reference); unhandledServlets.remove(reference); } } private void registerServlet(ServiceReference reference) { NonExistingResourceServlet servlet = (NonExistingResourceServlet) context.locateService("Servlet", reference); if ( servlet != null ) { synchronized (servlets) { servlets.put(reference, servlet); log.info("Servlets in order: " + servlets.values().toString()); } } } private void unregisterServlet(ServiceReference reference) { synchronized (servlets) { servlets.remove(reference); } } private long getServiceID(ServiceReference reference) { return (Long) reference.getProperty(Constants.SERVICE_ID); } private int getServiceRanking(ServiceReference reference) { Object obj = reference.getProperty(Constants.SERVICE_RANKING); if (obj == null) { // default service.ranking value return 0; } else if (obj instanceof Integer) { return (Integer) obj; } else { log.warn("Component " + reference.getProperty("component.name") + " has a non-Integer '" + Constants.SERVICE_RANKING + "' property"); return 0; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy