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 }