001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.framework;
011:
012: import java.util.*;
013: import org.w3c.dom.*;
014: import java.net.URI;
015: import org.mmbase.security.*;
016: import org.mmbase.util.xml.Instantiator;
017: import org.mmbase.util.LocalizedString;
018: import org.mmbase.util.functions.Parameter;
019: import org.mmbase.util.logging.*;
020:
021: /**
022: * A component is a piece of pluggable functionality that typically has dependencies on other
023: * components, and may be requested several blocks.
024: *
025: * @author Michiel Meeuwissen
026: * @version $Id: BasicComponent.java,v 1.44 2008/02/23 12:15:54 michiel Exp $
027: * @since MMBase-1.9
028: */
029: public class BasicComponent implements Component {
030: private static final Logger log = Logging
031: .getLoggerInstance(BasicComponent.class);
032:
033: private final String name;
034: private String bundle;
035: private final LocalizedString description;
036: private final Map<String, Block> blocks = new HashMap<String, Block>();
037: private final Map<String, Setting<?>> settings = new HashMap<String, Setting<?>>();
038: private Block defaultBlock = null;
039: private URI uri;
040: private int version = -1;
041:
042: protected final Collection<Component> dependencies = new HashSet<Component>();
043: protected final Collection<VirtualComponent> unsatisfied = new HashSet<VirtualComponent>();
044:
045: public BasicComponent(String name) {
046: this .name = name;
047: this .description = new LocalizedString(name);
048: }
049:
050: public String getName() {
051: return name;
052: }
053:
054: public URI getUri() {
055: return uri;
056: }
057:
058: public int getVersion() {
059: return version;
060: }
061:
062: public LocalizedString getDescription() {
063: return description;
064: }
065:
066: public void configure(Element el) {
067: try {
068: uri = new URI(el.getOwnerDocument().getDocumentURI());
069: } catch (Exception e) {
070: log.error(e);
071: }
072: log.debug("Configuring " + this );
073: description.fillFromXml("description", el);
074:
075: version = Integer.parseInt(el.getAttribute("version"));
076:
077: {
078: NodeList depElements = el
079: .getElementsByTagName("dependency");
080: for (int i = 0; i < depElements.getLength(); i++) {
081: Element element = (Element) depElements.item(i);
082: String name = element.getAttribute("component");
083: int version = Integer.parseInt(element
084: .getAttribute("version"));
085: Component comp = ComponentRepository.getInstance()
086: .getComponent(name);
087: if (comp != null && comp.getVersion() >= version) {
088: dependencies.add(comp);
089: } else {
090: unsatisfied
091: .add(new VirtualComponent(name, version));
092:
093: }
094: }
095: }
096: {
097: NodeList bundleElements = el.getElementsByTagName("bundle");
098: if (bundleElements.getLength() > 0) {
099: bundle = ((Element) bundleElements.item(0))
100: .getAttribute("name");
101: }
102: }
103:
104: {
105: NodeList settingElements = el
106: .getElementsByTagName("setting");
107: for (int i = 0; i < settingElements.getLength(); i++) {
108: Element element = (Element) settingElements.item(i);
109: Setting s = new Setting(this , element);
110: settings.put(s.getName(), s);
111: }
112: }
113: {
114: NodeList actionElements = el.getElementsByTagName("action");
115: for (int i = 0; i < actionElements.getLength(); i++) {
116: try {
117: Element element = (Element) actionElements.item(i);
118: String actionName = element.getAttribute("name");
119: String rank = element.getAttribute("rank");
120: Object c = Instantiator
121: .getInstanceWithSubElement(element);
122: Action a;
123: if (c != null) {
124: if (!"".equals(rank)) {
125: log.warn("Rank attribute ignored");
126: }
127: a = new Action(name, actionName,
128: (ActionChecker) c);
129: } else {
130: if ("".equals(rank)) {
131: rank = "basic user";
132: }
133: a = new Action(name, actionName,
134: new ActionChecker.Rank(Rank
135: .getRank(rank)));
136: }
137: a.getDescription().fillFromXml("description",
138: element);
139: log.service("Registering action " + a);
140: ActionRepository.getInstance().add(a);
141: } catch (Exception e) {
142: log.error(e);
143: }
144: }
145: }
146:
147: {
148: NodeList blockElements = el.getElementsByTagName("block");
149: if (log.isDebugEnabled()) {
150: log.debug("Found description: " + description);
151: log.debug("Found number of blocks: "
152: + blockElements.getLength());
153: }
154: for (int i = 0; i < blockElements.getLength(); i++) {
155: Element element = (Element) blockElements.item(i);
156: String blockName = element.getAttribute("name");
157: String mimetype = element.getAttribute("mimetype");
158: Block.Type[] classification = Block.Type
159: .getClassification(element
160: .getAttribute("classification"), true);
161: Block b = new Block(blockName, mimetype, this ,
162: classification);
163: b.getDescription().fillFromXml("description", element);
164: b.getTitle().fillFromXml("title", element);
165: log.trace("Found block: " + blockName);
166: b.getRenderers().put(Renderer.Type.HEAD,
167: getRenderer("head", element, b));
168: b.getRenderers().put(Renderer.Type.BODY,
169: getRenderer("body", element, b));
170: b.processor = getProcessor("process", element, b);
171: if (defaultBlock == null)
172: defaultBlock = b;
173: blocks.put(blockName, b);
174: }
175: }
176:
177: String defaultBlockName = el.getAttribute("defaultblock");
178: if (defaultBlockName != null && !defaultBlockName.equals("")) {
179: Block b = blocks.get(defaultBlockName);
180: if (b == null) {
181: log.error("There is no block '" + defaultBlockName
182: + "' so, cannot take it as default. Taking "
183: + defaultBlock + " in stead");
184: } else {
185: defaultBlock = b;
186: }
187: }
188: if (defaultBlock == null) {
189: log.warn("No blocks found.");
190: } else {
191: log.debug("Default block: " + defaultBlock);
192: }
193: }
194:
195: private Renderer getRenderer(String name, Element block, Block b) {
196: NodeList renderElements = block.getElementsByTagName(name);
197: log.debug("Number of [" + name + "] elements: "
198: + renderElements.getLength());
199: if (renderElements.getLength() < 1)
200: return null;
201: Renderer renderer = null;
202: for (int i = 0; i < renderElements.getLength(); i++) {
203: Element renderElement = (Element) renderElements.item(i);
204: String jsp = renderElement.getAttribute("jsp");
205:
206: Renderer subRenderer;
207: if (!"".equals(jsp)) {
208: subRenderer = new JspRenderer(name.toUpperCase(), jsp,
209: b);
210: } else {
211: try {
212: subRenderer = (Renderer) Instantiator
213: .getInstanceWithSubElement(renderElement,
214: name.toUpperCase(), b);
215: } catch (Exception e) {
216: log.error(e.getMessage(), e);
217: return null;
218: }
219: }
220: Parameter[] params = Parameter
221: .readArrayFromXml(renderElement);
222: if (params.length > 0) { // a bit to simple, how can you explicitely make a renderer parameter-less now?
223: b.addParameters(params);
224: }
225: if (renderer == null) {
226: renderer = subRenderer;
227: } else {
228: if (renderer instanceof ChainedRenderer) {
229: ((ChainedRenderer) renderer).add(subRenderer);
230: } else {
231: ChainedRenderer chain = new ChainedRenderer(name
232: .toUpperCase(), b);
233: chain.add(renderer);
234: chain.add(subRenderer);
235: renderer = chain;
236: }
237: }
238: }
239: return renderer;
240:
241: }
242:
243: private Processor getProcessor(String name, Element block, Block b) {
244: NodeList processorElements = block.getElementsByTagName(name);
245: if (processorElements.getLength() < 1)
246: return null;
247: Element processorElement = (Element) processorElements.item(0);
248: String jsp = processorElement.getAttribute("jsp");
249: Processor processor;
250: if (!"".equals(jsp)) {
251: processor = new JspProcessor(jsp, b);
252: } else {
253: try {
254: processor = (Processor) Instantiator
255: .getInstanceWithSubElement(processorElement,
256: name.toUpperCase(), b);
257: } catch (Exception e) {
258: log.error(e);
259: return null;
260: }
261: }
262: Parameter[] params = Parameter
263: .readArrayFromXml(processorElement);
264: if (params.length > 0) { // a bit to simple, how can you explicitely make a processor parameter-less now?
265: b.addParameters(params);
266: }
267: return processor;
268:
269: }
270:
271: public Collection<Block> getBlocks() {
272: return Collections.unmodifiableCollection(blocks.values());
273: }
274:
275: public Block getBlock(String name) {
276: if (name == null)
277: return getDefaultBlock();
278: return blocks.get(name);
279: }
280:
281: public Block getDefaultBlock() {
282: return defaultBlock;
283: }
284:
285: public String toString() {
286: return getName();
287: }
288:
289: public String getBundle() {
290: return bundle;
291: }
292:
293: public Collection<Setting<?>> getSettings() {
294: return settings.values();
295: }
296:
297: public Setting<?> getSetting(String name) {
298: return settings.get(name);
299: }
300:
301: public Collection<Component> getDependencies() {
302: return Collections.unmodifiableCollection(dependencies);
303: }
304:
305: public Collection<VirtualComponent> getUnsatisfiedDependencies() {
306: return Collections.unmodifiableCollection(unsatisfied);
307: }
308:
309: public Map<String, Action> getActions() {
310: return ActionRepository.getInstance().get(getName());
311: }
312:
313: public void resolve(VirtualComponent unsat, Component comp) {
314: unsatisfied.remove(unsat);
315: dependencies.add(comp);
316: }
317: }
|