All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.javasimon.ManagerConfiguration Maven / Gradle / Ivy

The newest version!
package org.javasimon;

import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.javasimon.callback.Callback;
import org.javasimon.callback.CompositeCallback;
import org.javasimon.callback.CompositeCallbackImpl;
import org.javasimon.callback.CompositeFilterCallback;
import org.javasimon.callback.FilterCallback;
import org.javasimon.callback.FilterRule;
import org.javasimon.utils.bean.SimonBeanUtils;

/**
 * Holds configuration for one Simon Manager. Configuration is read from the stream
 * and it is merged with any existing configuration read before. Method {@link #clear()}
 * must be used in order to reset this configuration object.
 * 

* Every {@link org.javasimon.Manager} holds its own configuration and programmer has * to take care of the initialization of the configuration. Default {@link org.javasimon.SimonManager} * is privileged and can be configured via file or resource when Java property {@code javasimon.config.file} * (constant {@link org.javasimon.SimonManager#PROPERTY_CONFIG_FILE_NAME}) * or {@code javasimon.config.resource} (constant * {@link org.javasimon.SimonManager#PROPERTY_CONFIG_RESOURCE_NAME}) is used. *

* Structure of the configuration XML: *

{@code
 * 
 * ... TODO
 * }
* * @author Richard "Virgo" Richter */ // TODO: This class needs serious rethinking, also manager config itself should be independent from the reading // of the config - so it can be set up by Spring for instance public final class ManagerConfiguration { private Map configs; private final Manager manager; /** * Creates manager configuration for a specified manager. * * @param manager manager on whose behalf this configuration is created */ ManagerConfiguration(Manager manager) { this.manager = manager; clear(); } /** Clears any previously loaded configuration. */ public void clear() { configs = new LinkedHashMap<>(); } /** * Reads config from provided buffered reader. Reader is not closed after this method finishes. * * @param reader reader containing configuration */ public synchronized void readConfig(Reader reader) { try { XMLStreamReader xr = XMLInputFactory.newInstance().createXMLStreamReader(reader); try { while (!xr.isStartElement()) { xr.next(); } processStartElement(xr, "simon-configuration"); while (true) { if (isStartTag(xr, "callback")) { manager.callback().addCallback(processCallback(xr)); } else if (isStartTag(xr, "filter-callback")) { manager.callback().addCallback(processFilterCallback(xr)); } else if (isStartTag(xr, "simon")) { processSimon(xr); } else { break; } } assertEndTag(xr, "simon-configuration"); } finally { xr.close(); } } catch (XMLStreamException e) { manager.callback().onManagerWarning(null, e); } catch (SimonException e) { manager.callback().onManagerWarning(e.getMessage(), e); } } private Callback processCallback(XMLStreamReader xr) throws XMLStreamException { Map attrs = processStartElement(xr, "callback"); String klass = attrs.get("class"); if (klass == null) { klass = CompositeCallbackImpl.class.getName(); } Callback callback; try { callback = (Callback) Class.forName(klass).newInstance(); } catch (InstantiationException | ClassCastException | ClassNotFoundException | IllegalAccessException e) { throw new SimonException(e); } processSetAndCallbacks(xr, callback); processEndElement(xr, "callback"); return callback; } private Callback processFilterCallback(XMLStreamReader xr) throws XMLStreamException { Map attrs = processStartElement(xr, "filter-callback"); String klass = attrs.get("class"); if (klass == null) { klass = CompositeFilterCallback.class.getName(); } FilterCallback callback; try { callback = (FilterCallback) Class.forName(klass).newInstance(); } catch (InstantiationException | ClassCastException | ClassNotFoundException | IllegalAccessException e) { throw new SimonException(e); } while (isStartTag(xr, "rule")) { processRule(xr, callback); } processSetAndCallbacks(xr, callback); processEndElement(xr, "filter-callback"); return callback; } private void processSetAndCallbacks(XMLStreamReader xr, Callback callback) throws XMLStreamException { while (isStartTag(xr, "set")) { processSet(xr, callback); } while (true) { if (isStartTag(xr, "callback")) { ((CompositeCallback) callback).addCallback(processCallback(xr)); } else if (isStartTag(xr, "filter-callback")) { ((CompositeCallback) callback).addCallback(processFilterCallback(xr)); } else { break; } } } private void processRule(XMLStreamReader xr, FilterCallback callback) throws XMLStreamException { String pattern = null; FilterRule.Type type = FilterRule.Type.SUFFICE; String condition = null; List events = new ArrayList<>(); Map attrs = processStartElement(xr, "rule"); if (attrs.get("condition") != null) { condition = attrs.get("condition"); } if (attrs.get("type") != null) { type = FilterRule.Type.valueOf(toEnum(attrs.get("type"))); } if (attrs.get("pattern") != null) { pattern = attrs.get("pattern"); } if (attrs.get("events") != null) { String[] sa = attrs.get("events").trim().split(" *, *"); for (String eventName : sa) { events.add(Callback.Event.forCode(eventName)); } } if (isStartTag(xr, "condition")) { xr.next(); condition = getText(xr); processEndElement(xr, "condition"); } processEndElement(xr, "rule"); callback.addRule(type, condition, pattern, events.toArray(new Callback.Event[events.size()])); } private void processSet(XMLStreamReader xr, Callback callback) throws XMLStreamException { Map attrs = processStartElement(xr, "set", "property"); setProperty(callback, attrs.get("property"), attrs.get("value")); processEndElement(xr, "set"); } /** * Sets the callback property. * * @param callback callback object * @param property name of the property * @param value value of the property */ private void setProperty(Callback callback, String property, String value) { try { if (value != null) { SimonBeanUtils.getInstance().setProperty(callback, property, value); } else { callback.getClass().getMethod(setterName(property)).invoke(callback); } } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { throw new SimonException(e); } } private String setterName(String name) { return "set" + name.substring(0, 1).toUpperCase() + name.substring(1); } private void processSimon(XMLStreamReader xr) throws XMLStreamException { Map attrs = processStartElement(xr, "simon", "pattern"); String pattern = attrs.get("pattern"); SimonState state = attrs.get("state") != null ? SimonState.valueOf(toEnum(attrs.get("state"))) : null; configs.put(new SimonPattern(pattern), new SimonConfiguration(state)); processEndElement(xr, "simon"); } /** * Returns configuration for the Simon with the specified name. * * @param name Simon name * @return configuration for that particular Simon */ synchronized SimonConfiguration getConfig(String name) { SimonState state = null; for (Map.Entry entry : configs.entrySet()) { if (entry.getKey().matches(name)) { SimonConfiguration config = entry.getValue(); if (config.getState() != null) { state = config.getState(); } } } return new SimonConfiguration(state); } private String toEnum(String enumVal) { return enumVal.trim().toUpperCase().replace('-', '_'); } // XML Utils private Map processStartElement(XMLStreamReader reader, String elementName, String... requiredAttributes) throws XMLStreamException { Map attrs = processStartElementPrivate(reader, elementName, requiredAttributes); reader.nextTag(); return attrs; } private Map processStartElementPrivate(XMLStreamReader reader, String elementName, String... requiredAttributes) throws XMLStreamException { assertStartTag(reader, elementName); Map attrs = readAttributes(reader); for (String attr : requiredAttributes) { if (!attrs.containsKey(attr)) { throw new XMLStreamException("Attribute '" + attr + "' MUST be present (element: " + elementName + "). " + readerPosition(reader)); } } return attrs; } private void assertStartTag(XMLStreamReader reader, String name) throws XMLStreamException { if (!reader.isStartElement()) { throw new XMLStreamException("Assert start tag - wrong event type " + reader.getEventType() + " (expected name: " + name + ") " + readerPosition(reader)); } assertName(reader, "start tag", name); } private Map readAttributes(XMLStreamReader reader) { Map attributes = new LinkedHashMap<>(); int attrCount = reader.getAttributeCount(); for (int i = 0; i < attrCount; i++) { attributes.put(reader.getAttributeName(i).toString(), reader.getAttributeValue(i)); } return attributes; } private void assertName(XMLStreamReader reader, String operation, String name) throws XMLStreamException { if (!reader.getLocalName().equals(name)) { throw new XMLStreamException("Assert " + operation + " - wrong element name " + reader.getName().toString() + " (expected name: " + name + ") " + readerPosition(reader)); } } private String readerPosition(XMLStreamReader reader) { return "[line: " + reader.getLocation().getLineNumber() + ", column: " + reader.getLocation().getColumnNumber() + "]"; } private void assertEndTag(XMLStreamReader reader, String name) throws XMLStreamException { if (!reader.isEndElement()) { throw new XMLStreamException("Assert end tag - wrong event type " + reader.getEventType() + " (expected name: " + name + ") " + readerPosition(reader)); } assertName(reader, "end tag", name); } private boolean isStartTag(XMLStreamReader reader, String name) { return reader.isStartElement() && reader.getLocalName().equals(name); } private void processEndElement(XMLStreamReader reader, String name) throws XMLStreamException { assertEndTag(reader, name); reader.nextTag(); } private String getText(XMLStreamReader reader) throws XMLStreamException { StringBuilder sb = new StringBuilder(); while (reader.isCharacters()) { sb.append(reader.getText()); reader.next(); } return sb.toString().trim(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy