001    /*
002    @license.text@  
003     */
004    package biz.hammurapi.metrics.persistent;
005    
006    import java.io.File;
007    import java.util.Properties;
008    
009    import org.w3c.dom.Element;
010    import org.w3c.dom.Node;
011    import org.w3c.dom.NodeList;
012    
013    import biz.hammurapi.config.Component;
014    import biz.hammurapi.config.ConfigurationException;
015    import biz.hammurapi.config.Context;
016    import biz.hammurapi.config.DomConfigurable;
017    import biz.hammurapi.config.MapContext;
018    import biz.hammurapi.metrics.Slice;
019    import biz.hammurapi.metrics.SliceConsumer;
020    import biz.hammurapi.sql.ConnectionPerThreadDataSource;
021    import biz.hammurapi.sql.IdentityManager;
022    import biz.hammurapi.sql.SQLProcessor;
023    import biz.hammurapi.xml.dom.AbstractDomObject;
024    import biz.hammurapi.xml.dom.DOMUtils;
025    
026    
027    /**
028     * @author Pavel Vlasov
029     */
030    public class PersistingSliceConsumerDomConfigurableAdapter implements DomConfigurable, Component, SliceConsumer {    
031        private SliceConsumer master;
032            private ConnectionPerThreadDataSource ds;
033            private SQLProcessor processor;
034            private long from;
035        
036        public void start() throws ConfigurationException {
037            from=System.currentTimeMillis();
038            try {           
039                ds=new ConnectionPerThreadDataSource(
040                            AbstractDomObject.getElementText(configElement, "driver-class"),
041                                            AbstractDomObject.getElementText(configElement, "database-url"),
042                                            AbstractDomObject.getElementText(configElement, "user"),
043                                            AbstractDomObject.getElementText(configElement, "password"),
044                                            null); // TODO - connection initialization nested elements???
045                
046                Properties properties=new Properties();
047                NodeList nl=DOMUtils.selectNodeList(configElement, "name-map");
048                    for (int i=0, l=nl.getLength(); i<l; ++i) {
049                            Element nme = (Element) nl.item(i);
050                    properties.setProperty(nme.getAttribute("key"), DOMUtils.getElementText(nme));
051                }
052                
053                processor=new SQLProcessor(ds, new MapContext(properties));
054                            
055    //            String kmValue=AbstractDomObject.getElementText(configElement, "keep-measurements", cxpa);
056    //            boolean keepMeasurements = kmValue==null ? false : "yes".equalsIgnoreCase(kmValue);
057    //            
058    //            String maxQueueValue=AbstractDomObject.getElementText(configElement, "max-queue", cxpa);
059    //            int maxQueue = maxQueueValue==null ? 1000 : Integer.parseInt(maxQueueValue);
060                
061                String root=AbstractDomObject.getElementText(configElement, "root-category");
062                
063                String historyValue=AbstractDomObject.getElementText(configElement, "history");            
064                long history = historyValue==null ? PersistingSliceConsumer.DAY : toTime(historyValue);
065                
066                String miValue=AbstractDomObject.getElementText(configElement, "maintenance-interval");            
067                long maintenanceInterval = miValue==null ? 10*PersistingSliceConsumer.MINUTE : toTime(miValue);
068                
069                String imValue=AbstractDomObject.getElementText(configElement, "identity-manager");            
070                IdentityManager identityManager = imValue==null ? null : (IdentityManager) Class.forName(imValue).newInstance();
071                
072                master = new PersistingSliceConsumer(
073                            root,
074                        history,
075                        maintenanceInterval,
076                        processor,
077                                            identityManager);            
078    
079                if (master instanceof Component) {
080                    ((Component) master).start();
081                }
082            } catch (Exception e) {
083                throw new ConfigurationException(e);
084                    }
085        }
086    
087        /**
088             * @param historyValue
089             * @return
090             */
091            static long toTime(String timeValue) throws ConfigurationException {
092                    String[] tva=timeValue.trim().split(" ");
093                    long ret=Long.parseLong(tva[0]);
094                    if (tva.length==1) {
095                            return ret;
096                    } else if (tva.length==2) {
097                            if ("sec".equalsIgnoreCase(tva[1])) {
098                                    return ret*PersistingSliceConsumer.SECOND;
099                            } else if ("min".equalsIgnoreCase(tva[1])) {
100                                    return ret*PersistingSliceConsumer.MINUTE;
101                            } else if ("hour".equalsIgnoreCase(tva[1]) || "hours".equalsIgnoreCase(tva[1])) {
102                                    return ret*PersistingSliceConsumer.MONTH;
103                            } else if ("day".equalsIgnoreCase(tva[1]) || "days".equalsIgnoreCase(tva[1])) {
104                                    return ret*PersistingSliceConsumer.DAY;
105                            } else if ("week".equalsIgnoreCase(tva[1]) || "weeks".equalsIgnoreCase(tva[1])) {
106                                    return ret*PersistingSliceConsumer.WEEK;
107                            } else if ("month".equalsIgnoreCase(tva[1]) || "months".equalsIgnoreCase(tva[1])) {
108                                    return ret*PersistingSliceConsumer.MONTH;
109                            } else if ("year".equalsIgnoreCase(tva[1]) || "years".equalsIgnoreCase(tva[1])) {
110                                    return ret*PersistingSliceConsumer.YEAR;
111                            } else {
112                                    throw new ConfigurationException("Invalid time: "+timeValue);                           
113                            }
114                    } else {
115                            throw new ConfigurationException("Invalid time: "+timeValue);
116                    }
117            }
118    
119            public void stop() throws ConfigurationException {
120            if (master instanceof Component) {
121                ((Component) master).stop();
122            }
123            
124            if (ds!=null) {
125                    try {
126                            if (DOMUtils.selectSingleNode(configElement, "output-dir")!=null) {
127                                            PeriodFactory factory=new PeriodFactory(processor);
128                                            SyntheticPeriod root;
129                                            root=factory.getRootPeriod(
130                                                            from, 
131                                                            System.currentTimeMillis(), 
132                                                            Integer.parseInt(DOMUtils.getSingleNonBlankElementText((Element) configElement, "slices")), false);
133                                            
134                                            PeriodVisualizer.generateHtmlDoc(
135                                                            root, 
136                                                            new File(DOMUtils.getSingleNonBlankElementText((Element) configElement, "output-dir")), 
137                                                            Integer.parseInt(DOMUtils.getSingleNonBlankElementText((Element) configElement, "width")), 
138                                                            Integer.parseInt(DOMUtils.getSingleNonBlankElementText((Element) configElement, "height")));
139                            }
140                                                                                    
141                                    ds.shutdown();
142                            } catch (Exception e) {
143                                    throw new ConfigurationException(e);
144                            }
145            }
146        }
147        
148            private Element configElement;
149        
150            public void configure(Node configNode, Context context) throws ConfigurationException {
151                    configElement=(Element) configNode;
152            }
153    
154            public boolean consumeSlice(String category, Slice slice) {
155                    return master.consumeSlice(category, slice);
156            }
157    
158            public void setOwner(Object owner) {
159                    // Ignore               
160            }       
161    }