001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.monitoring.snapshot;
017:
018: import java.io.File;
019: import java.io.FileOutputStream;
020: import java.util.ArrayList;
021:
022: import javax.xml.parsers.DocumentBuilder;
023: import javax.xml.parsers.DocumentBuilderFactory;
024: import javax.xml.parsers.ParserConfigurationException;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.xmlbeans.XmlCursor;
029: import org.apache.xmlbeans.XmlObject;
030: import org.w3c.dom.Document;
031: import org.w3c.dom.Element;
032: import org.w3c.dom.Node;
033: import org.w3c.dom.NodeList;
034:
035: //import com.sun.org.apache.xml.internal.serialize.OutputFormat;
036: //import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
037:
038: /**
039: * In charge of dealing with the XML processing of the snapshot's data.
040: */
041: public class SnapshotConfigXMLBuilder {
042: private static Log log = LogFactory
043: .getLog(SnapshotConfigXMLBuilder.class);
044:
045: private static final String pathToXML = System
046: .getProperty("org.apache.geronimo.home.dir")
047: + "/var/monitoring/snapshot-config.xml";
048:
049: private static final String SNAPSHOT_CONFIG = "snapshot-config";
050: private static final String DURATION = "duration";
051: private static final String RETENTION = "retention";
052: private static final String MBEAN = "mbean";
053:
054: /**
055: * @return A list of all mbean names that have been previously saved.
056: * These mbean names are those to keep track of for per snapshot.
057: */
058: public static ArrayList<String> getMBeanNames() {
059: ArrayList<String> mbeanList = new ArrayList<String>();
060: // get an instance of the document
061: Document doc = openDocument();
062: // get the root element node
063: Element rootElement = doc.getDocumentElement();
064: // get all children in the root node (i.e. all config properties)
065: NodeList configNodes = rootElement.getChildNodes();
066: // find the duration node and save it
067: for (int i = 0; i < configNodes.getLength(); i++) {
068: if (MBEAN.equals(configNodes.item(i).getNodeName())) {
069: mbeanList.add(configNodes.item(i).getTextContent());
070: }
071: }
072: return mbeanList;
073: }
074:
075: /**
076: * Adds to the snapshot-config.xml another configuration element <mbean>
077: * in order to persistently keep track of all user requested statistics.
078: * If there is a duplicate, nothing will be done.
079: */
080: public static boolean removeMBeanName(String mbeanName) {
081: ArrayList<String> mbeanList = getMBeanNames();
082: // operate on the snapshot-config.xml if there exists the mbean name
083: if (mbeanList.contains(mbeanName)) {
084: // get an instance of the document
085: Document doc = openDocument();
086: // get the root element node
087: Element rootElement = doc.getDocumentElement();
088: // find the Node that represents the mbeanName
089: NodeList list = rootElement.getChildNodes();
090: for (int i = 0; i < list.getLength(); i++) {
091: // check the Node's text context for a match with mbeanName
092: if (list.item(i).getTextContent().equals(mbeanName)) {
093: // remove the node from rootElement
094: Node toRemoveNode = list.item(i);
095: rootElement.removeChild(toRemoveNode);
096: break;
097: }
098: }
099: // save the document
100: saveDocument(doc, pathToXML);
101: return true;
102: } else {
103: return false;
104: }
105: }
106:
107: /**
108: * Removes from the snapshot-config.xml a configuration element <mbean>
109: * in order to persistently keep track of all user requested statistics.
110: * If there does not exist an instance of the mbeanNAme, nothing will be done.
111: */
112: public static boolean addMBeanName(String mbeanName) {
113: ArrayList<String> mbeanList = getMBeanNames();
114: if (mbeanList.contains(mbeanName)) {
115: return false;
116: } else {
117: // get an instance of the document
118: Document doc = openDocument();
119: // get the root element node
120: Element rootElement = doc.getDocumentElement();
121: // create <mbean> element
122: Element mbeanElement = doc.createElement(MBEAN);
123: mbeanElement.setTextContent(mbeanName);
124: // add <mbean> element to the rootElement
125: rootElement.appendChild(mbeanElement);
126: try {
127: Thread.sleep(1000);
128: } catch (Exception e) {
129:
130: }
131: // save the document
132: saveDocument(doc, pathToXML);
133: return true;
134: }
135: }
136:
137: /**
138: * Saves the duration of the snapshot as a configuration attribute
139: * @param duration
140: */
141: public static void saveDuration(long duration) {
142: saveAttribute(DURATION, duration);
143: }
144:
145: /**
146: * Saves the retention of the snapshot as a configuration attribute
147: * @param retention
148: */
149: public static void saveRetention(int retention) {
150: saveAttribute(RETENTION, retention);
151: }
152:
153: /**
154: * Saves a generic attribute value into the node with text = attribute name.
155: * Creates one if there is not an instance of one.
156: * @param attrName
157: * @param attributeValue
158: */
159: private static void saveAttribute(String attrName,
160: long attributeValue) {
161: Document doc = openDocument();
162: // get the root node
163: Element rootElement = doc.getDocumentElement();
164: // get all children in the root node (i.e. all config properties)
165: NodeList configNodes = rootElement.getChildNodes();
166: // find the duration node and save it
167: boolean foundNode = false;
168: for (int i = 0; i < configNodes.getLength() && !foundNode; i++) {
169: Node configNode = configNodes.item(i);
170: if (attrName.equals(configNode.getNodeName())) {
171: // found a match
172: configNode.setTextContent(attributeValue + "");
173: foundNode = true;
174: }
175: }
176: // if there was not a duration node, make one
177: if (!foundNode) {
178: Element element = doc.createElement(attrName);
179: element.setTextContent(attributeValue + "");
180: rootElement.appendChild(element);
181: }
182: try {
183: Thread.sleep(1000);
184: } catch (Exception e) {
185:
186: }
187: log.info("***saving: " + attrName + " = " + attributeValue);
188: // save the document to file
189: saveDocument(doc, pathToXML);
190: }
191:
192: /**
193: * Returns the value of the configuration attribute, defined by the key
194: * @param key
195: * @return
196: * @throws Exception
197: */
198: public static String getAttributeValue(String key) throws Exception {
199: // ensure that there exists the 'monitor' directory
200: ensureMonitorDir();
201: // get an instance of the document
202: Document doc = openDocument();
203: // get the root element node
204: Element rootElement = doc.getDocumentElement();
205: // get all children in the root node (i.e. all config properties)
206: NodeList configNodes = rootElement.getChildNodes();
207: // find the duration node and save it
208: for (int i = 0; i < configNodes.getLength(); i++) {
209: if (key.equals(configNodes.item(i).getNodeName())) {
210: return configNodes.item(i).getTextContent();
211: }
212: }
213: throw new Exception("[WARNING] " + key + " is not found in "
214: + SNAPSHOT_CONFIG);
215: }
216:
217: /**
218: * Ensures that there is an existing XML file. Creates one if there
219: * does not exist one already.
220: */
221: public static void checkXMLExists() {
222: File docFile = new File(pathToXML);
223: // create an XML document if it does not exist
224: if (!docFile.exists()) {
225: Document doc = setUpDocument(createDocument());
226: saveDocument(doc, pathToXML);
227: }
228: }
229:
230: /**
231: * Prepares the root element for a document.
232: */
233: public static Document setUpDocument(Document document) {
234: // add <snapshot-config> tag as the root
235: Element rootElement = document.createElement("snapshot-config");
236: document.appendChild(rootElement);
237: return document;
238: }
239:
240: /**
241: * Creates an instance of a Document and returns it
242: */
243: public static Document createDocument() {
244: // get an instance of factory
245: DocumentBuilderFactory dbf = DocumentBuilderFactory
246: .newInstance();
247: try {
248: // get an instance of builder
249: DocumentBuilder db = dbf.newDocumentBuilder();
250: // create an instance of DOM
251: return db.newDocument();
252: } catch (ParserConfigurationException pce) {
253: log
254: .error(
255: "Error while trying to instantiate DocumentBuilder",
256: pce);
257: }
258: return null;
259: }
260:
261: /**
262: * Write the document object to the file location specified by
263: * the path.
264: */
265: public static void saveDocument(Document document, String path) {
266: try {
267: // before saving, make sure the directory is present
268: ensureMonitorDir();
269:
270: //TODO GERONIMO-3719. Hack to use xmlbeans to write out xml instead of sun specific classes.
271: XmlObject xmlObject = XmlObject.Factory.parse(document
272: .getDocumentElement());
273: xmlObject.save(new File(path));
274:
275: // formatting the doc
276: // OutputFormat format = new OutputFormat(document);
277: // format.setIndenting(true);
278: // generate a file output
279: // XMLSerializer serializer = new XMLSerializer(new FileOutputStream(new File(path)), format);
280: // serializer.serialize(document);
281: } catch (Exception e) {
282: log.error(e.getMessage(), e);
283: }
284: }
285:
286: /**
287: * Parses the XML document specified by the private member 'pathToXML'
288: * and stores the information in the a Document object
289: */
290: public static Document openDocument() {
291: // ensure that the XML file is there
292: checkXMLExists();
293: // get the factory
294: DocumentBuilderFactory dbf = DocumentBuilderFactory
295: .newInstance();
296: // continue to attempt to parse
297: while (true) {
298: try {
299: // Using factory get an instance of document builder
300: DocumentBuilder db = dbf.newDocumentBuilder();
301: // parse using builder to get DOM representation of the XML file
302: Document doc = db.parse(pathToXML);
303: return doc;
304: } catch (Exception e) {
305: // Either this file is being read/written to by snapshot thread
306: // or there is an UNKNOWN error
307: log.error(e.getMessage(), e);
308: }
309: }
310: }
311:
312: /**
313: * Checks to see if the GERONIMO_HOME/var/monitoring/ directory was made.
314: * If not, the method creates it.
315: */
316: public static void ensureMonitorDir() {
317: final String pathToDir = System
318: .getProperty("org.apache.geronimo.home.dir")
319: + "/var/monitoring/";
320: File dir = new File(pathToDir);
321: if (dir.exists() && dir.isDirectory()) {
322: // all good
323: return;
324: } else {
325: // make a directory
326: if (dir.mkdir()) {
327: // directory was successfully created
328: log.info("/var/monitoring directory created.");
329: return;
330: } else {
331: log.error("Could not make the directory " + pathToDir);
332: }
333: }
334: }
335: }
|