blob: bfb9b1a729a23b4afd1a54638f6b3b4ca9c1e633 [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation
* Licensed 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.cocoon.blocks;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.avalon.framework.service.ServiceException;
import org.apache.avalon.framework.service.ServiceManager;
/**
* Look for a component in blocks that are connected to the current block.
*
* @version $Id$
*/
public class InterBlockServiceManager extends AbstractLogEnabled implements ServiceManager {
private BlockWiring blockWiring;
private Blocks blocks;
private Map managers = new HashMap();
private boolean called;
/**
* @param blockWiring
* @param blocks
*/
public InterBlockServiceManager(BlockWiring blockWiring, Blocks blocks) {
this.blockWiring = blockWiring;
this.blocks = blocks;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.service.ServiceManager#lookup(java.lang.String)
*/
public Object lookup(String role) throws ServiceException {
ServiceManager manager = this.findServiceManager(role);
if (manager == null) {
throw new ServiceException(role, "Could not find any manager in connected blocks that contains the role");
}
Object component = manager.lookup(role);
// Keep track on what manager that was used so that we can return the component
this.managers.put(component, manager);
return component;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.service.ServiceManager#hasService(java.lang.String)
*/
public boolean hasService(String role) {
ServiceManager manager = this.findServiceManager(role);
return manager != null;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.service.ServiceManager#release(java.lang.Object)
*/
public void release(Object component) {
if (component == null)
return;
ServiceManager manager = (ServiceManager)this.managers.get(component);
if (manager != null) {
manager.release(component);
}
}
/**
* Find a service manager that contains a given role from one of the connected blocks. The component
* managers of the connected blocks are searched in the order they are declared in the block configuration.
* The super block, if there is one, is tried after the connected blocks. This is to make certain that
* a blocks connections is searched before its super blocks connections.
*
* @param role the role to find a service manager for
* @return the found service manager or null if not found
*/
private ServiceManager findServiceManager(String role) {
this.getLogger().debug("findServiceManager: blockId=" + this.blockWiring.getId() + " role=" + role);
// FIXME: Called is used for protection about infinite loops for blocks with circular dependencies.
// It must be made thread safe.
if (called) {
return null;
} else {
this.called = true;
}
ServiceManager manager = null;
try {
Enumeration connectionNames = this.blockWiring.getConnectionNames();
while (connectionNames.hasMoreElements()) {
String blockName = (String)connectionNames.nextElement();
String blockId = this.blockWiring.getBlockId(blockName);
Block block = this.blocks.getBlock(blockId);
// Don't access blocks that isn't setup yet
if (block != null) {
manager = block.getServiceManager();
if (manager != null && manager.hasService(role)) {
return manager;
}
} else {
this.getLogger().debug("Serching for role=" + role + " in blockId=" + blockId + " that isn't setup.");
}
}
String superId = this.blockWiring.getBlockId(Block.SUPER);
if (superId != null) {
Block superBlock = this.blocks.getBlock(superId);
// Don't access blocks that isn't setup yet
if (superBlock != null) {
manager = superBlock.getServiceManager();
if (manager.hasService(role)) {
return manager;
}
} else {
this.getLogger().debug("Serching for role=" + role + " in blockId=" + superId + " that isn't setup.");
}
}
} finally {
this.called = false;
}
return null;
}
}