001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.hivemind.lib.pipeline; 016 017 import java.util.List; 018 019 import org.apache.hivemind.ErrorLog; 020 import org.apache.hivemind.Location; 021 import org.apache.hivemind.impl.BaseLocatable; 022 import org.apache.hivemind.lib.DefaultImplementationBuilder; 023 import org.apache.hivemind.order.Orderer; 024 import org.apache.hivemind.service.ClassFactory; 025 026 /** 027 * Used by the {@link org.apache.hivemind.lib.pipeline.PipelineFactory} to assemble the pipeline. 028 * 029 * @author Howard Lewis Ship 030 */ 031 public class PipelineAssembler extends BaseLocatable 032 { 033 /** @since 1.1 */ 034 private ErrorLog _errorLog; 035 036 private String _serviceId; 037 038 private Class _serviceInterface; 039 040 private Class _filterInterface; 041 042 private ClassFactory _classFactory; 043 044 private DefaultImplementationBuilder _defaultBuilder; 045 046 private Orderer _orderer; 047 048 private Object _terminator; 049 050 private Location _terminatorLocation; 051 052 /** 053 * @param errorLog 054 * used for reporting recoverable errors 055 * @param serviceInterface 056 * the main interface 057 * @param filterInterface 058 * the interface for filters 059 * @param classFactory 060 * for creating new classes 061 * @param defaultBuilder 062 * used to provide a placeholder terminator if no real terminator is supplied 063 * @param servceId 064 * of the service being assembled 065 */ 066 public PipelineAssembler(ErrorLog errorLog, String serviceId, Class serviceInterface, 067 Class filterInterface, ClassFactory classFactory, 068 DefaultImplementationBuilder defaultBuilder) 069 { 070 _errorLog = errorLog; 071 _serviceId = serviceId; 072 _serviceInterface = serviceInterface; 073 _filterInterface = filterInterface; 074 _classFactory = classFactory; 075 _defaultBuilder = defaultBuilder; 076 077 _orderer = new Orderer(_errorLog, "filter"); 078 079 } 080 081 public void addFilter(String name, String prereqs, String postreqs, Object filter, 082 Location location) 083 { 084 if (!checkInterface(_filterInterface, filter, location)) 085 return; 086 087 FilterHolder holder = new FilterHolder(filter, location); 088 089 _orderer.add(holder, name, prereqs, postreqs); 090 } 091 092 public void setTerminator(Object terminator, Location terminatorLocation) 093 { 094 if (_terminator != null) 095 { 096 _errorLog.error(PipelineMessages.duplicateTerminator( 097 terminator, 098 _serviceId, 099 _terminator, 100 _terminatorLocation), terminatorLocation, null); 101 return; 102 } 103 104 if (!checkInterface(_serviceInterface, terminator, terminatorLocation)) 105 return; 106 107 _terminator = terminator; 108 _terminatorLocation = terminatorLocation; 109 } 110 111 // For testing 112 113 Object getTerminator() 114 { 115 return _terminator; 116 } 117 118 private boolean checkInterface(Class interfaceType, Object instance, Location location) 119 { 120 if (interfaceType.isAssignableFrom(instance.getClass())) 121 return true; 122 123 _errorLog.error( 124 PipelineMessages.incorrectInterface(instance, interfaceType, _serviceId), 125 location, 126 null); 127 128 return false; 129 } 130 131 /** 132 * Returns an object that implements the service interface, and integrates any filters for the 133 * pipeline with the 134 */ 135 public Object createPipeline() 136 { 137 List filterHolders = _orderer.getOrderedObjects(); 138 int count = filterHolders.size(); 139 140 BridgeBuilder bb = (count == 0) ? null : new BridgeBuilder(_errorLog, _serviceId, 141 _serviceInterface, _filterInterface, _classFactory); 142 143 Object next = _terminator != null ? _terminator : _defaultBuilder 144 .buildDefaultImplementation(_serviceInterface); 145 146 // Like service interceptors, we work deepest (last) to shallowest (first). 147 148 for (int i = count - 1; i >= 0; i--) 149 { 150 FilterHolder h = (FilterHolder) filterHolders.get(i); 151 Object filter = h.getFilter(); 152 153 next = bb.instantiateBridge(next, filter); 154 } 155 156 return next; 157 } 158 }