Package org.apache.clerezza.platform.typerendering

Source Code of org.apache.clerezza.platform.typerendering.RenderletManagerImpl

/*
* 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.clerezza.platform.typerendering;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.ws.rs.core.MediaType;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.utils.GraphNode;
import org.apache.felix.scr.annotations.Component;
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.Service;
import org.apache.felix.scr.annotations.Services;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component
@Services({
  @Service(RenderletManager.class)
})
@Reference(name = "renderlet",
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
referenceInterface = Renderlet.class)
@Deprecated
public class RenderletManagerImpl implements RenderletManager {
  private Collection<RegistrationRequest> pendingRequests
      = new HashSet<RegistrationRequest>();



  private static class RegistrationRequest {

    String renderletServiceName;
    UriRef renderingSpecification;
    UriRef rdfType;
    String mode;
    MediaType mediaType;

    public RegistrationRequest(String renderletServiceName, UriRef renderingSpecification, UriRef rdfType, String mode, MediaType mediaType) {
      this.renderletServiceName = renderletServiceName;
      this.renderingSpecification = renderingSpecification;
      this.rdfType = rdfType;
      this.mode = mode;
      this.mediaType = mediaType;
    }
  }
  private Logger logger = LoggerFactory.getLogger(RenderletManagerImpl.class);
  private ComponentContext componentContext;
  private final Set<ServiceReference> renderletRefStore =
      Collections.synchronizedSet(new HashSet<ServiceReference>());
  private final Set<ServiceRegistration> registeredTypeRenderlets =
      Collections.synchronizedSet(new HashSet<ServiceRegistration>());
  private ReentrantReadWriteLock configLock = new ReentrantReadWriteLock();
  /**
   * maps from service-id to the renderlet
   */
  private Map<String, Renderlet> renderletMap = new HashMap<String, Renderlet>();
  private BundleContext bundleContext;

  /**
   * Registeres a renderlet.
   *
   * For the same rdfType, mediaType and Mode at motst one built-in and one
   * non-built-in renderlet can be registered. An attempt to register a second
   * renderlet results in the unregistration of the previously registered one
   *
   * @param renderingSpecification the argument that is passed to the
   *   renderlet.
   * @param rdfType defines the RDF-type to be rendered with specified renderlet
   *   and renderingSpecification and mode.
   * @param mode defines the mode in which the renderlet and rendering
   *    specification has to be used.
   *    mode may be null, that indicates that it is only used when no mode is
   *    required.
   * @param mediaType The media type of the rendered
   * @param builtIn ignored
   */
  public void registerRenderlet(String renderletServiceName,
      final UriRef renderingSpecification,
      final UriRef rdfType,
      final String mode,
      final MediaType mediaType, boolean builtIn) {
    RegistrationRequest registrationRequest = new RegistrationRequest(renderletServiceName,
        renderingSpecification,
        rdfType,
        mode,
        mediaType);
    if (!attemptRegistration(registrationRequest)) {
      logger.info("no renderlet service registered for "
          + renderletServiceName + ", will retry later.");
      pendingRequests.add(registrationRequest);
    }
  }

  protected void bindRenderlet(ServiceReference renderletRef) {
    logger.info("Bind renderlet of bundle {}", renderletRef.getBundle().getSymbolicName());
    if (componentContext != null) {
      registerRenderletService(renderletRef);
    } else {
      renderletRefStore.add(renderletRef);
    }
  }

  private void registerRenderletService(ServiceReference renderletRef) {
    String servicePid = (String) renderletRef.getProperty(Constants.SERVICE_PID);
    Renderlet renderlet = (Renderlet) componentContext.locateService("renderlet", renderletRef);
    registerRenderletService(servicePid, renderlet);
  }

  protected void registerRenderletService(String servicePid, Renderlet renderlet) {
    configLock.writeLock().lock();
    try {
      if (renderletMap.get(servicePid) == null) {
        renderletMap.put(servicePid, renderlet);
      }
    } finally {
      configLock.writeLock().unlock();
    }
    handlePendingRegistrations();
  }

  protected void unbindRenderlet(ServiceReference renderletRef) {
    Lock l = configLock.writeLock();
    l.lock();
    try {
      if (!renderletRefStore.remove(renderletRef)) {
        String servicePid = (String) renderletRef.getProperty(Constants.SERVICE_PID);
        Renderlet renderlet = (Renderlet) componentContext.locateService("renderlet", renderletRef);
        unregisterRenderletService(servicePid, renderlet);
      }
    } finally {
      l.unlock();
    }
  }

  protected void unregisterRenderletService(String servicePid, Renderlet renderlet) {
    logger.debug("unregistering {} with pid {}", renderlet, servicePid);
    configLock.writeLock().lock();
    try {
      renderletMap.remove(servicePid);
    } finally {
      configLock.writeLock().unlock();
    }
  }

  private void registerRenderletsFromStore() {
    synchronized (renderletRefStore) {
      for (ServiceReference renderletRef : renderletRefStore) {
        registerRenderletService(renderletRef);
      }
    }
    renderletRefStore.clear();
  }

  /**
   * The activate method is called when SCR activates the component
   * configuration
   *
   * @param componentContext
   */
  protected void activate(ComponentContext componentContext) {
    bundleContext = componentContext.getBundleContext();
    this.componentContext = componentContext;
    registerRenderletsFromStore();
  }

  /**
   * The deactivate method is called when SCR deactivates the component
   * configuration
   *
   * @param componentContext
   */
  protected void deactivate(ComponentContext componentContext) {
    for (ServiceRegistration registration : registeredTypeRenderlets) {
      registration.unregister();
    }
    registeredTypeRenderlets.clear();
    bundleContext = null;
  }

  private void handlePendingRegistrations() {
    Lock l = configLock.readLock();
    l.lock();
    try {
      Iterator<RegistrationRequest> iterator = pendingRequests.iterator();
      while (iterator.hasNext()) {
        RegistrationRequest pending = iterator.next();
        if (attemptRegistration(pending)) {
          iterator.remove();
        }
      }
    } finally {
      l.unlock();
    }
  }

  private boolean attemptRegistration(RegistrationRequest registrationRequest) {
    final String renderletServiceName = registrationRequest.renderletServiceName;
    UriRef renderingSpecification = registrationRequest.renderingSpecification;
    final UriRef rdfType = registrationRequest.rdfType;
    final String modePattern = registrationRequest.mode;
    final MediaType mediaType = registrationRequest.mediaType;

    final Renderlet renderlet = renderletMap.get(renderletServiceName);
    if (renderlet == null) {
      return false;
    }
    final URI renderingSpecificationUri;
    try {
      renderingSpecificationUri = renderingSpecification != null
          ? new URI(renderingSpecification.getUnicodeString())
          : null;
    } catch (URISyntaxException ex) {
      throw new RuntimeException(ex);
    }
    TypeRenderlet typeRenderlet = new TypeRenderlet() {

      @Override
      public UriRef getRdfType() {
        return rdfType;
      }

      @Override
      public String getModePattern() {
        return modePattern;
      }

      @Override
      public MediaType getMediaType() {
        return mediaType;
      }

      @Override
      public void render(GraphNode node, GraphNode context,
          Map<String, Object> sharedRenderingValues,
          CallbackRenderer callbackRenderer,
          RequestProperties typeRenderletRequestProperties,
          OutputStream os) throws IOException {
        Renderlet.RequestProperties renderletRequestProperties =
            new Renderlet.RequestProperties(typeRenderletRequestProperties.getUriInfo(),
            typeRenderletRequestProperties.getRequestHeaders(),
            typeRenderletRequestProperties.getResponseHeaders(), bundleContext);
        renderlet.render(node, context, sharedRenderingValues,
            callbackRenderer, renderingSpecificationUri,
            typeRenderletRequestProperties.getMode(),
            typeRenderletRequestProperties.getMediaType(),
            renderletRequestProperties, os);
      }

      @Override
      public String toString() {
        return "RenderletManager managed for: "+renderletServiceName+" with "+renderingSpecificationUri;
      }


    };

    ServiceRegistration oldServiceRegistration =
        getAlreadyRegisteredServiceReg(rdfType, mediaType, modePattern);
    if(oldServiceRegistration != null) {
      oldServiceRegistration.unregister();
      registeredTypeRenderlets.remove(oldServiceRegistration);
    }

    ServiceRegistration registration = bundleContext.registerService(TypeRenderlet.class.getName(), typeRenderlet,
        new Hashtable());
    registeredTypeRenderlets.add(registration);
    return true;
  }

  private ServiceRegistration getAlreadyRegisteredServiceReg(UriRef rdfType,
      MediaType mediaType, String modePattern) {
   
    for (ServiceRegistration serviceRegistration : registeredTypeRenderlets) {
      TypeRenderlet registeredRenderlet = (TypeRenderlet)
          bundleContext.getService(serviceRegistration.getReference());
      if (registeredRenderlet != null
          && registeredRenderlet.getRdfType().equals(rdfType)
          && registeredRenderlet.getMediaType().equals(mediaType)) {

        if(modePattern == null && registeredRenderlet.getModePattern() == null) {
          return serviceRegistration;
        } else if(modePattern != null && registeredRenderlet.getModePattern() != null) {
          if(registeredRenderlet.getModePattern().equals(modePattern)) {
            return serviceRegistration;
          }
        }
      }
    }
    return null;
  }
}
TOP

Related Classes of org.apache.clerezza.platform.typerendering.RenderletManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.