blob: 0ed049b325146f7c089bf3dd09aadc79679f01a9 [file] [log] [blame]
/*
* 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.felix.http.base.internal.whiteboard;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import javax.servlet.ServletContext;
import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
import org.apache.felix.http.base.internal.service.HttpServiceFactory;
import org.apache.felix.http.base.internal.service.PerBundleHttpServiceImpl;
import org.osgi.framework.Bundle;
public class HttpServiceContextHandler extends WhiteboardContextHandler
{
private final PerContextHandlerRegistry registry;
private final HttpServiceFactory httpServiceFactory;
/** A map of all created servlet contexts. Each bundle gets it's own instance. */
private final Map<Long, ContextHolder> perBundleContextMap = new HashMap<Long, ContextHolder>();
private final ServletContext sharedContext;
public HttpServiceContextHandler(final ServletContextHelperInfo info,
final PerContextHandlerRegistry registry,
final HttpServiceFactory httpServiceFactory,
final ServletContext webContext,
final Bundle httpBundle)
{
super(info, webContext, httpBundle);
this.registry = registry;
this.httpServiceFactory = httpServiceFactory;
this.sharedContext = webContext;
}
@Override
public PerContextHandlerRegistry getRegistry()
{
return this.registry;
}
@Override
public ServletContext getSharedContext()
{
return this.sharedContext;
}
@Override
public @Nullable ExtServletContext getServletContext(@Nullable final Bundle bundle)
{
if ( bundle == null )
{
return null;
}
final Long key = bundle.getBundleId();
synchronized ( this.perBundleContextMap )
{
ContextHolder holder = this.perBundleContextMap.get(key);
if ( holder == null )
{
holder = new ContextHolder();
final PerBundleHttpServiceImpl service = (PerBundleHttpServiceImpl)this.httpServiceFactory.getService(bundle, null);
holder.servletContext = service.getServletContext(service.createDefaultHttpContext());
holder.httpService = service;
this.perBundleContextMap.put(key, holder);
}
holder.counter++;
return holder.servletContext;
}
}
@Override
public void ungetServletContext(@NotNull final Bundle bundle)
{
final Long key = bundle.getBundleId();
synchronized ( this.perBundleContextMap )
{
ContextHolder holder = this.perBundleContextMap.get(key);
if ( holder != null )
{
holder.counter--;
if ( holder.counter == 0 )
{
this.perBundleContextMap.remove(key);
holder.httpService.unregisterAll();
}
}
}
}
private static final class ContextHolder
{
public long counter;
public ExtServletContext servletContext;
public PerBundleHttpServiceImpl httpService;
}
}