blob: 76c150c470319cca7c43e95e6b871c43da068eb8 [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.directory.server.component.hub;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import org.apache.directory.server.component.ADSComponent;
import org.apache.directory.server.component.ADSConstants;
import org.apache.directory.server.component.hub.listener.HubListener;
import org.apache.directory.server.component.schema.ComponentSchemaGenerator;
import org.apache.directory.server.component.schema.UserComponentSchemaGenerator;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.ManifestMetadataParser;
import org.apache.felix.ipojo.parser.ParseException;
import org.apache.felix.ipojo.whiteboard.Wbp;
import org.apache.felix.ipojo.whiteboard.Whiteboards;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
/**
* An IPojo component that listens for incoming factories and instances.
* Creating or destroying corresponding ADSComponent from them.
*
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@Component
@Whiteboards(whiteboards =
{
@Wbp(onArrival = "onFactoryArrival",
onDeparture = "onFactoryDeparture",
filter = "(objectClass=org.apache.felix.ipojo.Factory)"),
@Wbp(onArrival = "onInstanceArrival",
onDeparture = "onInstanceDeparture",
filter = "(objectClass=org.apache.felix.ipojo.architecture.Architecture)")
})
public class ComponentHub
{
/*
* boolean value to check for deferred writes to schema partition
*/
private boolean schemaReady = false;
/*
* boolean value to check for deferred writes to config partition
*/
private boolean configReady = false;
/*
* Map to keep "component type" -> "components" mapping.
*/
private Dictionary<String, List<ADSComponent>> componentMap;
/*
* List to keep all active ApacheDS components.
*/
private List<ADSComponent> components;
/*
* Map to keep "component type" -> "schema generator" mapping.
*/
private Dictionary<String, ComponentSchemaGenerator> schemaGenerators;
/*
* Map to keep "component type" -> "listeners" mapping
*/
private Dictionary<String, List<HubListener>> listenersMap;
/*
* OSGI Logger
*/
@Requires
private LogService logger;
public ComponentHub()
{
componentMap = new Hashtable<String, List<ADSComponent>>();
components = new ArrayList<ADSComponent>();
schemaGenerators = new Hashtable<String, ComponentSchemaGenerator>();
schemaGenerators.put( ADSConstants.ADS_COMPONENT_TYPE_USER, new UserComponentSchemaGenerator() );
listenersMap = new Hashtable<String, List<HubListener>>();
}
/**
* Called when ADSComponentHub instance is validated by IPojo
*
*/
@Validate
public void hubValidated()
{
logger.log( LogService.LOG_INFO, "ADSComponentHub validated." );
}
/**
* Called when ADSComponentHub instance is invalidated by IPojo
*
*/
@Invalidate
public void hubInvalidated()
{
logger.log( LogService.LOG_INFO, "ADSComponentHub validated." );
}
/**
* Factory arrival callback, registered by whiteboard handler.
*
* @param ref Reference to IPojo Factory
*/
public void onFactoryArrival( ServiceReference ref )
{
Factory arrivingFactory = ( Factory ) ref.getBundle().getBundleContext().getService( ref );
if ( !checkIfADSComponent( arrivingFactory ) )
{
return;
}
try
{
String componentType = parseComponentType( arrivingFactory );
List<HubListener> listenersByType = listenersMap.get( componentType );
// Fire the 'factory arrived' event on listeners.
if ( listenersByType != null )
{
for ( HubListener listener : listenersByType )
{
listener.onFactoryArrival( arrivingFactory );
}
}
//Actual ADSComponent creation
ADSComponent component = generateADSComponent( componentType, arrivingFactory );
// Iterate over listeners for 'component created' event. Apply the changes applied by them.
if ( listenersByType != null )
{
for ( HubListener listener : listenersByType )
{
ADSComponent _comp = listener.onComponentCreation( component );
if ( _comp != null )
{
component = _comp;
}
}
}
//Keep the newly created ADSComponent reference.
components.add( component );
List<ADSComponent> componentsByType = componentMap.get( componentType );
if ( componentsByType == null )
{
List<ADSComponent> newCompList = new ArrayList<ADSComponent>();
newCompList.add( component );
componentMap.put( componentType, newCompList );
}
else
{
componentsByType.add( component );
}
}
catch ( ParseException e )
{
e.printStackTrace();
}
}
/**
* Factory departure callback, registered by whiteboard handler.
*
* @param ref Reference to IPojo Factory
*/
public void onFactoryDeparture( ServiceReference ref )
{
Factory leavingFactory = ( Factory ) ref.getBundle().getBundleContext().getService( ref );
if ( !checkIfADSComponent( leavingFactory ) )
{
return;
}
try
{
String componentType = parseComponentType( leavingFactory );
List<HubListener> listenersByType = listenersMap.get( componentType );
// Fire the 'factory leaving' event on listeners.
if ( listenersByType != null )
{
for ( HubListener listener : listenersByType )
{
listener.onFactoryDeparture( leavingFactory );
}
}
ADSComponent associatedComp = null;
for ( ADSComponent _comp : components )
{
if ( _comp.getFactory().getName().equals( leavingFactory.getName() ) )
{
associatedComp = _comp;
break;
}
}
if ( associatedComp == null )
{
logger.log( LogService.LOG_INFO, "Couldn't found an associated ADSComponent for factory:"
+ leavingFactory.getName() );
return;
}
// Iterate over listeners for 'component deleting' event.
if ( listenersByType != null )
{
for ( HubListener listener : listenersByType )
{
listener.onComponentDeletion( associatedComp );
}
}
// All clients are notified now cache and delete the ADSComponent existence on ApacheDS
cacheAndReleaseADSComponent( associatedComp );
}
catch ( ParseException e )
{
e.printStackTrace();
}
}
/**
* IPojo instance arrival callback, registered by whiteboard handler.
*
* @param ref Reference to IPojo instance
*/
public void onInstanceArrival( ServiceReference ref )
{
}
/**
* IPojo instance departure callback, registered by whiteboard handler.
*
* @param ref Reference to IPojo instance
*/
public void onInstanceDeparture( ServiceReference ref )
{
}
/**
* Check whether the argument is ADSComponent annotated.
*
* @param factory
* @return
*/
private boolean checkIfADSComponent( Factory factory )
{
List<String> handlers = factory.getRequiredHandlers();
for ( String handlerName : handlers )
{
if ( handlerName.equals( ADSConstants.ADS_COMPONENT_HANDLER_FULLNAME ) )
{
return true;
}
}
return false;
}
private String parseComponentType( Factory factory ) throws ParseException
{
Dictionary bundleHeaders = factory.getBundleContext().getBundle().getHeaders();
String ipojoHeader = ( String ) bundleHeaders.get( ADSConstants.IPOJO_HEADER );
if ( ipojoHeader == null )
{
throw new ParseException( "Null ipojo header returned for factory: " + factory.getName() );
}
ManifestMetadataParser parser = new ManifestMetadataParser();
parser.parseHeader( ipojoHeader );
Element[] componentMetas = parser.getComponentsMetadata();
for ( Element componentMeta : componentMetas )
{
String compName = componentMeta.getAttribute( "name" );
if ( compName.equals( factory.getName() ) )
{
Element[] adsElements = componentMeta.getElements(
ADSConstants.ADS_COMPONENT_HANDLER_NAME,
ADSConstants.ADS_COMPONENT_HANDLER_NS );
if ( adsElements == null || adsElements.length == 0 )
{
throw new ParseException( "ADSComponent element couldn't be found for factory: "
+ factory.getName() );
}
return adsElements[0].getAttribute( "componentType" );
}
}
return null;
}
/**
* Generates a new ADSComponent with its schema and cache handle.
*
* @param componentType Type of a component being created
* @param factory a factory reference to create a ADSComponent for.
* @return
*/
private ADSComponent generateADSComponent( String componentType, Factory factory )
{
return null;
}
/**
* Cache the ADSComponent existence on ApacheDS with all of its DIT entries. And then release it from hub.
*
* @param leavingComp ADSComponent reference to cache and release.
*/
private void cacheAndReleaseADSComponent( ADSComponent leavingComp )
{
}
/**
* Registers a HubListener for specified component type.
*
* @param componentType component type to get notifications for.
* @param listener HubListener implementation
*/
public void registerListener( String componentType, HubListener listener )
{
List<HubListener> listenersForComp = listenersMap.get( componentType );
if ( listenersForComp == null )
{
ArrayList<HubListener> list = new ArrayList<HubListener>();
list.add( listener );
listenersMap.put( componentType, list );
}
else
{
if ( !listenersForComp.contains( listener ) )
{
listenersForComp.add( listener );
}
}
}
/**
* Removes the specified listener from the notification chain.
*
* @param listener HubListener implementation
*/
public void removeListener( HubListener listener )
{
Enumeration<List<HubListener>> it = listenersMap.elements();
while ( it.hasMoreElements() )
{
List<HubListener> list = it.nextElement();
if ( list.contains( listener ) )
{
list.remove( listener );
}
}
}
}