[rhq] Branch 'mtho11/dual-slider-chart-control' - 4 commits - modules/enterprise
by mike thompson
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java | 42
modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js |12891 +++++-----
modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js | 9
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js | 155
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js | 6
6 files changed, 7010 insertions(+), 6095 deletions(-)
New commits:
commit 29b1871084bb26e56aed03de01af0f079a0bd1aa
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 14:51:23 2013 -0700
[BZ 958754] Time units should have proper units for multi-line graphs. Updated the nvd3 javascript libraries to 0.9.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
index e405d2e..a547f21 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
@@ -135,7 +135,11 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
gravity = gravity || 's';
dist = dist || 20;
- var body = parentContainer ? parentContainer : document.getElementsByTagName('body')[0];
+ var body = parentContainer;
+ if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {
+ //If the parent element is an SVG element, place tooltip in the <body> element.
+ body = document.getElementsByTagName('body')[0];
+ }
container.innerHTML = content;
container.style.left = 0;
@@ -351,6 +355,19 @@ nv.utils.pjax = function(links, content) {
});
}
+/* For situations where we want to approximate the width in pixels for an SVG:text element.
+Most common instance is when the element is in a display:none; container.
+Forumla is : text.length * font-size * constant_factor
+*/
+nv.utils.calcApproxTextWidth = function (svgTextElem) {
+ if (svgTextElem instanceof d3.selection) {
+ var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""));
+ var textLength = svgTextElem.text().length;
+
+ return textLength * fontSize * 0.5;
+ }
+ return 0;
+};
nv.models.axis = function() {
//============================================================
@@ -1633,7 +1650,7 @@ nv.models.bulletChart = function() {
//------------------------------------------------------------
dispatch.on('tooltipShow', function(e) {
- e.key = data[0].title;
+ e.key = d.title;
if (tooltips) showTooltip(e, that.parentNode);
});
@@ -1788,6 +1805,7 @@ nv.models.cumulativeLineChart = function() {
, state = { index: 0, rescaleY: rescaleY }
, defaultState = null
, noData = 'No Data Available.'
+ , average = function(d) { return d.average }
, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
@@ -1985,6 +2003,7 @@ nv.models.cumulativeLineChart = function() {
gEnter.append('g').attr('class', 'nv-y nv-axis');
gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
+ gEnter.append('g').attr('class', 'nv-avgLinesWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
@@ -2047,8 +2066,6 @@ nv.models.cumulativeLineChart = function() {
.text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
}
-
-
//------------------------------------------------------------
// Main Chart Component(s)
@@ -2066,16 +2083,51 @@ nv.models.cumulativeLineChart = function() {
.height(availableHeight)
.color(data.map(function(d,i) {
return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled }));
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
+ .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
//d3.transition(linesWrap).call(lines);
linesWrap.call(lines);
+ /*Handle average lines [AN-612] ----------------------------*/
+
+ //Store a series index number in the data array.
+ data.forEach(function(d,i) {
+ d.seriesIndex = i;
+ });
+
+ var avgLineData = data.filter(function(d) {
+ return !d.disabled && !!average(d);
+ });
+
+ var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
+ .data(avgLineData, function(d) { return d.key; });
+
+ avgLines.enter()
+ .append('line')
+ .style('stroke-width',2)
+ .style('stroke-dasharray','10,10')
+ .style('stroke',function (d,i) {
+ return lines.color()(d,d.seriesIndex);
+ })
+ .attr('x1',0)
+ .attr('x2',availableWidth)
+ .attr('y1', function(d) { return y(average(d)); })
+ .attr('y2', function(d) { return y(average(d)); });
+
+ avgLines
+ .attr('x1',0)
+ .attr('x2',availableWidth)
+ .attr('y1', function(d) { return y(average(d)); })
+ .attr('y2', function(d) { return y(average(d)); });
+
+ avgLines.exit().remove();
+
+ //Create index line -----------------------------------------
var indexLine = linesWrap.selectAll('.nv-indexLine')
.data([index]);
@@ -2349,6 +2401,12 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.average = function(_) {
+ if(!arguments.length) return average;
+ average = _;
+ return chart;
+ };
+
//============================================================
@@ -2359,6 +2417,9 @@ nv.models.cumulativeLineChart = function() {
/* Normalize the data according to an index point. */
function indexify(idx, data) {
return data.map(function(line, i) {
+ if (!line.values) {
+ return line;
+ }
var v = lines.y()(line.values[idx], idx);
//TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
@@ -3533,9 +3594,13 @@ nv.models.indentedTree = function() {
// NEW ALIGNING CODE, TODO: clean up
if (align) {
+
var seriesWidths = [];
series.each(function(d,i) {
- seriesWidths.push(d3.select(this).select('text').node().getComputedTextLength() + 28); // 28 is ~ the width of the circle plus some padding
+ var legendText = d3.select(this).select('text');
+ var svgComputedTextLength = legendText.node().getComputedTextLength()
+ || nv.utils.calcApproxTextWidth(legendText);
+ seriesWidths.push(svgComputedTextLength + 28); // 28 is ~ the width of the circle plus some padding
});
//nv.log('Series Widths: ', JSON.stringify(seriesWidths));
@@ -4002,7 +4067,7 @@ nv.models.lineChart = function() {
// New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else
if (offsetElement) {
var svg = d3.select(offsetElement).select('svg');
- var viewBox = svg.attr('viewBox');
+ var viewBox = (svg.node()) ? svg.attr('viewBox') : null;
if (viewBox) {
viewBox = viewBox.split(' ');
var ratio = parseInt(svg.style('width')) / viewBox[2];
@@ -6160,10 +6225,11 @@ nv.models.multiBar = function() {
groups.enter().append('g')
.style('stroke-opacity', 1e-6)
.style('fill-opacity', 1e-6);
- d3.transition(groups.exit())
- //.style('stroke-opacity', 1e-6)
- //.style('fill-opacity', 1e-6)
+
+
+ groups.exit()
.selectAll('rect.nv-bar')
+ .transition()
.delay(function(d,i) { return i * delay/ data[0].values.length })
.attr('y', function(d) { return stacked ? y0(d.y0) : y0(0) })
.attr('height', 0)
@@ -6259,7 +6325,7 @@ nv.models.multiBar = function() {
if (stacked)
- d3.transition(bars)
+ bars.transition()
.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('y', function(d,i) {
@@ -6443,13 +6509,14 @@ nv.models.multiBarChart = function() {
, controls = nv.models.legend()
;
- var margin = {top: 30, right: 20, bottom: 30, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 60}
, width = null
, height = null
, color = nv.utils.defaultColor()
, showControls = true
, showLegend = true
, reduceXTicks = true // if false a tick will show for every data point
+ , staggerLabels = false
, rotateLabels = 0
, tooltips = true
, tooltip = function(key, x, y, e, graph) {
@@ -6664,6 +6731,27 @@ nv.models.multiBarChart = function() {
.selectAll('line, text')
.style('opacity', 1)
+ if (staggerLabels) {
+ var getTranslate = function(x,y) {
+ return "translate(" + x + "," + y + ")";
+ };
+
+ var staggerUp = 5, staggerDown = 17; //pixels to stagger by
+ // Issue #140
+ xTicks
+ .selectAll("text")
+ .attr('transform', function(d,i,j) {
+ return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));
+ });
+
+ var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;
+ g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text")
+ .attr("transform", function(d,i) {
+ return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);
+ });
+ }
+
+
if (reduceXTicks)
xTicks
.filter(function(d,i) {
@@ -6853,6 +6941,12 @@ nv.models.multiBarChart = function() {
return chart;
}
+ chart.staggerLabels = function(_) {
+ if (!arguments.length) return staggerLabels;
+ staggerLabels = _;
+ return chart;
+ };
+
chart.tooltip = function(_) {
if (!arguments.length) return tooltip;
tooltip = _;
@@ -9327,7 +9421,7 @@ nv.models.scatter = function() {
})
);
- x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x }).concat(forceX)))
+ x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
if (padData && data[0])
x.range([(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
@@ -9353,6 +9447,14 @@ nv.models.scatter = function() {
y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])
: y.domain([-1,1]);
+ if ( isNaN(x.domain()[0])) {
+ x.domain([-1,1]);
+ }
+
+ if ( isNaN(y.domain()[0])) {
+ y.domain([-1,1]);
+ }
+
x0 = x0 || x;
y0 = y0 || y;
@@ -9399,8 +9501,16 @@ nv.models.scatter = function() {
return group.values
.map(function(point, pointIndex) {
// *Adding noise to make duplicates very unlikely
- // **Injecting series and point index for reference
- return [x(getX(point,pointIndex)) * (Math.random() / 1e12 + 1) , y(getY(point,pointIndex)) * (Math.random() / 1e12 + 1), groupIndex, pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates
+ // *Injecting series and point index for reference
+ /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.
+ */
+ var pX = getX(point,pointIndex) + Math.random() * 1e-10;
+ var pY = getY(point,pointIndex) + Math.random() * 1e-10;
+
+ return [x(pX),
+ y(pY),
+ groupIndex,
+ pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates
})
.filter(function(pointArray, pointIndex) {
return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!
@@ -9467,7 +9577,12 @@ nv.models.scatter = function() {
.attr('class', function(d,i) { return 'nv-path-'+i; });
pointPaths.exit().remove();
pointPaths
- .attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
+ .attr('d', function(d) {
+ if (d.data.length === 0)
+ return 'M 0 0'
+ else
+ return 'M' + d.data.join('L') + 'Z';
+ });
pointPaths
.on('click', function(d) {
@@ -11277,7 +11392,7 @@ nv.models.sparklinePlus = function() {
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
- var currentValue = sparkline.y()(data[data.length-1], data.length-1);
+
chart.update = function() { chart(selection) };
chart.container = this;
@@ -11304,6 +11419,8 @@ nv.models.sparklinePlus = function() {
container.selectAll('.nv-noData').remove();
}
+ var currentValue = sparkline.y()(data[data.length-1], data.length-1);
+
//------------------------------------------------------------
@@ -11350,7 +11467,7 @@ nv.models.sparklinePlus = function() {
var valueWrap = g.select('.nv-valueWrap');
-
+
var value = valueWrap.selectAll('.nv-currentValue')
.data([currentValue]);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js
new file mode 100644
index 0000000..dc28049
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.min.js
@@ -0,0 +1,6 @@
+(function(){function t(e,t){return(new Date(t,e+1,0)).getDate()}function n(e,t,n){return function(r,i,s){var o=e(r),u=[];o<r&&t(o);if(s>1)while(o<i){var a=new Date(+o);n(a)%s===0&&u.push(a),t(o)}else while(o<i)u.push(new Date(+o)),t(o);return u}}var e=window.nv||{};e.version="0.0.1a",e.dev=!0,window.nv=e,e.tooltip={},e.utils={},e.models={},e.charts={},e.graphs=[],e.logs={},e.dispatch=d3.dispatch("render_start","render_end"),e.dev&&(e.dispatch.on("render_start",function(t){e.logs.startTime=+(new Date)}),e.dispatch.on("render_end",function(t){e.logs.endTime=+(new Date),e.logs.totalTime=e.logs.endTime-e.logs.startTime,e.log("total",e.logs.totalTime)})),e.log=function(){if(e.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(e.dev&&console.log&&Function.prototype.bind){var t=Function.prototype.bind.call(console.log,console);t.apply(console,arguments)}return arguments[arguments.length-1]},e.render=function(n){n=n||1,e.render.active=!0,e.dispatch.rend
er_start(),setTimeout(function(){var t,r;for(var i=0;i<n&&(r=e.render.queue[i]);i++)t=r.generate(),typeof r.callback==typeof Function&&r.callback(t),e.graphs.push(t);e.render.queue.splice(0,i),e.render.queue.length?setTimeout(arguments.callee,0):(e.render.active=!1,e.dispatch.render_end())},0)},e.render.active=!1,e.render.queue=[],e.addGraph=function(t){typeof arguments[0]==typeof Function&&(t={generate:arguments[0],callback:arguments[1]}),e.render.queue.push(t),e.render.active||e.render()},e.identity=function(e){return e},e.strip=function(e){return e.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(e){return new Date(e.getFullYear(),e.getMonth(),0)},d3.time.monthEnds=n(d3.time.monthEnd,function(e){e.setUTCDate(e.getUTCDate()+1),e.setDate(t(e.getMonth()+1,e.getFullYear()))},function(e){return e.getMonth()}),function(){var t=window.nv.tooltip={};t.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip"),r=r||"s",i=i||20;var a=
s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.innerHTML=n,u.style.left=0,u.style.top=0,u.style.opacity=0,a.appendChild(u);var f=parseInt(u.offsetHeight),l=parseInt(u.offsetWidth),c=e.utils.windowSize().width,h=e.utils.windowSize().height,p=window.scrollY,d=window.scrollX,v,m;h=window.innerWidth>=document.body.scrollWidth?h:h-16,c=window.innerHeight>=document.body.scrollHeight?c:c-16;var g=function(e){var t=m;do isNaN(e.offsetTop)||(t+=e.offsetTop);while(e=e.offsetParent);return t},y=function(e){var t=v;do isNaN(e.offsetLeft)||(t+=e.offsetLeft);while(e=e.offsetParent);return t};switch(r){case"e":v=t[0]-l-i,m=t[1]-f/2;var b=y(u),w=g(u);b<d&&(v=t[0]+i>d?t[0]+i:d-b+v),w<p&&(m=p-w+m),w+f>p+h&&(m=p+h-w+m-f);break;case"w":v=t[0]+i,m=t[1]-f/2,b+l>c&&(v=t[0]-l-i),w<p&&(m=p+5),w+f>p+h&&(m=p-f-5);break;case"n":v=t[0]-l/2-5,m=t[1]+i;var b=y(u),w=g(u);b<d&&(v=d+5),b+l>c&&(v=v-l/2+5),w+f>p+h&&(m=p+h-w+m-f);break;case"s":v=t[0]-l/2,m=t[1]-f-i;var b=y(u),w=
g(u);b<d&&(v=d+5),b+l>c&&(v=v-l/2+5),p>w&&(m=p)}return u.style.left=v+"px",u.style.top=m+"px",u.style.opacity=1,u.style.position="absolute",u.style.pointerEvents="none",u},t.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){var t=windo
w.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.sta
te)})},e.utils.calcApproxTextWidth=function(e){if(e instanceof d3.selection){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.models.axis=function(){function d(r){return r.each(function(r){var d=d3.select(this),v=d.selectAll("g.nv-wrap.nv-axis").data([r]),m=v.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),g=m.append("g"),y=v.select("g");h!==null?e.ticks(h):(e.orient()=="top"||e.orient()=="bottom")&&e.ticks(Math.abs(i.range()[1]-i.range()[0])/100),d3.transition(y).call(e),p=p||e.scale();var b=e.tickFormat();b==null&&(b=p.tickFormat());var w=y.selectAll("text.nv-axislabel").data([s||null]);w.exit().remove();switch(e.orient()){case"top":w.enter().append("text").attr("class","nv-axislabel");var E=i.range().length==2?i.range()[1]:i.range()[i.range().length-1]+(i.range()[1]-i.range()[0]);w.attr("text-anchor","middle").attr("y",0).attr("x",E/2);if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g"
).attr("class","nv-axisMaxMin").append("text"),S.exit().remove(),S.attr("transform",function(e,t){return"translate("+i(e)+",0)"}).select("text").attr("dy","0em").attr("y",-e.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate("+i.range()[t]+",0)"})}break;case"bottom":var x=36,T=30,N=y.selectAll("g").select("text");if(a%360){N.each(function(e,t){var n=this.getBBox().width;n>T&&(T=n)});var C=Math.abs(Math.sin(a*Math.PI/180)),x=(C?C*T:T)+30;N.attr("transform",function(e,t,n){return"rotate("+a+" 0,0)"}).attr("text-anchor",a%360>0?"start":"end")}w.enter().append("text").attr("class","nv-axislabel");var E=i.range().length==2?i.range()[1]:i.range()[i.range().length-1]+(i.range()[1]-i.range()[0]);w.attr("text-anchor","middle").attr("y",x).attr("x",E/2);if(o){var S=v.selectAll("g.nv-axisMaxMin").data([i.domain()[0],i.domain()[i.domain().length-1]]);S.enter().append(
"g").attr("class","nv-axisMaxMin").append("text"),S.exit().remove(),S.attr("transform",function(e,t){return"translate("+(i(e)+(c?i.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",e.tickPadding()).attr("transform",function(e,t,n){return"rotate("+a+" 0,0)"}).attr("text-anchor",a?a%360>0?"start":"end":"middle").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate("+(i(e)+(c?i.rangeBand()/2:0))+",0)"})}l&&N.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":w.enter().append("text").attr("class","nv-axislabel"),w.attr("text-anchor",f?"middle":"begin").attr("transform",f?"rotate(90)":"").attr("y",f?-Math.max(t.right,n)+12:-10).attr("x",f?i.range()[0]/2:e.tickPadding());if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),S.exit().remove(),S.attr("transf
orm",function(e,t){return"translate(0,"+i(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",e.tickPadding()).attr("text-anchor","start").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transform",function(e,t){return"translate(0,"+i.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":w.enter().append("text").attr("class","nv-axislabel"),w.attr("text-anchor",f?"middle":"end").attr("transform",f?"rotate(-90)":"").attr("y",f?-Math.max(t.left,n)+12:-10).attr("x",f?-i.range()[0]/2:-e.tickPadding());if(o){var S=v.selectAll("g.nv-axisMaxMin").data(i.domain());S.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),S.exit().remove(),S.attr("transform",function(e,t){return"translate(0,"+p(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-e.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=b(e);return(""+n).match("NaN")?"":n}),d3.transition(S).attr("transfor
m",function(e,t){return"translate(0,"+i.range()[t]+")"}).select("text").style("opacity",1)}}w.text(function(e){return e}),o&&(e.orient()==="left"||e.orient()==="right")&&(y.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(i(e)<i.range()[1]+10||i(e)>i.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),i.domain()[0]==i.domain()[1]&&i.domain()[0]==0&&v.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(o&&(e.orient()==="top"||e.orient()==="bottom")){var k=[];v.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?k.push(i(e)-this.getBBox().width-4):k.push(i(e)+this.getBBox().width+4)}catch(n){t?k.push(i(e)-4):k.push(i(e)+4)}}),y.selectAll("g").each(function(e,t){if(i(e)<k[0]||i(e)>k[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}u&&y.selectAll("line.tick").filter(function(e){return!parseFloat(Math.round(e*1
e5)/1e6)}).classed("zero",!0),p=i.copy()}),d}var e=d3.svg.axis(),t={top:0,right:0,bottom:0,left:0},n=75,r=60,i=d3.scale.linear(),s=null,o=!0,u=!0,a=0,f=!0,l=!1,c=!1,h=null;e.scale(i).orient("bottom").tickFormat(function(e){return e});var p;return d.axis=e,d3.rebind(d,e,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(d,i,"domain","range","rangeBand","rangeBands"),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.ticks=function(e){return arguments.length?(h=e,d):h},d.height=function(e){return arguments.length?(r=e,d):r},d.axisLabel=function(e){return arguments.length?(s=e,d):s},d.showMaxMin=function(e){return arguments.length?(o=e,d):o},d.highlightZero=function(e){return arguments.len
gth?(u=e,d):u},d.scale=function(t){return arguments.length?(i=t,e.scale(i),c=typeof i.rangeBands=="function",d3.rebind(d,i,"domain","range","rangeBand","rangeBands"),d):i},d.rotateYLabel=function(e){return arguments.length?(f=e,d):f},d.rotateLabels=function(e){return arguments.length?(a=e,d):a},d.staggerLabels=function(e){return arguments.length?(l=e,d):l},d},e.models.historicalBar=function(){function g(e){return e.each(function(e){var g=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);s.domain(d||d3.extent(e[0].values.map(u).concat(f))),c?s.range([g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range([0,g]),o.domain(v||d3.extent(e[0].values.map(a).concat(l))).range([b,0]);if(s.domain()[0]===s.domain()[1]||o.domain()[0]===o.domain()[1])singlePoint=!0;s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.
domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var E=w.selectAll("g.nv-wrap.nv-bar").data([e[0].values]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-bar"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-bars"),E.attr("transform","translate("+t.left+","+t.top+")"),w.on("click",function(e,t){m.chartClick({data:e,index:t,pos:d3.event,id:i})}),T.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),E.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",b),C.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var k=E.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e});k.exit().remove();var L=k.enter().append("rect").attr("x",0).attr("y",function(e,t){return o(Math.max(0,a(e,t)))}).attr("height",function(e,t){return Math.abs(o(a(e,t))-o(0))}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),m.elementMouseover({point:t,series:e[0],pos:[
s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),m.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){m.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){m.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});k.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).attr("transform",function(t,n){return"translate("+(s(u(t,n))-g/e[0].values.length*.45)+",0)"}).attr("width",g/e[0].values.length*.9),d3.transition(k).attr("y",function(e,t){return a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t))}).attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)})}),g}var t={top:0,right:0,bottom:0,left:0
},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return g.dispatch=m,g.x=function(e){return arguments.length?(u=e,g):u},g.y=function(e){return arguments.length?(a=e,g):a},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.xScale=function(e){return arguments.length?(s=e,g):s},g.yScale=function(e){return arguments.length?(o=e,g):o},g.xDomain=function(e){return arguments.length?(d=e,g):d},g.yDomain=function(e){return arguments.length?(v=
e,g):v},g.forceX=function(e){return arguments.length?(f=e,g):f},g.forceY=function(e){return arguments.length?(l=e,g):l},g.padData=function(e){return arguments.length?(c=e,g):c},g.clipEdge=function(e){return arguments.length?(h=e,g):h},g.color=function(t){return arguments.length?(p=e.utils.getColor(t),g):p},g.id=function(e){return arguments.length?(i=e,g):i},g},e.models.bullet=function(){function p(e){return e.each(function(e,n){var l=a-t.left-t.right,p=f-t.top-t.bottom,d=d3.select(this),v=i.call(this,e,n).slice().sort(d3.descending),m=s.call(this,e,n).slice().sort(d3.descending),g=o.call(this,e,n).slice().sort(d3.descending),y=d3.scale.linear().domain(d3.extent(d3.merge([u,v]))).range(r?[l,0]:[0,l]),b=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(y.range());this.__chart__=y;var w=d3.min(v),E=d3.max(v),S=v[1],x=d.selectAll("g.nv-wrap.nv-bullet").data([e]),T=x.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),N=T.append("g"),C=x.select("g");N.append("re
ct").attr("class","nv-range nv-rangeMax"),N.append("rect").attr("class","nv-range nv-rangeAvg"),N.append("rect").attr("class","nv-range nv-rangeMin"),N.append("rect").attr("class","nv-measure"),N.append("path").attr("class","nv-markerTriangle"),x.attr("transform","translate("+t.left+","+t.top+")");var k=function(e){return Math.abs(b(e)-b(0))},L=function(e){return Math.abs(y(e)-y(0))},A=function(e){return e<0?b(e):b(0)},O=function(e){return e<0?y(e):y(0)};C.select("rect.nv-rangeMax").attr("height",p).attr("width",L(E>0?E:w)).attr("x",O(E>0?E:w)).datum(E>0?E:w),C.select("rect.nv-rangeAvg").attr("height",p).attr("width",L(S)).attr("x",O(S)).datum(S),C.select("rect.nv-rangeMin").attr("height",p).attr("width",L(E)).attr("x",O(E)).attr("width",L(E>0?w:E)).attr("x",O(E>0?w:E)).datum(E>0?w:E),C.select("rect.nv-measure").style("fill",c).attr("height",p/3).attr("y",p/3).attr("width",g<0?y(0)-y(g[0]):y(g[0])-y(0)).attr("x",O(g)).on("mouseover",function(){h.elementMouseover({value:g[0],
label:"Current",pos:[y(g[0]),p/2]})}).on("mouseout",function(){h.elementMouseout({value:g[0],label:"Current"})});var M=p/6;m[0]?C.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+y(m[0])+","+p/2+")"}).attr("d","M0,"+M+"L"+M+","+ -M+" "+ -M+","+ -M+"Z").on("mouseover",function(){h.elementMouseover({value:m[0],label:"Previous",pos:[y(m[0]),p/2]})}).on("mouseout",function(){h.elementMouseout({value:m[0],label:"Previous"})}):C.selectAll("path.nv-markerTriangle").remove(),x.selectAll(".nv-range").on("mouseover",function(e,t){var n=t?t==1?"Mean":"Minimum":"Maximum";h.elementMouseover({value:e,label:n,pos:[y(e),p/2]})}).on("mouseout",function(e,t){var n=t?t==1?"Mean":"Minimum":"Maximum";h.elementMouseout({value:e,label:n})})}),p}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=[0],a=380,f=30,l=null,c=e.utils.getColor(["#1f77b4"]),h=d3.dispatch("ele
mentMouseover","elementMouseout");return p.dispatch=h,p.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",p):n},p.ranges=function(e){return arguments.length?(i=e,p):i},p.markers=function(e){return arguments.length?(s=e,p):s},p.measures=function(e){return arguments.length?(o=e,p):o},p.forceX=function(e){return arguments.length?(u=e,p):u},p.width=function(e){return arguments.length?(a=e,p):a},p.height=function(e){return arguments.length?(f=e,p):f},p.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,p):t},p.tickFormat=function(e){return arguments.length?(l=e,p):l},p.color=function(t){return arguments.length?(c=e.utils.getColor(t),p):c},p},e.models.bulletChart=function(){function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width")
)||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=
A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("
y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"co
lor"),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){function C(e){return e.each(function(d){function P(e,t){d3.select(C.container).style("
cursor","ew-resize")}function H(e,t){T.x=d3.event.x,T.i=Math.round(x.invert(T.x)),K()}function B(e,t){d3.select(C.container).style("cursor","auto"),y.index=T.i,S.stateChange(y)}function K(){J.data([T]),C.update()}var L=d3.select(this).classed("nv-chart-"+g,!0),A=this,O=(a||parseInt(L.style("width"))||960)-o.left-o.right,M=(f||parseInt(L.style("height"))||400)-o.top-o.bottom;C.update=function(){C(e)},C.container=this,y.disabled=d.map(function(e){return!!e.disabled});if(!b){var _;b={};for(_ in y)y[_]instanceof Array?b[_]=y[_].slice(0):b[_]=y[_]}var D=d3.behavior.drag().on("dragstart",P).on("drag",H).on("dragend",B);if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var j=L.selectAll(".nv-noData").data([w]);return j.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),j.attr("x",o.left+O/2).attr("y",o.top+M/2).text(function(e){return e}),C}L.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();if(!p){
var F=d.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),I=[d3.min(F,function(e){return e[0]}),d3.max(F,function(e){return e[1]})];t.yDomain(I)}else t.yDomain(null);x.domain([0,d[0].values.length-1]).range([0,O]).clamp(!0);var d=k(T.i,d),q=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([d]),R=q.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),U=q.select("g");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-background"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-avgLinesWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),l&&(i.width(O),U.select(".nv-legendWrap").datum(d).call(i),o.top!=i.height()&&(o.top=i.height(),M=(f||parseInt(L.style("height"))||400)-o.top-o.bottom),U.select(".nv-lege
ndWrap").attr("transform","translate(0,"+ -o.top+")"));if(h){var z=[{key:"Re-scale y-axis",disabled:!p}];s.width(140).color(["#444","#444","#444"]),U.select(".nv-controlsWrap").datum(z).attr("transform","translate(0,"+ -o.top+")").call(s)}q.attr("transform","translate("+o.left+","+o.top+")");var W=d.filter(function(e){return e.tempDisabled});q.select(".tempDisabled").remove(),W.length&&q.append("text").attr("class","tempDisabled").attr("x",O/2).attr("y","-.71em").style("text-anchor","end").text(W.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),R.select(".nv-background").append("rect"),U.select(".nv-background rect").attr("width",O).attr("height",M),t.y(function(e){return e.display.y}).width(O).height(M).color(d.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!d[t].disabled&&!d[t].tempDisabled}));var X=U.select(".nv-linesWrap").datum(d.filter(function(e){return!e.disabled&&!e.tempDisabled}));X.call(t),d.for
Each(function(e,t){e.seriesIndex=t});var V=d.filter(function(e){return!e.disabled&&!!E(e)}),$=U.select(".nv-avgLinesWrap").selectAll("line").data(V,function(e){return e.key});$.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",O).attr("y1",function(e){return m(E(e))}).attr("y2",function(e){return m(E(e))}),$.attr("x1",0).attr("x2",O).attr("y1",function(e){return m(E(e))}).attr("y2",function(e){return m(E(e))}),$.exit().remove();var J=X.selectAll(".nv-indexLine").data([T]);J.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).call(D),J.attr("transform",function(e){return"translate("+x(e.i)+",0)"}).attr("height",M),n.scale(v).ticks(Math.min(d[0].values.length,O/70)).tickSize(-M,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),d3.transition(U.select(".nv-x.nv-a
xis")).call(n),r.scale(m).ticks(M/36).tickSize(-O,0),d3.transition(U.select(".nv-y.nv-axis")).call(r),U.select(".nv-background rect").on("click",function(){T.x=d3.mouse(this)[0],T.i=Math.round(x.invert(T.x)),y.index=T.i,S.stateChange(y),K()}),t.dispatch.on("elementClick",function(e){T.i=e.pointIndex,T.x=x(T.i),y.index=T.i,S.stateChange(y),K()}),s.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,p=!t.disabled,y.rescaleY=p,S.stateChange(y),e.call(C)}),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,q.selectAll(".nv-series").classed("disabled",!1),e}),y.disabled=d.map(function(e){return!!e.disabled}),S.stateChange(y),e.call(C)}),S.on("tooltipShow",function(e){c&&N(e,A.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(d.forEach(function(e,n){e.disabled=t.disabled[n]}),y.disabled=t.disabled),typeof t.index!="undefined"&&(T.i=t.index,T.
x=x(T.i),y.index=t.index,J.data([T])),typeof t.rescaleY!="undefined"&&(p=t.rescaleY),e.call(C)})}),C}function k(e,n){return n.map(function(n,r){if(!n.values)return n;var i=t.y()(n.values[e],e);return i<-0.95?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values=n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-i)/(1+i)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:30,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},v,m,g=t.id(),y={index:0,rescaleY:p},b=null,w="No Data Available.",E=function(e){return e.average},S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.orient("bottom").tickPadding(7),r.orient("left");var x=d3.scale.linear(),T={i:0,x:0},N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickF
ormat()(t.y()(i.point,i.pointIndex)),l=d(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),C.dispatch=S,C.lines=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"defined","isArea","x","y","size","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(a=e,C):a},C.height=function(e){return arguments.length?(f=e,C):f},C.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),C):u},C.rescaleY=fu
nction(e){return arguments.length?(p=e,p):p},C.showControls=function(e){return arguments.length?(h=e,C):h},C.showLegend=function(e){return arguments.length?(l=e,C):l},C.tooltips=function(e){return arguments.length?(c=e,C):c},C.tooltipContent=function(e){return arguments.length?(d=e,C):d},C.state=function(e){return arguments.length?(y=e,C):y},C.defaultState=function(e){return arguments.length?(b=e,C):b},C.noData=function(e){return arguments.length?(w=e,C):w},C.average=function(e){return arguments.length?(E=e,C):E},C},e.models.discreteBar=function(){function b(e){return e.each(function(e){var i=n-t.left-t.right,b=r-t.top-t.bottom,w=d3.select(this);e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e});var E=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(E).map(function(e){return e.x})).rangeBands([0,i],.1),o.domain(d||d3.extent(d3.merge(E).map(function(e){return e.y}).conc
at(f))),c?o.range([b-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range([b,0]),g=g||s,y=y||o.copy().range([o(0),o(0)]);var S=w.selectAll("g.nv-wrap.nv-discretebar").data([e]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-groups"),S.attr("transform","translate("+t.left+","+t.top+")");var k=S.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});k.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(k.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),k.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),d3.transition(k).style("stroke-opacity",1).style("fill-opacity",.75);var L=k.selectAll("g.nv-bar").data(function(e){return e.values});L.exit().remove();var A=L.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e
,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),v.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),v.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){v.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){v.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});A.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(A.append("text").
attr("text-anchor","middle"),L.select("text").attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4
+}).text(function(e,t){return h(a(e,t))})):L.selectAll("text").remove(),L.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",m).attr("width",s.rangeBand()*.9/e.length),d3.transition(L).attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0))||1)}),g=s.copy(),y=o.copy()}),b}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),m="discreteBar",g,y;return b.dispatch=v,b.x
=function(e){return arguments.length?(u=e,b):u},b.y=function(e){return arguments.length?(a=e,b):a},b.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,b):t},b.width=function(e){return arguments.length?(n=e,b):n},b.height=function(e){return arguments.length?(r=e,b):r},b.xScale=function(e){return arguments.length?(s=e,b):s},b.yScale=function(e){return arguments.length?(o=e,b):o},b.xDomain=function(e){return arguments.length?(p=e,b):p},b.yDomain=function(e){return arguments.length?(d=e,b):d},b.forceY=function(e){return arguments.length?(f=e,b):f},b.color=function(t){return arguments.length?(l=e.utils.getColor(t),b):l},b.id=function(e){return arguments.length?(i=e,b):i},b.showValues=function(e){return arguments.length?(c=e,b):c},b.valueFormat=function(e){return arguments.length?(h=e,b):h}
,b.rectClass=function(e){return arguments.length?(m=e,b):m},b},e.models.discreteBarChart=function(){function m(e){return e.each(function(u){var l=d3.select(this),g=this,b=(s||parseInt(l.style("width"))||960)-i.left-i.right,w=(o||parseInt(l.style("height"))||400)-i.top-i.bottom;m.update=function(){d.beforeUpdate(),e.transition().call(m)},m.container=this;if(!u||!u.length||!u.filter(function(e){return e.values.length}).length){var E=l.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+b/2).attr("y",i.top+w/2).text(function(e){return e}),m}l.selectAll(".nv-noData").remove(),c=t.xScale(),h=t.yScale();var S=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([u]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),N=T.append("defs"),C=S.select("g");T.append("g").attr("class","nv-x nv-axis"),T.append("g").attr("class","nv-y nv-axis")
,T.append("g").attr("class","nv-barsWrap"),C.attr("transform","translate("+i.left+","+i.top+")"),t.width(b).height(w);var k=C.select(".nv-barsWrap").datum(u.filter(function(e){return!e.disabled}));d3.transition(k).call(t),N.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),C.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",c.rangeBand()*(a?2:1)).attr("height",16).attr("x",-c.rangeBand()/(a?1:2)),n.scale(c).ticks(b/100).tickSize(-w,0),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+(h.range()[0]+(t.showValues()&&h.domain()[0]<0?16:0))+")"),C.select(".nv-x.nv-axis").transition().duration(0).call(n);var L=C.select(".nv-x.nv-axis").selectAll("g");a&&L.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"}),r.scale(h).ticks(w/36).tickSize(-b,0),d3.transition(C.select(".nv-y.nv-axis")).call(r),d.on("tooltipShow",function(e){f&&v(e,g.parentNode)})}),m}var t=e.models.discreteBar(),n=e.models.axis(),r=e.mod
els.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!1,f=!0,l=function(e,t,n,r,i){return"<h3>"+t+"</h3>"+"<p>"+n+"</p>"},c,h,p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate");n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("left").tickFormat(d3.format(",.1f"));var v=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),c=l(i.series.key,a,f,i,m);e.tooltip.show([o,u],c,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){f&&e.tooltip.cleanup()}),m.dispatch=d,m.discretebar=t,m.xAxis=n,m.yAxis=r,d3.rebind(m,t,"x","y","xDomain","yDomain","forceX","forceY","id","showValu
es","valueFormat"),m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.width=function(e){return arguments.length?(s=e,m):s},m.height=function(e){return arguments.length?(o=e,m):o},m.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),m):u},m.staggerLabels=function(e){return arguments.length?(a=e,m):a},m.tooltips=function(e){return arguments.length?(f=e,m):f},m.tooltipContent=function(e){return arguments.length?(l=e,m):l},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.distribution=function(){function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.ap
pend("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),d3.transition(m.exit().selectAll("line.nv-dist"+i)).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),d3.transition(g).attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linea
r(),a,f;return l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.indentedTree=function(){function m(e){return e.each(function(e){function C(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&C(e,0,!0)}),!0;if(!A(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),m.update()}fu
nction k(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function L(e){return e._values&&e._values.length}function A(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);m.update=function(){n.transition().duration(600).call(m)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),g=d3.select(this).selectAll("div").data([[s]]),y=g.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),b=y.append("table"),w=g.select("table").attr("width","100%").attr("class",c);if(o){var E=b.append("thead"),S=E.append("tr");l.forEach(function(e){S.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var x=w.selectAll("tbody").data(function(e){return e});x.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var T=x.selectAll("tr").data(function(e){return e.filter(function(e){r
eturn u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++v});T.exit().remove(),T.select("img.nv-treeicon").attr("src",k).classed("folded",L);var N=T.enter().append("tr");l.forEach(function(e,t){var n=N.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(k(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",L).attr("src",k).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return k(e)?"inline-block":"none"}).on("click",C),n.append("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?e.format(t):t[e.key]||"-"}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),T.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filt
er(function(e){return u?u(e):!0}).length||0)+")":""})),e.click&&n.select("span").on("click",e.click)}),T.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),m}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=0;return m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!=
"undefined"?e.left:t.left,m):t},m.width=function(e){return arguments.length?(n=e,m):n},m.height=function(e){return arguments.length?(r=e,m):r},m.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),m):i},m.id=function(e){return arguments.length?(s=e,m):s},m.header=function(e){return arguments.length?(o=e,m):o},m.noData=function(e){return arguments.length?(a=e,m):a},m.filterZero=function(e){return arguments.length?(u=e,m):u},m.columns=function(e){return arguments.length?(l=e,m):l},m.tableClass=function(e){return arguments.length?(c=e,m):c},m.iconOpen=function(e){return arguments.length?(h=e,m):h},m.iconClose=function(e){return arguments.length?(p=e,m):p},m},e.models.legend=function(){function a(f){return f.each(function(a){var f=n-t.left-t.right,l=d3.select(this),c=l.selectAll("g.nv-legend").data([a]),h=c.enter().append("g").attr("class","nvd3 nv-legend").append("g"),p=c.select("g");c.attr("transform","translate("+t.left+","+t.top+")");var d=p.sel
ectAll(".nv-series").data(function(e){return e}),v=d.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){u.legendMouseover(e,t)}).on("mouseout",function(e,t){u.legendMouseout(e,t)}).on("click",function(e,t){u.legendClick(e,t)}).on("dblclick",function(e,t){u.legendDblclick(e,t)});v.append("circle").style("stroke-width",2).attr("r",5),v.append("text").attr("text-anchor","start").attr("dy",".32em").attr("dx","8"),d.classed("disabled",function(e){return e.disabled}),d.exit().remove(),d.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),d.select("text").text(i);if(o){var m=[];d.each(function(t,n){var r=d3.select(this).select("text"),i=r.node().getComputedTextLength()||e.utils.calcApproxTextWidth(r);m.push(i+28)});var g=0,y=0,b=[];while(y<f&&g<m.length)b[g]=m[g],y+=m[g++];while(y>f&&g>1){b=[],g--;for(k=0;k<m.length;k++)m[k]>(b[k%g]||0)&&(b[k%g]=m[k]);y=b.reduce(function(e,t,n,r){return e
+t})}var w=[];for(var E=0,S=0;E<g;E++)w[E]=S,S+=b[E];d.attr("transform",function(e,t){return"translate("+w[t%g]+","+(5+Math.floor(t/g)*20)+")"}),p.attr("transform","translate("+(n-t.right-y)+","+t.top+")"),r=t.top+t.bottom+Math.ceil(m.length/g)*20}else{var x=5,T=5,N=0,C;d.attr("transform",function(e,r){var i=d3.select(this).select("text").node().getComputedTextLength()+28;return C=T,n<t.left+t.right+C+i&&(T=C=5,x+=20),T+=i,T>N&&(N=T),"translate("+C+","+x+")"}),p.attr("transform","translate("+(n-t.right-N)+","+t.top+")"),r=t.top+t.bottom+x+15}}),a}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout");return a.dispatch=u,a.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefin
ed"?e.left:t.left,a):t},a.width=function(e){return arguments.length?(n=e,a):n},a.height=function(e){return arguments.length?(r=e,a):r},a.key=function(e){return arguments.length?(i=e,a):i},a.color=function(t){return arguments.length?(s=e.utils.getColor(t),a):s},a.align=function(e){return arguments.length?(o=e,a):o},a},e.models.line=function(){function m(e){return e.each(function(e){var m=r-n.left-n.right,g=i-n.top-n.bottom,b=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var w=b.selectAll("g.nv-wrap.nv-line").data([e]),E=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),S=E.append("defs"),T=E.append("g"),N=w.select("g");T.append("g").attr("class","nv-groups"),T.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+n.left+","+n.top+")"),t.width(m).height(g);var C=w.select(".nv-scatterWrap");d3.transition(C).call(t),S.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),w.select("#nv-edge-clip-"+t.id()+" rect").attr("width",
m).attr("height",g),N.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var k=w.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});k.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(k.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),k.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),d3.transition(k).style("stroke-opacity",1).style("fill-opacity",.5);var L=k.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});L.enter().append("path").attr("class","nv-area").attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?
0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])}),d3.transition(k.exit().selectAll("path.nv-area")).attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])}),d3.transition(L).attr("d",function(e){return d3.svg.area().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y0(function(e,t){return v(u(e,t))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[e.values])});var A=k.selectAll("path.nv-line").data(function(e){return[e.values]});A.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e,t){return d(o(e,t))}).y(function(e,t){return v(u(e,t))})),d3.transition(k.exit().selectAll("path.nv-line")).attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e
,t){return c(o(e,t))}).y(function(e,t){return h(u(e,t))})),d3.transition(A).attr("d",d3.svg.line().interpolate(p).defined(a).x(function(e,t){return c(o(e,t))}).y(function(e,t){return h(u(e,t))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","forceX","forceY","forceSize","clipVoronoi","clipRadius","padData"),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function
(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){function b(e){return e.each(function(c){var w=d3.select(this),E=this,S=(u||parseInt(w.style("width"))||960)-s.left-s.right,T=(a||parseInt(w.style("height"))||400)-s.top-s.bottom;b.update=function(){b(e)},b.container=this,d.disabled=c.map(function(e){return!!e.disabled});if(!v){var N;v={};for(N in d)d[N]instanceof Array?v[N]=d[N].slice(0):v[N]=d[N]}if(!c||!c.length||!c.filter(function(e){return e.values.length}).le
ngth){var C=w.selectAll(".nv-noData").data([m]);return C.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),C.attr("x",s.left+S/2).attr("y",s.top+T/2).text(function(e){return e}),b}w.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale();var k=w.selectAll("g.nv-wrap.nv-lineChart").data([c]),L=k.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),A=k.select("g");L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-linesWrap"),L.append("g").attr("class","nv-legendWrap"),f&&(i.width(S),A.select(".nv-legendWrap").datum(c).call(i),s.top!=i.height()&&(s.top=i.height(),T=(a||parseInt(w.style("height"))||400)-s.top-s.bottom),k.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),k.attr("transform","translate("+s.left+","+s.top+")"),t.width(S).height(T).color(c.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){re
turn!c[t].disabled}));var O=A.select(".nv-linesWrap").datum(c.filter(function(e){return!e.disabled}));d3.transition(O).call(t),n.scale(h).ticks(S/100).tickSize(-T,0),A.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")"),d3.transition(A.select(".nv-x.nv-axis")).call(n),r.scale(p).ticks(T/36).tickSize(-S,0),d3.transition(A.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,c.filter(function(e){return!e.disabled}).length||c.map(function(e){return e.disabled=!1,k.selectAll(".nv-series").classed("disabled",!1),e}),d.disabled=c.map(function(e){return!!e.disabled}),g.stateChange(d),e.transition().call(b)}),g.on("tooltipShow",function(e){l&&y(e,E.parentNode)}),g.on("changeState",function(t){typeof t.disabled!="undefined"&&(c.forEach(function(e,n){e.disabled=t.disabled[n]}),d.disabled=t.disabled),e.call(b)})}),b}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:20,bottom:5
0,left:60},o=e.utils.defaultColor(),u=null,a=null,f=!0,l=!0,c=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},h,p,d={},v=null,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.orient("bottom").tickPadding(7),r.orient("left");var y=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),h=n.tickFormat()(t.x()(i.point,i.pointIndex)),p=r.tickFormat()(t.y()(i.point,i.pointIndex)),d=c(i.series.key,h,p,i,b);e.tooltip.show([f,l],d,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){l&&e.tooltip.cleanup()}),b.dispatch=g,b.lines=t,b.legend=i,b.xAxis=n,b
.yAxis=r,d3.rebind(b,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate"),b.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,b):s},b.width=function(e){return arguments.length?(u=e,b):u},b.height=function(e){return arguments.length?(a=e,b):a},b.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),b):o},b.showLegend=function(e){return arguments.length?(f=e,b):f},b.tooltips=function(e){return arguments.length?(l=e,b):l},b.tooltipContent=function(e){return arguments.length?(c=e,b):c},b.state=function(e){return arguments.length?(d=e,b):d},b.defaultState=function(e){return arguments.length?(v=e,b):v},b.noData=function(e){return arguments.length?(m=e,b):m},b},e.models.lin
ePlusBarChart=function(){function T(e){return e.each(function(l){var c=d3.select(this),v=this,N=(a||parseInt(c.style("width"))||960)-u.left-u.right,C=(f||parseInt(c.style("height"))||400)-u.top-u.bottom;T.update=function(){T(e)},T.container=this,b.disabled=l.map(function(e){return!!e.disabled});if(!w){var k;w={};for(k in b)b[k]instanceof Array?w[k]=b[k].slice(0):w[k]=b[k]}if(!l||!l.length||!l.filter(function(e){return e.values.length}).length){var L=c.selectAll(".nv-noData").data([E]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",u.left+N/2).attr("y",u.top+C/2).text(function(e){return e}),T}c.selectAll(".nv-noData").remove();var A=l.filter(function(e){return!e.disabled&&e.bar}),O=l.filter(function(e){return!e.bar});m=O.filter(function(e){return!e.disabled}).length&&O.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var M=d3.select(this).selectAl
l("g.nv-wrap.nv-linePlusBar").data([l]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),D=M.select("g");_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y1 nv-axis"),_.append("g").attr("class","nv-y2 nv-axis"),_.append("g").attr("class","nv-barsWrap"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-legendWrap"),p&&(o.width(N/2),D.select(".nv-legendWrap").datum(l.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),C=(f||parseInt(c.style("height"))||400)-u.top-u.bottom),D.select(".nv-legendWrap").attr("transform","translate("+N/2+","+ -u.top+")")),M.attr("transform","translate("+u.left+","+u.top+")"),t.width(N).height(C).color(l.map(function(e,t){return e.color||h(e,t)}).filter(function(e,t){return!l[t].disabled&&!l[t].bar})),n.width(N).height(C).color(l.map
(function(e,t){return e.color||h(e,t)}).filter(function(e,t){return!l[t].disabled&&l[t].bar}));var P=D.select(".nv-barsWrap").datum(A.length?A:[{values:[]}]),H=D.select(".nv-linesWrap").datum(O[0]&&!O[0].disabled?O:[{values:[]}]);d3.transition(P).call(n),d3.transition(H).call(t),r.scale(m).ticks(N/100).tickSize(-C,0),D.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(D.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(C/36).tickSize(-N,0),d3.transition(D.select(".nv-y1.nv-axis")).style("opacity",A.length?1:0).call(i),s.scale(y).ticks(C/36).tickSize(A.length?0:-N,0),D.select(".nv-y2.nv-axis").style("opacity",O.length?1:0).attr("transform","translate("+N+",0)"),d3.transition(D.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,l.filter(function(e){return!e.disabled}).length||l.map(function(e){return e.disabled=!1,M.selectAll(".nv-series").classed("disabled",!1),e}),b.disabled=l.map(function(
e){return!!e.disabled}),S.stateChange(b),e.transition().call(T)}),S.on("tooltipShow",function(e){d&&x(e,v.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(l.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),e.call(T)})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?
i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefi
ned"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){function C(e){return e.each(function(S){function R(e){var t=+(e=="e"),n=t?1:-1,r=M/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function U(){a.empty()||a.extent(w),I.data([a.empty()?g.domain():w]).
each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function z(){w=a.empty()?null:a.extent(),extent=a.empty()?g.domain():a.extent(),T.brush({extent:extent,brush:a}),U();var e=H.select(".nv-focus .nv-linesWrap").datum(S.filter(function(e){return!e.disabled}).map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=extent[0]&&t.x()(e,n)<=extent[1]})}}));d3.transition(e).call(t),d3.transition(H.select(".nv-focus .nv-x.nv-axis")).call(r),d3.transition(H.select(".nv-focus .nv-y.nv-axis")).call(i)}var k=d3.select(this),L=this,A=(h||parseInt(k.style("width"))||960)-f.left-f.right,O=(p||parseInt(k.style("height"))||400)-f.top-f.bottom-d,M=d-l.top-l.bottom;C.update=function(){C(e)},C.container=this;if(!S||!S.length||!S.filter(function(e){return e.values.length}).length){var _=k.selectAll(".nv-noData").data(
[x]);return _.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),_.attr("x",f.left+A/2).attr("y",f.top+O/2).text(function(e){return e}),C}k.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var D=k.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([S]),P=D.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),H=D.select("g");P.append("g").attr("class","nv-legendWrap");var B=P.append("g").attr("class","nv-focus");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap");var j=P.append("g").attr("class","nv-context");j.append("g").attr("class","nv-x nv-axis"),j.append("g").attr("class","nv-y nv-axis"),j.append("g").attr("class","nv-linesWrap"),j.append("g").attr("class","nv-brushBackground"),j.append("g").attr("class","nv-x nv-brush"),b&&(u.width(A),H.select(".nv-legendWrap").datum(S).call(u),
f.top!=u.height()&&(f.top=u.height(),O=(p||parseInt(k.style("height"))||400)-f.top-f.bottom-d),H.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),D.attr("transform","translate("+f.left+","+f.top+")"),t.width(A).height(O).color(S.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!S[t].disabled})),n.defined(t.defined()).width(A).height(M).color(S.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!S[t].disabled})),H.select(".nv-context").attr("transform","translate(0,"+(O+f.bottom+l.top)+")");var F=H.select(".nv-context .nv-linesWrap").datum(S.filter(function(e){return!e.disabled}));d3.transition(F).call(n),r.scale(v).ticks(A/100).tickSize(-O,0),i.scale(m).ticks(O/36).tickSize(-A,0),H.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+O+")"),a.x(g).on("brush",z),w&&a.extent(w);var I=H.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),q=I.enter().append("g");q.append("rect").attr("class
","left").attr("x",0).attr("y",0).attr("height",M),q.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M),gBrush=H.select(".nv-x.nv-brush").call(a),gBrush.selectAll("rect").attr("height",M),gBrush.selectAll(".resize").append("path").attr("d",R),z(),s.scale(g).ticks(A/100).tickSize(-M,0),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(H.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(M/36).tickSize(-A,0),d3.transition(H.select(".nv-context .nv-y.nv-axis")).call(o),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,S.filter(function(e){return!e.disabled}).length||S.map(function(e){return e.disabled=!1,D.selectAll(".nv-series").classed("disabled",!1),e}),e.transition().call(C)}),T.on("tooltipShow",function(e){E&&N(e,L.parentNode)})}),C}var t=e.models.line(),n=e.models.line(),r=e.models.
axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60
+},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush");t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var N=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,C);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),C.dispatch=T,C.legend=u,C.lines=t,C.lines2=n,C.xAxis=r,C.yAxis=i,C.x2Axis=s,C.y2Axis=o,d3.rebind(C,t,"defined","isArea","
size","xDomain","yDomain","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),C.x=function(e){return arguments.length?(t.x(e),n.x(e),C):t.x},C.y=function(e){return arguments.length?(t.y(e),n.y(e),C):t.y},C.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,C):f},C.margin2=function(e){return arguments.length?(l=e,C):l},C.width=function(e){return arguments.length?(h=e,C):h},C.height=function(e){return arguments.length?(p=e,C):p},C.height2=function(e){return arguments.length?(d=e,C):d},C.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),C):c},C.showLegend=function(e){return arguments.length?(b=e,C):b},C.tooltips=function(e){return arguments.length?(E=e,C):E},C.tooltipContent=function(e){return arguments.length?(S=e,C):S},C.interpolate=function(e){retur
n arguments.length?(t.interpolate(e),n.interpolate(e),C):t.interpolate()},C.noData=function(e){return arguments.length?(x=e,C):x},C.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),C):r.tickFormat()},C.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),C):i.tickFormat()},C},e.models.linePlusBarWithFocusChart=function(){function H(e){return e.each(function(N){function nt(e){var t=+(e=="e"),n=t?1:-1,r=q/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function rt(){h.empty()||h.extent(x),Z.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function it(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({e
xtent:S,brush:h}),rt(),r.width(F).height(I).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&N[t].bar})),t.width(F).height(I).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&!N[t].bar}));var e=J.select(".nv-focus .nv-barsWrap").datum(U.length?U.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),n=J.select(".nv-focus .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));U.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(F/100).tickSize(-I,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),d3.transition(J.select(".nv-x.nv-axis")).call(s),d3.transition(e).call(r),d3.transition(n).call(t),J.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(I/36
).tickSize(-F,0),J.select(".nv-focus .nv-y1.nv-axis").style("opacity",U.length?1:0),a.scale(A).ticks(I/36).tickSize(U.length?0:-F,0),J.select(".nv-focus .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),d3.transition(J.select(".nv-focus .nv-y1.nv-axis")).call(u),d3.transition(J.select(".nv-focus .nv-y2.nv-axis")).call(a)}var B=d3.select(this),j=this,F=(v||parseInt(B.style("width"))||960)-p.left-p.right,I=(m||parseInt(B.style("height"))||400)-p.top-p.bottom-g,q=g-d.top-d.bottom;H.update=function(){H(e)},H.container=this;if(!N||!N.length||!N.filter(function(e){return e.values.length}).length){var R=B.selectAll(".nv-noData").data([_]);return R.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),R.attr("x",p.left+F/2).attr("y",p.top+I/2).text(function(e){return e}),H}B.selectAll(".nv-noData").remove();var U=N.filter(function(e){return!e.disabled&&e.bar}),z=N.filter(function(e){retur
n!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var W=N.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),X=N.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,F]),k.domain(d3.extent(d3.merge(W.concat(X)),function(e){return e.x})).range([0,F]);var V=B.selectAll("g.nv-wrap.nv-linePlusBar").data([N]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),J=V.select("g");$.append("g").attr("class","nv-legendWrap");var K=$.append("g").attr("class","nv-focus");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap");var Q=$.append("g").attr("class","nv-context");Q.append("g").attr("class","nv-x nv-ax
is"),Q.append("g").attr("class","nv-y1 nv-axis"),Q.append("g").attr("class","nv-y2 nv-axis"),Q.append("g").attr("class","nv-barsWrap"),Q.append("g").attr("class","nv-linesWrap"),Q.append("g").attr("class","nv-brushBackground"),Q.append("g").attr("class","nv-x nv-brush"),E&&(c.width(F/2),J.select(".nv-legendWrap").datum(N.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),I=(m||parseInt(B.style("height"))||400)-p.top-p.bottom-g),J.select(".nv-legendWrap").attr("transform","translate("+F/2+","+ -p.top+")")),V.attr("transform","translate("+p.left+","+p.top+")"),i.width(F).height(q).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&N[t].bar})),n.width(F).height(q).color(N.map(function(e,t){return e.color||w(e,t)}).filter(function(e,t){return!N[t].disabled&&!N[t].bar}));var G=J.select(".nv-context
.nv-barsWrap").datum(U.length?U:[{values:[]}]),Y=J.select(".nv-context .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z);J.select(".nv-context").attr("transform","translate(0,"+(I+p.bottom+d.top)+")"),d3.transition(G).call(i),d3.transition(Y).call(n),h.x(k).on("brush",it),x&&h.extent(x);var Z=J.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),et=Z.enter().append("g");et.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",q),et.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",q);var tt=J.select(".nv-x.nv-brush").call(h);tt.selectAll("rect").attr("height",q),tt.selectAll(".resize").append("path").attr("d",nt),o.ticks(F/100).tickSize(-q,0),J.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),d3.transition(J.select(".nv-context .nv-x.nv-axis")).call(o),f.scale(O).ticks(q/36).tickSize(-F,0),J.select(".nv-context .nv-y1.nv-axis").style("opacity",U.length?1:0).attr("transform","t
ranslate(0,"+k.range()[0]+")"),d3.transition(J.select(".nv-context .nv-y1.nv-axis")).call(f),l.scale(M).ticks(q/36).tickSize(U.length?0:-F,0),J.select(".nv-context .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),d3.transition(J.select(".nv-context .nv-y2.nv-axis")).call(l),c.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,N.filter(function(e){return!e.disabled}).length||N.map(function(e){return e.disabled=!1,V.selectAll(".nv-series").classed("disabled",!1),e}),e.call(H)}),D.on("tooltipShow",function(e){T&&P(e,j.parentNode)}),it()}),H}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y}
,w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush");t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var P=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,H);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("e
lementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),H.dispatch=D,H.legend=c,H.lines=t,H.lines2=n,H.bars=r,H.bars2=i,H.xAxis=s,H.x2Axis=o,H.y1Axis=u,H.y2Axis=a,H.y3Axis=f,H.y4Axis=l,d3.rebind(H,t,"defined","size","clipVoronoi","interpolate"),H.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),H):y},H.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),H):b},H.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,H):p},H.width=function(e){return arguments.length?(v=e,H):v},H.height=function(e){return arguments.length?(m=e,H):m},H.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),H):w},H.showLegend=function(e){return arguments.length?(E=e,H):E},H.tooltips=function(e){return arguments.length?(T=e,H
):T},H.tooltipContent=function(e){return arguments.length?(N=e,H):N},H.noData=function(e){return arguments.length?(_=e,H):_},H.brushExtent=function(e){return arguments.length?(x=e,H):x},H},e.models.multiBar=function(){function S(e){return e.each(function(e){var S=n-t.left-t.right,T=r-t.top-t.bottom,N=d3.select(this);p&&e.length&&(p=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(!e.length&&p?p:e)),e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var C=g&&y?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(d3.merge(C).map(function(e){return e.x})).rangeBands([0,S],.1),s.domain(y||d3.extent(d3.merge(C).map(fu
nction(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range([T,0]);if(i.domain()[0]===i.domain()[1]||s.domain()[0]===s.domain()[1])singlePoint=!0;i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),w=w||i,E=E||s;var k=N.selectAll("g.nv-wrap.nv-multibar").data([e]),L=k.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),A=L.append("defs"),O=L.append("g"),M=k.select("g");O.append("g").attr("class","nv-groups"),k.attr("transform","translate("+t.left+","+t.top+")"),A.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),k.select("#nv-edge-clip-"+o+" rect").attr("width",S).attr("height",T),M.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var _=k.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){retur
n e.key});_.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),_.exit().selectAll("rect.nv-bar").transition().delay(function(t,n){return n*m/e[0].values.length}).attr("y",function(e){return c?E(e.y0):E(0)}).attr("height",0).remove(),_.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return h(e,t)}).style("stroke",function(e,t){return h(e,t)}),d3.transition(_).style("stroke-opacity",1).style("fill-opacity",.75);var D=_.selectAll("rect.nv-bar").data(function(t){return p&&!e.length?p.values:t.values});D.exit().remove();var P=D.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return E(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length));D.style("fill",function(e,t,n){return h(e,n,t)}).style("stroke",function(e,t,n){ret
urn h(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),b.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),b.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){b.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){b.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),D.attr("class",function(e,t){return a(e,t)<0?"n
v-bar negative":"nv-bar positive"}).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),d&&(v||(v=e.map(function(){return!0})),D.style("fill",function(e,t,n){return d3.rgb(d(e,t)).darker(v.map(function(e,t){return t}).filter(function(e,t){return!v[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(d(e,t)).darker(v.map(function(e,t){return t}).filter(function(e,t){return!v[t]})[n]).toString()})),c?D.transition().delay(function(t,n){return n*m/e[0].values.length}).attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).each("end",function(){d3.transition(d3.select(this)).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length))}):d3.transition(D).delay(function(t,n){return n*m/e[0].values.length}).attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).each("end",function()
{d3.transition(d3.select(this)).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0})}),w=i.copy(),E=s.copy()}),S}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h=e.utils.defaultColor(),p=!1,d=null,v,m=1200,g,y,b=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),w,E;return S.dispatch=b,S.x=function(e){return arguments.length?(u=e,S):u},S.y=function(e){return arguments.length?(a=e,S):a},S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):
n},S.height=function(e){return arguments.length?(r=e,S):r},S.xScale=function(e){return arguments.length?(i=e,S):i},S.yScale=function(e){return arguments.length?(s=e,S):s},S.xDomain=function(e){return arguments.length?(g=e,S):g},S.yDomain=function(e){return arguments.length?(y=e,S):y},S.forceY=function(e){return arguments.length?(f=e,S):f},S.stacked=function(e){return arguments.length?(c=e,S):c},S.clipEdge=function(e){return arguments.length?(l=e,S):l},S.color=function(t){return arguments.length?(h=e.utils.getColor(t),S):h},S.barColor=function(t){return arguments.length?(d=e.utils.getColor(t),S):d},S.disabled=function(e){return arguments.length?(v=e,S):v},S.id=function(e){return arguments.length?(o=e,S):o},S.hideable=function(e){return arguments.length?(p=e,S):p},S.delay=function(e){return arguments.length?(m=e,S):m},S},e.models.multiBarChart=function(){function N(e){return e.each(function(m){var C=d3.select(this),k=this,L=(u||parseInt(C.style("width"))||960)-o.left-o.right,A
=(a||parseInt(C.style("height"))||400)-o.top-o.bottom;N.update=function(){e.transition().call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var O;w={};for(O in b)b[O]instanceof Array?w[O]=b[O].slice(0):w[O]=b[O]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var M=C.selectAll(".nv-noData").data([E]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",o.left+L/2).attr("y",o.top+A/2).text(function(e){return e}),N}C.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var _=C.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([m]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),P=_.select("g");D.append("g").attr("class","nv-x nv-axis"),D.append("g").attr("class","nv-y nv-axis"),D.append("g").attr("class","nv-barsWrap"),D.append("g").attr("class","nv-legendWrap"),D.append("g").attr("class","nv-controlsWrap"),
c&&(i.width(L-x()),t.barColor()&&m.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),P.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),A=(a||parseInt(C.style("height"))||400)-o.top-o.bottom),P.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var H=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),P.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -o.top+")").call(s)}_.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(m.map(function(e){return e.disabled})).width(L).height(A).color(m.map(function(e,t){return e.color||f(e,t)}).filter(function(e,t){return!m[t].disabled}));var B=P.select(".nv-barsWrap").datum(m.filter(function(e){return!e.disabled}));d3.transition(B).call(t),n.scale(g).ticks(L/100).tickSize(-A,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.tr
ansition(P.select(".nv-x.nv-axis")).call(n);var j=P.select(".nv-x.nv-axis > g").selectAll("g");j.selectAll("line, text").style("opacity",1);if(p){var F=function(e,t){return"translate("+e+","+t+")"},I=5,q=17;j.selectAll("text").attr("transform",function(e,t,n){return F(0,n%2==0?I:q)});var R=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;P.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return F(0,t===0||R%2!==0?q:I)})}h&&j.filter(function(e,t){return t%Math.ceil(m[0].values.length/(L/100))!==0}).selectAll("text, line").style("opacity",0),d&&j.selectAll("text").attr("transform","rotate("+d+" 0,0)").attr("text-anchor",d>0?"start":"end"),P.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1),r.scale(y).ticks(A/36).tickSize(-L,0),d3.transition(P.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,m.filter(function(e){return!e.disabled}).length||m.map(function(e){return e
.disabled=!1,_.selectAll(".nv-series").classed("disabled",!1),e}),b.disabled=m.map(function(e){return!!e.disabled}),S.stateChange(b),e.transition().call(N)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;H=H.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),e.transition().call(N)}),S.on("tooltipShow",function(e){v&&T(e,k.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(m.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),e.call(N)})}),N}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!1,d=0,v=!0,m=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},g,y,b={s
tacked:!1},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0};t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("left").tickFormat(d3.format(",.1f"));var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.multibar=t,N.legend=i,N.xAxis=n,N.yAxis=r,d3.rebind(N,t,"x","y","xDomain","yDomain","forceX","forceY","clipEdge","id","stacked","delay","barColor"),N.margin=function(e){return ar
guments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(u=e,N):u},N.height=function(e){return arguments.length?(a=e,N):a},N.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),N):f},N.showControls=function(e){return arguments.length?(l=e,N):l},N.showLegend=function(e){return arguments.length?(c=e,N):c},N.reduceXTicks=function(e){return arguments.length?(h=e,N):h},N.rotateLabels=function(e){return arguments.length?(d=e,N):d},N.staggerLabels=function(e){return arguments.length?(p=e,N):p},N.tooltip=function(e){return arguments.length?(m=e,N):m},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){re
turn arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N},e.models.multiBarHorizontal=function(){function x(e){return e.each(function(e){var i=n-t.left-t.right,g=r-t.top-t.bottom,x=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var T=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(y||d3.merge(T).map(function(e){return e.x})).rangeBands([0,g],.1),o.domain(b||d3.extent(d3.merge(T).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range([o.domain()[0]<0?v:0,i-(o.domain()[1]>0?v:0)]):o.range([0,i]),E=E||s,S=S||d3.scale.linear().domain(o.domain()).range([o(0),o(0)])
;var N=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var O=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition(O.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),O.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),d3.transition(O).style("stroke-opacity",1).style("fill-opacity",.75);var M=O.selectAll("g.nv-bar").data(function(e){return e.values});M.exit().remove();var _=M.enter().append("g").attr("transform",function(t,n,r){return"tran
slate("+S(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});_.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),M.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),w.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),w.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){w.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){w.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(
p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),_.append("text"),d&&!p?(M.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return m(a(e,t))}),d3.transition(M).select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):M.selectAll("text").text(""),M.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),M.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?d3.transition(M).attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)
-o(e.y0))}).attr("height",s.rangeBand()):d3.transition(M).attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),E=s.copy(),S=o.copy()}),x}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=60,m=d3.format(",.2f"),g=1200,y,b,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),E,S;return x.dispatch=w,x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bott
om!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.forceY=function(e){return arguments.length?(f=e,x):f},x.stacked=function(e){return arguments.length?(p=e,x):p},x.color=function(t){return arguments.length?(l=e.utils.getColor(t),x):l},x.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),x):c},x.disabled=function(e){return arguments.length?(h=e,x):h},x.id=function(e){return arguments.length?(i=e,x):i},x.delay=function(e){return arguments.length?(g=e,x):g},x.showValues=function(e){return arguments.length?(d=e,x):d},x.valueFormat=function(e){return arguments.length?(m=e,x):m},x.valuePadding=f
unction(e){return arguments.length?(v=e,x):v},x},e.models.multiBarHorizontalChart=function(){function x(e){return e.each(function(h){var d=d3.select(this),T=this,N=(u||parseInt(d.style("width"))||960)-o.left-o.right,C=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;x.update=function(){e.transition().call(x)},x.container=this,g.disabled=h.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!h||!h.length||!h.filter(function(e){return e.values.length}).length){var L=d.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",o.left+N/2).attr("y",o.top+C/2).text(function(e){return e}),x}d.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var A=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([h]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),M=A.sel
ect("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-barsWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),c&&(i.width(N-E()),t.barColor()&&h.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),M.select(".nv-legendWrap").datum(h).call(i),o.top!=i.height()&&(o.top=i.height(),C=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate("+E()+","+ -o.top+")"));if(l){var _=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(E()).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(_).attr("transform","translate(0,"+ -o.top+")").call(s)}A.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(h.map(function(e){return e.disabled})).width(N).height(C).color(h.map(function(e,t){return e.color||f(e,t)}).filter(function(e,t){return!h[t].disabled}
));var D=M.select(".nv-barsWrap").datum(h.filter(function(e){return!e.disabled}));d3.transition(D).call(t),n.scale(v).ticks(C/24).tickSize(-N,0),d3.transition(M.select(".nv-x.nv-axis")).call(n);var P=M.select(".nv-x.nv-axis").selectAll("g");P.selectAll("line, text").style("opacity",1),r.scale(m).ticks(N/100).tickSize(-C,0),M.select(".nv-y.nv-axis").attr("transform","translate(0,"+C+")"),d3.transition(M.select(".nv-y.nv-axis")).call(r),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,h.filter(function(e){return!e.disabled}).length||h.map(function(e){return e.disabled=!1,A.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=h.map(function(e){return!!e.disabled}),w.stateChange(g),e.transition().call(x)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;_=_.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}g.stacked=t.stacked(),w.stateChange(g),e.transition()
.call(x)}),w.on("tooltipShow",function(e){p&&S(e,T.parentNode)}),w.on("changeState",function(n){typeof n.disabled!="undefined"&&(h.forEach
+(function(e,t){e.disabled=n.disabled[t]}),g.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),g.stacked=n.stacked),e.call(x)})}),x}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"<h3>"+e+" - "+t+"</h3>"+"<p>"+n+"</p>"},v,m,g={stacked:h},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=function(){return l?180:0};t.stacked(h),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f"));var S=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=d(i.series.key,a,f,i,x);e.tooltip.show([o,u],l,i.v
alue<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.multibar=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"x","y","xDomain","yDomain","forceX","forceY","clipEdge","id","delay","showValues","valueFormat","stacked","barColor"),x.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,x):o},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),x):f},x.showControls=function(e){return arguments.length?(l=e,x):l},x.showLegend=function(
e){return arguments.length?(c=e,x):c},x.tooltip=function(e){return arguments.length?(d=e,x):d},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x},e.models.multiChart=function(){function T(e){return e.each(function(u){var f=d3.select(this),N=this,C=(r||parseInt(f.style("width"))||960)-t.left-t.right,k=(i||parseInt(f.style("height"))||400)-t.top-t.bottom,L=u.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),A=u.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),O=u.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),M=u.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),_=u.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),D=u.filter(function(e){return!e.di
sabled&&e.type=="area"&&e.yAxis==2}),P=u.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),H=u.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(P.concat(H)),function(e){return e.x})).range([0,C]);var B=f.selectAll("g.wrap.multiChart").data([u]),j=B.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");j.append("g").attr("class","x axis"),j.append("g").attr("class","y1 axis"),j.append("g").attr("class","y2 axis"),j.append("g").attr("class","lines1Wrap"),j.append("g").attr("class","lines2Wrap"),j.append("g").attr("class","bars1Wrap"),j.append("g").attr("class","bars2Wrap"),j.append("g").attr("class","stack1Wrap"),j.append("g").attr("class","stack2Wrap"),j.append("g").attr("class","legendWrap");var F=B.select("g");s&&(E.width(C/2),F.select(".legendWrap").datum(u.map(function(e){return e.
originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(E),t.top!=E.height()&&(t.top=E.height(),k=(i||parseInt(f.style("height"))||400)-t.top-t.bottom),F.select(".legendWrap").attr("transform","translate("+C/2+","+ -t.top+")")),h.width(C).height(k).interpolate("monotone").color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="line"})),p.width(C).height(k).interpolate("monotone").color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="line"})),d.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="bar"})),v.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="bar"})),m.width(C).height(k
).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==1&&u[t].type=="area"})),g.width(C).height(k).color(u.map(function(e,t){return e.color||n[t%n.length]}).filter(function(e,t){return!u[t].disabled&&u[t].yAxis==2&&u[t].type=="area"})),F.attr("transform","translate("+t.left+","+t.top+")");var I=F.select(".lines1Wrap").datum(L),q=F.select(".bars1Wrap").datum(O),R=F.select(".stack1Wrap").datum(_),U=F.select(".lines2Wrap").datum(A),z=F.select(".bars2Wrap").datum(M),W=F.select(".stack2Wrap").datum(D),X=_.length?_.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];l.domain(d3.extent(d3.merge(P).concat(X),function(e){return e.y})).range([0,k]),c.domain(d3.extent(d3.merge(H).concat(V),functio
n(e){return e.y})).range([0,k]),h.yDomain(l.domain()),d.yDomain(l.domain()),m.yDomain(l.domain()),p.yDomain(c.domain()),v.yDomain(c.domain()),g.yDomain(c.domain()),_.length&&d3.transition(R).call(m),D.length&&d3.transition(W).call(g),O.length&&d3.transition(q).call(d),M.length&&d3.transition(z).call(v),L.length&&d3.transition(I).call(h),A.length&&d3.transition(U).call(p),y.ticks(C/100).tickSize(-k,0),F.select(".x.axis").attr("transform","translate(0,"+k+")"),d3.transition(F.select(".x.axis")).call(y),b.ticks(k/36).tickSize(-C,0),d3.transition(F.select(".y1.axis")).call(b),w.ticks(k/36).tickSize(-C,0),d3.transition(F.select(".y2.axis")).call(w),F.select(".y2.axis").style("opacity",H.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),E.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,u.filter(function(e){return!e.disabled}).length||u.map(function(e){return e.disabled=!1,B.selectAll(".series").classed("disabled",!1),e}),e.transition().call(T)}),S.on("to
oltipShow",function(e){o&&x(e,N.parentNode)})}),T.update=function(){T(e)},T.container=this,T}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" at "+t+"</p>"},a,f,a=d3.scale.linear(),l=d3.scale.linear(),c=d3.scale.linear(),h=e.models.line().yScale(l),p=e.models.line().yScale(c),d=e.models.multiBar().stacked(!1).yScale(l),v=e.models.multiBar().stacked(!1).yScale(c),m=e.models.stackedArea().yScale(l),g=e.models.stackedArea().yScale(c),y=e.models.axis().scale(a).orient("bottom").tickPadding(5),b=e.models.axis().scale(l).orient("left"),w=e.models.axis().scale(c).orient("right"),E=e.models.legend().height(30),S=d3.dispatch("tooltipShow","tooltipHide"),x=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=y.tickFormat()(h.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?w:b).tickFormat()(h.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,T);e.tooltip.show(
[r,i],a,undefined,undefined,n.offsetParent)};return h.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),h.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),p.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),p.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),m.dispatch.on("tooltipShow",function(e){if(!Math.round(m.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipS
how(e)}),m.dispatch.on("tooltipHide",function(e){S.tooltipHide(e)}),g.dispatch.on("tooltipShow",function(e){if(!Math.round(g.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),g.dispatch.on("tooltipHide",function(e){S.tooltipHide(e)}),h.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),h.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),p.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],S.tooltipShow(e)}),p.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),T.dispatch=S,T.lines1=h,T.lines2=p,T.bars1=d,T.bars2=v,T.stack1=m,T.stack2=g,T.xAxis=y,T.yAxis1=b,T.yAxis2=w,T.x=function(e){return arguments.length?(getX=e,h.x(e),d.x(e),T):getX},T.y=function(e){return arguments.length?(getY
=e,h.y(e),d.y(e),T):getY},T.margin=function(e){return arguments.length?(t=e,T):t},T.width=function(e){return arguments.length?(r=e,T):r},T.height=function(e){return arguments.length?(i=e,T):i},T.color=function(e){return arguments.length?(n=e,E.color(e),T):n},T.showLegend=function(e){return arguments.length?(s=e,T):s},T.tooltips=function(e){return arguments.length?(o=e,T):o},T.tooltipContent=function(e){return arguments.length?(u=e,T):u},T},e.models.ohlcBar=function(){function E(e){return e.each(function(e){var g=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range([g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range([0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range([E,0]);if(s.domain()[0]===s.domain()[1]||o.domain()[0]===o.domain()[1])singlePoint=!0;s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.0
1,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var T=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),C=N.append("defs"),k=N.append("g"),L=T.select("g");k.append("g").attr("class","nv-ticks"),T.attr("transform","translate("+t.left+","+t.top+")"),S.on("click",function(e,t){w.chartClick({data:e,index:t,pos:d3.event,id:i})}),C.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),T.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",E),L.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var A=T.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});A.exit().remove();var O=A.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+
n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),w.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),w.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){w.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){w.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});A.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" n
v-tick-"+n+"-"+t}),d3.transition(A).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return E.dispatch=w,E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.open=function(e){return arguments.length?(f=e,E):f},E.close=function(e){return arguments.length?(l=e,E):l},E.hi
gh=function(e){return arguments.length?(c=e,E):c},E.low=function(e){return arguments.length?(h=e,E):h},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(y=e,E):y},E.yDomain=function(e){return arguments.length?(b=e,E):b},E.forceX=function(e){return arguments.length?(p=e,E):p},E.forceY=function(e){return arguments.length?(d=e,E):d},E.padData=function(e){return arguments.length?(v=e,E):v},E.clipEdge=function(e){return arguments.length?(m=e,E):m},E.color=function(t){return arguments.length?(g=e.utils.getColor(t),E):
g},E.id=function(e){return arguments.length?(i=e,E):i},E},e.models.pie=function(){function E(e){return e.each(function(e){function P(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function H(e){v||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return L(t(e))}}function B(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return L(t(e))}}var u=n-t.left-t.right,l=r-t.top-t.bottom,E=Math.min(u,l)/2,S=E-E/5,x=d3.select(this),T=x.selectAll(".nv-wrap.nv-pie").data([i(e[0])]),N=T.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+a),C=N.append("g"),k=T.select("g");C.append("g").attr("class","nv-pie"),T.attr("transform","translate("+t.left+","+t.top+")"),k.select(".nv-pie").attr("transform","translate("+u/2+","+l/2+")"),x.on("click",function(e,t){w.chartClick({data:e,index:t,pos:d3.event,id:a})});var L=d3.svg.arc().outerRadius(S);g&&L.startAngle(g),y&&L.endAngle(y),
v&&L.innerRadius(E*b);var A=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:o(e)}),O=T.select(".nv-pie").selectAll(".nv-slice").data(A);O.exit().remove();var M=O.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),w.elementMouseover({label:s(e.data),value:o(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:a})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),w.elementMouseout({label:s(e.data),value:o(e.data),point:e.data,index:t,id:a})}).on("click",function(e,t){w.elementClick({label:s(e.data),value:o(e.data),point:e.data,index:t,pos:d3.event,id:a}),d3.event.stopPropagation()}).on("dblclick",function(e,t){w.elementDblClick({label:s(e.data),value:o(e.data),point:e.data,index:t,pos:d3.event,id:a}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return f(e,t)}).attr("stroke",function(e,t){return f(e,t)});var _=M.append("path").each(function(e){this._curren
t=e});d3.transition(O.select("path")).attr("d",L).attrTween("d",H);if(c){var D=d3.svg.arc().innerRadius(0);h&&(D=L),p&&(D=d3.svg.arc().outerRadius(L.outerRadius())),M.append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(m){e.outerRadius=S+10,e.innerRadius=S+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+D.centroid(e)+") rotate("+t+")"}return e.outerRadius=E+10,e.innerRadius=E+15,"translate("+D.centroid(e)+")"}),n.append("rect").style("stroke","#fff").style("fill","#fff").attr("rx",3).attr("ry",3),n.append("text").style("text-anchor",m?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").style("fill","#000")}),O.select(".nv-label").transition().attr("transform",function(e){if(m){e.outerRadius=S+10,e.innerRadius=S+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2<Math.PI?t-=90:t+=90,"translate("+D.centroid(e)+
") rotate("+t+")"}return e.outerRadius=E+10,e.innerRadius=E+15,"translate("+D.centroid(e)+")"}),O.each(function(e,t){var n=d3.select(this);n.select(".nv-label text").style("text-anchor",m?(e.startAngle+e.endAngle)/2<Math.PI?"start":"end":"middle").text(function(e,t){var n=(e.endAngle-e.startAngle)/(2*Math.PI);return e.value&&n>d?s(e.data):""});var r=n.select("text").node().getBBox();n.select(".nv-label rect").attr("width",r.width+10).attr("height",r.height+10).attr("transform",function(){return"translate("+[r.x-5,r.y-5]+")"})})}}),E}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.values},s=function(e){return e.x},o=function(e){return e.y},u=function(e){return e.description},a=Math.floor(Math.random()*1e4),f=e.utils.defaultColor(),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d=.02,v=!1,m=!1,g=!1,y=!1,b=.5,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return E.dispatch=w,E.margin=function(e){return arguments.le
ngth?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.values=function(e){return arguments.length?(i=e,E):i},E.x=function(e){return arguments.length?(s=e,E):s},E.y=function(e){return arguments.length?(o=d3.functor(e),E):o},E.description=function(e){return arguments.length?(u=e,E):u},E.showLabels=function(e){return arguments.length?(c=e,E):c},E.labelSunbeamLayout=function(e){return arguments.length?(m=e,E):m},E.donutLabelsOutside=function(e){return arguments.length?(p=e,E):p},E.pieLabelsOutside=function(e){return arguments.length?(h=e,E):h},E.donut=function(e){return arguments.length?(v=e,E):v},E.donutRatio=function(e){return arguments.length?(b=e,E):b},E.startAngle=function(e){return arguments.length?(g=e,E):g
},E.endAngle=function(e){return arguments.length?(y=e,E):y},E.id=function(e){return arguments.length?(a=e,E):a},E.color=function(t){return arguments.length?(f=e.utils.getColor(t),E):f},E.valueFormat=function(e){return arguments.length?(l=e,E):l},E.labelThreshold=function(e){return arguments.length?(d=e,E):d},E},e.models.pieChart=function(){function v(e){return e.each(function(u){var a=d3.select(this),f=this,d=(i||parseInt(a.style("width"))||960)-r.left-r.right,m=(s||parseInt(a.style("height"))||400)-r.top-r.bottom;v.update=function(){v(e)},v.container=this,l.disabled=u[0].map(function(e){return!!e.disabled});if(!c){var g;c={};for(g in l)l[g]instanceof Array?c[g]=l[g].slice(0):c[g]=l[g]}if(!u[0]||!u[0].length){var y=a.selectAll(".nv-noData").data([h]);return y.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),y.attr("x",r.left+d/2).attr("y",r.top+m/2).text(function(e){return e}),v}a.selectAll(".nv-noData").remove();var b=a.
selectAll("g.nv-wrap.nv-pieChart").data([u]),w=b.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),E=b.select("g");w.append("g").attr("class","nv-pieWrap"),w.append("g").attr("class","nv-legendWrap"),o&&(n.width(d).key(t.x()),b.select(".nv-legendWrap").datum(t.values()(u[0])).call(n),r.top!=n.height()&&(r.top=n.height(),m=(s||parseInt(a.style("height"))||400)-r.top-r.bottom),b.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),b.attr("transform","translate("+r.left+","+r.top+")"),t.width(d).height(m);var S=E.select(".nv-pieWrap").datum(u);d3.transition(S).call(t),n.dispatch.on("legendClick",function(n,r,i){n.disabled=!n.disabled,t.values()(u[0]).filter(function(e){return!e.disabled}).length||t.values()(u[0]).map(function(e){return e.disabled=!1,b.selectAll(".nv-series").classed("disabled",!1),e}),l.disabled=u[0].map(function(e){return!!e.disabled}),p.stateChange(l),e.transition().call(v)}),t.dispatch.on("elementMouseout.tooltip",fun
ction(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(u[0].forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),e.call(v)})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+t+"</p>"},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","
y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","donut","donutRatio","labelThreshold"),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){function B(e){return e.each(fun
ction(e){function V(){if(!g)return!1;var i,a=d3.merge(e.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n)+Math.random()*1e-10,i=l(e,n)+Math.random()*1e-10;return[o(r),u(i),t,n,e]}).filter(function(e,t){return y(e[4],t)})}));if(O===!0){if(S){var c=q.select("defs").selectAll(".nv-point-clips").data([s]).enter();c.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var h=q.select("#nv-points-clip-"+s).selectAll("circle").data(a);h.enter().append("circle").attr("r",x),h.exit().remove(),h.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),q.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}a.push([o.range()[0]-20,u.range()[0]-20,null,null]),a.push([o.range()[1]+20,u.range()[1]+20,null,null]),a.push([o.range()[0]-20,u.range()[0]+20,null,null]),a.push([o.range()[1]+20,u.range()[1]-20,null,null]);var p=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),d=d3.geom.voronoi(a).map(functio
n(e,t){return{data:p.clip(e),series:a[t][2],point:a[t][3]}}),v=q.select(".nv-point-paths").selectAll("path").data(d);v.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),v.exit().remove(),v.attr("d",function(e){return e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"}),v.on("click",function(n){if(H)return 0;var r=e[n.series],i=r.values[n.point];A.elementClick({point:i,series:r,pos:[o(f(i,n.point))+t.left,u(l(i,n.point))+t.top],seriesIndex:n.series,pointIndex:n.point})}).on("mouseover",function(n){if(H)return 0;var r=e[n.series],i=r.values[n.point];A.elementMouseover({point:i,series:r,pos:[o(f(i,n.point))+t.left,u(l(i,n.point))+t.top],seriesIndex:n.series,pointIndex:n.point})}).on("mouseout",function(t,n){if(H)return 0;var r=e[t.series],i=r.values[t.point];A.elementMouseout({point:i,series:r,seriesIndex:t.series,pointIndex:t.point})})}else q.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(n,r){if(H||!e[n.series])retu
rn 0;var i=e[n.series],s=i.values[r];A.elementClick({point:s,series:i,pos:[o(f(s,r))+t.left,u(l(s,r))+t.top],seriesIndex:n.series,pointIndex:r})}).on("mouseover",function(n,r){if(H||!e[n.series])return 0;var i=e[n.series],s=i.values[r];A.elementMouseover({point:s,series:i,pos:[o(f(s,r))+t.left,u(l(s,r))+t.top],seriesIndex:n.series,pointIndex:r})}).on("mouseout",function(t,n){if(H||!e[t.series])return 0;var r=e[t.series],i=r.values[n];A.elementMouseout({point:i,series:r,seriesIndex:t.series,pointIndex:n})});H=!1}var B=n-t.left-t.right,j=r-t.top-t.bottom,F=d3.select(this);e=e.map(function(e,t){return e.values=e.values.map(function(e){return e.series=t,e}),e});var I=T&&N&&C?[]:d3.merge(e.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(T||d3.extent(I.map(function(e){return e.x}).concat(d))),b&&e[0]?o.range([(B*w+B)/(2*e[0].values.length),B-B*(1+w)/(2*e[0].values.length)]):o.range([0,B]),u.domain(N||d3.extent(I.map(function(e)
{return e.y}).concat(v))).range([j,0]),a.domain(C||d3.extent(I.map(function(e){return e.size}).concat(m))).range(k||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])L=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]+u.domain()[0]*.01,u.domain()[1]-u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),M=M||o,_=_||u,D=D||a;var q=F.selectAll("g.nv-wrap.nv-scatter").data([e]),R=q.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(L?" nv-single-point":"")),U=R.append("defs"),W=R.append("g"),X=q.select("g");W.append("g").attr("class","nv-groups"),W.append("g").attr("class","nv-point-paths"),q.attr("transform","translate("+t.left+","+t.top+")"),U.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),q.sele
ct("#nv-edge-clip-"+s+" rect").attr("width",B).attr("height",j),X.attr("clip-path",E?"url(#nv-edge-clip-"+s+")":""),H=!0;var $=q.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});$.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),d3.transition($.exit()).style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),$.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),d3.transition($).style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var J=$.selectAll("circle.nv-point").data(function(e){return e.values});J.enter().append("circle").attr("cx",function(e,t){return M(f(e,t))}).attr("cy",function(e,t){return _(l(e,t))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),J.exit().remove(),d3.transition($.exit().selectAll("path.nv-point")).attr("cx",fu
nction(e,t){return o(f(e,t))}).attr("cy",function(e,t){return u(l(e,t))}).remove(),J.attr("class",function(e,t){return"nv-point nv-point-"+t}),d3.transition(J).attr("cx",function(e,t){return o(f(e,t))}).attr("cy",function(e,t){return u(l(e,t))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var J=$.selectAll("path.nv-point").data(function(e){return e.values});J.enter().append("path").attr("transform",function(e,t){return"translate("+M(f(e,t))+","+_(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),J.exit().remove(),d3.transition($.exit().selectAll("path.nv-point")).attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),J.attr("class",function(e,t){return"nv-point nv-point-"+t}),d3.transition(J).attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(P),P=setTimeout(V,300),M=o.cop
y(),_=u.copy(),D=a.copy()}),B}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=function(e){return!e.notActive},b=!1,w=.1,E=!1,S=!0,x=function(){return 25},T=null,N=null,C=null,k=null,L=!1,A=d3.dispatch("elementClick","elementMouseover","elementMouseout"),O=!0,M,_,D,P,H=!1;return A.on("elementMouseover.point",function(e){g&&d3.select(".nv-chart-"+s+" .nv-series-"+e.seriesIndex+" .nv-point-"+e.pointIndex).classed("hover",!0)}),A.on("elementMouseout.point",function(e){g&&d3.select(".nv-chart-"+s+" .nv-series-"+e.seriesIndex+" .nv-point-"+e.pointIndex).classed("hover",!1)}),B.dispatch=A,B.x=function(e){return arguments.length?(f=d3.functor(e),B):f},B.y=function(e){return arguments.length?(l=d3.functor(e),B):l},B.si
ze=function(e){return arguments.length?(c=d3.functor(e),B):c},B.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,B):t},B.width=function(e){return arguments.length?(n=e,B):n},B.height=function(e){return arguments.length?(r=e,B):r},B.xScale=function(e){return arguments.length?(o=e,B):o},B.yScale=function(e){return arguments.length?(u=e,B):u},B.zScale=function(e){return arguments.length?(a=e,B):a},B.xDomain=function(e){return arguments.length?(T=e,B):T},B.yDomain=function(e){return arguments.length?(N=e,B):N},B.sizeDomain=function(e){return arguments.length?(C=e,B):C},B.sizeRange=function(e){return arguments.length?(k=e,B):k},B.forceX=function(e){return arguments.length?(d=e,B):d},B.forceY=function(e){return arguments.length?(v=e,B):v},B.forceSize=function(e){return arguments.length?(m=
e,B):m},B.interactive=function(e){return arguments.length?(g=e,B):g},B.pointActive=function(e){return arguments.length?(y=e,B):y},B.padData=function(e){return arguments.length?(b=e,B):b},B.padDataOuter=function(e){return arguments.length?(w=e,B):w},B.clipEdge=function(e){return arguments.length?(E=e,B):E},B.clipVoronoi=function(e){return arguments.length?(S=e,B):S},B.useVoronoi=function(e){return arguments.length?(O=e,O===!1&&(S=!1),B):O},B.clipRadius=function(e){return arguments.length?(x=e,B):x},B.color=function(t){return arguments.length?(i=e.utils.getColor(t),B):i},B.shape=function(e){return arguments.length?(h=e,B):h},B.onlyCircles=function(e){return arguments.length?(p=e,B):p},B.id=function(e){return arguments.length?(s=e,B):s},B.singlePoint=function(e){return arguments.length?(L=e,B):L},B},e.models.scatterChart=function(){function P(e){return e.each(function(x){function X(){if(E)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-pa
ths").style("pointer-events","none");var e=d3.mouse(this);h.distortion(w).focus(e[0]),p.distortion(w).focus(e[1]),U.select(".nv-scatterWrap"
+).call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r),U.select(".nv-distributionX").datum(x.filter(function(e){return!e.disabled})).call(o),U.select(".nv-distributionY").datum(x.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,H=(f||parseInt(T.style("width"))||960)-a.left-a.right,B=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;P.update=function(){P(e)},P.container=this,C.disabled=x.map(function(e){return!!e.disabled});if(!k){var j;k={};for(j in C)C[j]instanceof Array?k[j]=C[j].slice(0):k[j]=C[j]}if(!x||!x.length||!x.filter(function(e){return e.values.length}).length){var F=T.selectAll(".nv-noData").data([A]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",a.left+H/2).attr("y",a.top+B/2).text(function(e){return e}),P}T.selectAll(".nv-noData").remove(),O=O||h,M=M||p;var I=T.selectAll("g.nv-wrap.nv-scatterChart").data([x]),q=I.enter().append("g")
.attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),R=q.append("g"),U=I.select("g");R.append("rect").attr("class","nvd3 nv-background"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),y&&(i.width(H/2),I.select(".nv-legendWrap").datum(x).call(i),a.top!=i.height()&&(a.top=i.height(),B=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),I.select(".nv-legendWrap").attr("transform","translate("+H/2+","+ -a.top+")")),b&&(s.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(D).attr("transform","translate(0,"+ -a.top+")").call(s)),I.attr("transform","translate("+a.left+","+a.top+")"),t.width(H).height(B).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),I.select(".nv-scatterWrap").datum(x.filter(functio
n(e){return!e.disabled})).call(t);if(d){var z=h.domain()[1]-h.domain()[0];h.domain([h.domain()[0]-d*z,h.domain()[1]+d*z])}if(v){var W=p.domain()[1]-p.domain()[0];p.domain([p.domain()[0]-v*W,p.domain()[1]+v*W])}n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():H/100).tickSize(-B,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n),r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():B/36).tickSize(-H,0),U.select(".nv-y.nv-axis").call(r),m&&(o.getData(t.x()).scale(h).width(H).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(x.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(B).color(x.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!x[t].disabled})),R.select(".nv-distWrap").append
("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate(-"+u.size()+",0)").datum(x.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(U.select(".nv-background").attr("width",H).attr("height",B),U.select(".nv-background").on("mousemove",X),U.select(".nv-background").on("click",function(){E=!E}),t.dispatch.on("elementClick.freezeFisheye",function(){E=!E})),s.dispatch.on("legendClick",function(i,s){i.disabled=!i.disabled,w=i.disabled?0:2.5,U.select(".nv-background").style("pointer-events",i.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",i.disabled?"all":"none"),i.disabled?(h.distortion(w).focus(0),p.distortion(w).focus(0),U.select(".nv-scatterWrap").call(t),U.select(".nv-x.nv-axis").call(n),U.select(".nv-y.nv-axis").call(r)):E=!1,P(e)}),i.dispatch.on("legendClick",function(t,n,r){t.disabled=!t.disabled,x.filter(function(e){return!e.disabled}).length||x.map(function(e){return e.disabled=!1,I.selectAll
(".nv-series").classed("disabled",!1),e}),C.disabled=x.map(function(e){return!!e.disabled}),L.stateChange(C),P(e)}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-B),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],L.tooltipShow(e)}),L.on("tooltipShow",function(e){S&&_(e,N.parentNode)}),L.on("changeState",function(t){typeof t.disabled!="undefined"&&(x.forEach(function(e,n){e.disabled=t.disabled[n]}),C.disabled=t.disabled),e.call(P)}),O=h.copy(),M=p.copy()}),P}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.
fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!!d3.fisheye,w=0,E=!1,S=!0,x=function(e,t,n){return"<strong>"+t+"</strong>"},T=function(e,t,n){return"<strong>"+n+"</strong>"},N=null,C={},k=null,L=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),A="No Data Available.";t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient("left").tickPadding(10),o.axis("x"),u.axis("y");var O,M,_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));x!=null&&e.tooltip.show([f,l],x(i.series.key,v,m,i,P),"n",1,s,"x-nvtooltip"),T!=null&&e.tooltip.show([c,d],T(i.series.key,v,m,i,P),"e",1,s,"y-nvtooltip"),N!=null&&e.tooltip.show([o,u],N(i.series.key,v,m,i,P),i.value<0?"n":"s",null,
s)},D=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){L.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),L.on("tooltipHide",function(){S&&e.tooltip.cleanup()}),P.dispatch=L,P.scatter=t,P.legend=i,P.controls=s,P.xAxis=n,P.yAxis=r,P.distX=o,P.distY=u,d3.rebind(P,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),P.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,P):a},P.width=function(e){return arguments.length?(f=e,P):f},P.he
ight=function(e){return arguments.length?(l=e,P):l},P.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),P):c},P.showDistX=function(e){return arguments.length?(m=e,P):m},P.showDistY=function(e){return arguments.length?(g=e,P):g},P.showControls=function(e){return arguments.length?(b=e,P):b},P.showLegend=function(e){return arguments.length?(y=e,P):y},P.fisheye=function(e){return arguments.length?(w=e,P):w},P.xPadding=function(e){return arguments.length?(d=e,P):d},P.yPadding=function(e){return arguments.length?(v=e,P):v},P.tooltips=function(e){return arguments.length?(S=e,P):S},P.tooltipContent=function(e){return arguments.length?(N=e,P):N},P.tooltipXContent=function(e){return arguments.length?(x=e,P):x},P.tooltipYContent=function(e){return arguments.length?(T=e,P):T},P.state=function(e){return arguments.length?(C=e,P):C},P.defaultState=function(e){return arguments.length?(k=e,P):k},P.noData=function(e){return arguments.length?(A=e
,P):A},P},e.models.scatterPlusLineChart=function(){function _(e){return e.each(function(E){function z(){if(b)return q.select(".nv-point-paths").style("pointer-events","all"),!1;q.select(".nv-point-paths").style("pointer-events","none");var e=d3.mouse(this);h.distortion(y).focus(e[0]),p.distortion(y).focus(e[1]),q.select(".nv-scatterWrap").datum(E.filter(function(e){return!e.disabled})).call(t),q.select(".nv-x.nv-axis").call(n),q.select(".nv-y.nv-axis").call(r),q.select(".nv-distributionX").datum(E.filter(function(e){return!e.disabled})).call(o),q.select(".nv-distributionY").datum(E.filter(function(e){return!e.disabled})).call(u)}var S=d3.select(this),x=this,D=(f||parseInt(S.style("width"))||960)-a.left-a.right,P=(l||parseInt(S.style("height"))||400)-a.top-a.bottom;_.update=function(){_(e)},_.container=this,T.disabled=E.map(function(e){return!!e.disabled});if(!N){var H;N={};for(H in T)T[H]instanceof Array?N[H]=T[H].slice(0):N[H]=T[H]}if(!E||!E.length||!E.filter(function(e){re
turn e.values.length}).length){var B=S.selectAll(".nv-noData").data([k]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",a.left+D/2).attr("y",a.top+P/2).text(function(e){return e}),_}S.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),L=L||h,A=A||p;var j=S.selectAll("g.nv-wrap.nv-scatterChart").data([E]),F=j.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),I=F.append("g"),q=j.select("g");I.append("rect").attr("class","nvd3 nv-background"),I.append("g").attr("class","nv-x nv-axis"),I.append("g").attr("class","nv-y nv-axis"),I.append("g").attr("class","nv-scatterWrap"),I.append("g").attr("class","nv-regressionLinesWrap"),I.append("g").attr("class","nv-distWrap"),I.append("g").attr("class","nv-legendWrap"),I.append("g").attr("class","nv-controlsWrap"),j.attr("transform","translate("+a.left+","+a.top+")"),m&&(i.width(D/2),j.select(".nv-legendWrap").datum(E).call(i
),a.top!=i.height()&&(a.top=i.height(),P=(l||parseInt(S.style("height"))||400)-a.top-a.bottom),j.select(".nv-legendWrap").attr("transform","translate("+D/2+","+ -a.top+")")),g&&(s.width(180).color(["#444"]),q.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(D).height(P).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),j.select(".nv-scatterWrap").datum(E.filter(function(e){return!e.disabled})).call(t),j.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var R=j.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e}),U=R.enter().append("g").attr("class","nv-regLines").append("line").attr("class","nv-regLine").style("stroke-opacity",0);R.selectAll(".nv-regLines line").attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.d
omain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),n.scale(h).ticks(n.ticks()?n.ticks():D/100).tickSize(-P,0),q.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n),r.scale(p).ticks(r.ticks()?r.ticks():P/36).tickSize(-D,0),q.select(".nv-y.nv-axis").call(r),d&&(o.getData(t.x()).scale(h).width(D).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),I.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),q.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(E.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width(P).color(E.map(function(e,t){return e.color||c(e,t)}).filter(function(e,t){return!E[t].disabled})),I.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),q.s
elect(".nv-distributionY").attr("transform","translate(-"+u.size()+",0)").datum(E.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(q.select(".nv-background").attr("width",D).attr("height",P),q.select(".nv-background").on("mousemove",z),q.select(".nv-background").on("click",function(){b=!b}),t.dispatch.on("elementClick.freezeFisheye",function(){b=!b})),s.dispatch.on("legendClick",function(i,s){i.disabled=!i.disabled,y=i.disabled?0:2.5,q.select(".nv-background").style("pointer-events",i.disabled?"none":"all"),q.select(".nv-point-paths").style("pointer-events",i.disabled?"all":"none"),i.disabled?(h.distortion(y).focus(0),p.distortion(y).focus(0),q.select(".nv-scatterWrap").call(t),q.select(".nv-x.nv-axis").call(n),q.select(".nv-y.nv-axis").call(r)):b=!1,_(e)}),i.dispatch.on("legendClick",function(t,n,r){t.disabled=!t.disabled,E.filter(function(e){return!e.disabled}).length||E.map(function(e){return e.disabled=!1,j.selectAll(".nv-series").classed("disabled",!1),e}),
T.disabled=E.map(function(e){return!!e.disabled}),C.stateChange(T),_(e)}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-P),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],C.tooltipShow(e)}),C.on("tooltipShow",function(e){w&&O(e,x.parentNode)}),C.on("changeState",function(t){typeof t.disabled!="undefined"&&(E.forEach(function(e,n){e.disabled=t.disabled[n]}),T.disabled=t.disabled),e.call(_)}),L=h.copy(),A=p.copy()}),_}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).
distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!!d3.fisheye,y=0,b=!1,w=!0,E=function(e,t,n){return"<strong>"+t+"</strong>"},S=function(e,t,n){return"<strong>"+n+"</strong>"},x=function(e,t,n,r){return"<h3>"+e+"</h3>"+"<p>"+r+"</p>"},T={},N=null,C=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),k="No Data Available.";t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient("left").tickPadding(10),o.axis("x"),u.axis("y");var L,A,O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));E!=null&&e.tooltip.show([f,l],E(i.series.key,v,m,i,_),"n",1,s,"x-nvtooltip"),S!=null&&e.tooltip.show([c,d],S(i.series.key,v,m,i,_),"e",1,s,"y-nvtooltip"),x!=null&&e.tooltip.show([o,u],x(i.series.key,v,m,i.point.tooltip,i,_),i.val
ue<0?"n":"s",null,s)},M=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){C.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),C.on("tooltipHide",function(){w&&e.tooltip.cleanup()}),_.dispatch=C,_.scatter=t,_.legend=i,_.controls=s,_.xAxis=n,_.yAxis=r,_.distX=o,_.distY=u,d3.rebind(_,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),_.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,_):a},_.width=function(e){return arguments.leng
th?(f=e,_):f},_.height=function(e){return arguments.length?(l=e,_):l},_.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),_):c},_.showDistX=function(e){return arguments.length?(d=e,_):d},_.showDistY=function(e){return arguments.length?(v=e,_):v},_.showControls=function(e){return arguments.length?(g=e,_):g},_.showLegend=function(e){return arguments.length?(m=e,_):m},_.fisheye=function(e){return arguments.length?(y=e,_):y},_.tooltips=function(e){return arguments.length?(w=e,_):w},_.tooltipContent=function(e){return arguments.length?(x=e,_):x},_.tooltipXContent=function(e){return arguments.length?(E=e,_):E},_.tooltipYContent=function(e){return arguments.length?(S=e,_):S},_.state=function(e){return arguments.length?(T=e,_):T},_.defaultState=function(e){return arguments.length?(N=e,_):N},_.noData=function(e){return arguments.length?(k=e,_):k},_},e.models.sparkline=function(){function h(e){return e.each(function(e){var i=n-t.left-t.r
ight,h=r-t.top-t.bottom,p=d3.select(this);s.domain(l||d3.extent(e,u)).range([0,i]),o.domain(c||d3.extent(e,a)).range([h,0]);var d=p.selectAll("g.nv-wrap.nv-sparkline").data([e]),v=d.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),m=v.append("g"),g=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var b=d.selectAll("path").data(function(e){return[e]});b.enter().append("path"),b.exit().remove(),b.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var w=d.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});w.enter().append("circle"),w.exit().remove(),w.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",f
unction(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),h}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c;return h.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,h):t},h.width=function(e){return arguments.length?(n=e,h):n},h.height=function(e){return arguments.length?(r=e,h):r},h.x=function(e){return arguments.length?(u=d3.functor(e),h):u},h.y=function(e){return arguments.length?(a=d3.functor(e),h):a},h.xScale=function(e){return arguments.length?(s=e,h):s},h.yScale=function(e){ret
urn arguments.length?(o=e,h):o},h.xDomain=function(e){return arguments.length?(l=e,h):l},h.yDomain=function(e){return arguments.length?(c=e,h):c},h.animate=function(e){return arguments.length?(i=e,h):i},h.color=function(t){return arguments.length?(f=e.utils.getColor(t),h):f},h},e.models.sparklinePlus=function(){function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.sel
ect(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s<e.length;s++)Math.abs(t.x()(e[s],s)-n)<r&&(r=Math.abs(t.x()(e[s],s)-n),i=s);return i}if(a)return;var e=d3.mouse(this)[0]-n.left;u=[r(c,Math.round(s.invert(e)))],O()}var m=d3.select(this),g=(r||parseInt(m.style("width"))||960)-n.left-n.right,b=(i||parseInt(m.style("height"))||400)-n.top-n.bottom;v.update=function(){v(e)},v.container=this;if(!c||!c.length){var w=m.selectAll(".nv-noData").data([d]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",n.left+g/2).attr("y",n.top+b/2).text(function(e){return e}),v}m.selectAll(".nv-noData").remove();var E=t.y()(c[c.length-1],c.length-1);s=t.xS
cale(),o=t.yScale();var S=m.selectAll("g.nv-wrap.nv-sparklineplus").data([c]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-sparklineplus"),N=T.append("g"),C=S.select("g");N.append("g").attr("class","nv-sparklineWrap"),N.append("g").attr("class","nv-valueWrap"),N.append("g").attr("class","nv-hoverArea"),S.attr("transform","translate("+n.left+","+n.top+")");var k=C.select(".nv-sparklineWrap");t.width(g).height(b),k.call(t);var L=C.select(".nv-valueWrap"),A=L.selectAll(".nv-currentValue").data([E]);A.enter().append("text").attr("class","nv-currentValue").attr("dx",p?-8:8).attr("dy",".9em").style("text-anchor",p?"end":"start"),A.attr("x",g+(p?n.right:0)).attr("y",h?function(e){return o(e)}:0).style("fill",t.color()(c[c.length-1],c.length-1)).text(l(E)),N.select(".nv-hoverArea").append("rect").on("mousemove",M).on("click",function(){a=!a}).on("mouseout",function(){u=[],O()}),C.select(".nv-hoverArea rect").attr("transform",function(e){return"translate("+ -n.left+","+ -n.t
op+")"}).attr("width",g+n.left+n.right).attr("height",b+n.top)}),v}var t=e.models.sparkline(),n={top:15,right:100,bottom:10,left:50},r=null,i=null,s,o,u=[],a=!1,f=d3.format(",r"),l=d3.format(",.2f"),c=!0,h=!0,p=!1,d="No Data Available.";return v.sparkline=t,d3.rebind(v,t,"x","y","xScale","yScale","color"),v.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,v):n},v.width=function(e){return arguments.length?(r=e,v):r},v.height=function(e){return arguments.length?(i=e,v):i},v.xTickFormat=function(e){return arguments.length?(f=e,v):f},v.yTickFormat=function(e){return arguments.length?(l=e,v):l},v.showValue=function(e){return arguments.length?(c=e,v):c},v.alignValue=function(e){return arguments.length?(h=e,v):h},v.rightAlignValue=function(e){return arguments.length?(p=e,v):p},v.noData=func
tion(e){return arguments.length?(d=e,v):d},v},e.models.stackedArea=function(){function g(e){return e.each(function(e){var a=n-t.left-t.right,g=r-t.top-t.bottom,b=d3.select(this);p=v.xScale(),d=v.yScale(),e=e.map(function(e,t){return e.values=e.values.map(function(t,n){return t.index=n,t.stackedY=e.disabled?0:u(t,n),t}),e}),e=d3.layout.stack().order(l).offset(f).values(function(e){return e.values}).x(o).y(function(e){return e.stackedY}).out(function(e,t,n){e.display={y:n,y0:t}})(e);var w=b.selectAll("g.nv-wrap.nv-stackedarea").data([e]),E=w.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedarea"),S=E.append("defs"),T=E.append("g"),N=w.select("g");T.append("g").attr("class","nv-areaWrap"),T.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+t.left+","+t.top+")"),v.width(a).height(g).x(o).y(function(e){return e.display.y+e.display.y0}).forceY([0]).color(e.map(function(e,t){return e.color||i(e,t)}).filter(function(t,n){return!e[n].disabled}));var C
=N.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled}));C.call(v),S.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),w.select("#nv-edge-clip-"+s+" rect").attr("width",a).attr("height",g),N.attr("clip-path",h?"url(#nv-edge-clip-"+s+")":"");var k=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y+e.display.y0)}).interpolate(c),L=d3.svg.area().x(function(e,t){return p(o(e,t))}).y0(function(e){return d(e.display.y0)}).y1(function(e){return d(e.display.y0)}),A=N.select(".nv-areaWrap").selectAll("path.nv-area").data(function(e){return e});A.enter().append("path").attr("class",function(e,t){return"nv-area nv-area-"+t}).on("mouseover",function(e,t){d3.select(this).classed("hover",!0),m.areaMouseover({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),m.areaMouseout({point:e,series:e.key,po
s:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}).on("click",function(e,t){d3.select(this).classed("hover",!1),m.areaClick({point:e,series:e.key,pos:[d3.event.pageX,d3.event.pageY],seriesIndex:t})}),A.exit().attr("d",function(e,t){return L(e.values,t)}).remove(),A.style("fill",function(e,t){return e.color||i(e,t)}).style("stroke",function(e,t){return e.color||i(e,t)}),A.attr("d",function(e,t){return k(e.values,t)}),v.dispatch.on("elementMouseover.area",function(e){N.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!0)}),v.dispatch.on("elementMouseout.area",function(e){N.select(".nv-chart-"+s+" .nv-area-"+e.seriesIndex).classed("hover",!1)})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=function(e){return e.x},u=function(e){return e.y},a="stack",f="zero",l="default",c="linear",h=!1,p,d,v=e.models.scatter(),m=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");
return v.size(2.2).sizeDomain([2.2,2.2]),v.dispatch.on("elementClick.area",function(e){m.areaClick(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],m.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){m.tooltipHide(e)}),g.dispatch=m,g.scatter=v,d3.rebind(g,v,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","sizeDomain","forceX","forceY","forceSize","clipVoronoi","clipRadius"),g.x=function(e){return arguments.length?(o=d3.functor(e),g):o},g.y=function(e){return arguments.length?(u=d3.functor(e),g):u},g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.clipEdge=function(e){return argume
nts.length?(h=e,g):h},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),g):i},g.offset=function(e){return arguments.length?(f=e,g):f},g.order=function(e){return arguments.length?(l=e,g):l},g.style=function(e){if(!arguments.length)return a;a=e;switch(a){case"stack":g.offset("zero"),g.order("default");break;case"stream":g.offset("wiggle"),g.order("inside-out");break;case"stream-center":g.offset("silhouette"),g.order("inside-out");break;case"expand":g.offset("expand"),g.order("default")}return g},g.interpolate=function(e){return arguments.length?(c=e,c):c},g},e.models.stackedAreaChart=function(){function x(e){return e.each(function(f){var p=d3.select(this),T=this,N=(u||parseInt(p.style("width"))||960)-o.left-o.right,C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom;x.update=function(){x(e)},x.container=this,g.disabled=f.map(function(e){return!!e.disabled});if(!y){var k;y={};for(k in g)g[k]instanceof Array?y[k]=g[k].slice(0):y[k]=g[k]}if(!f||!f.length||!f.f
ilter(function(e){return e.values.length}).length){var L=p.selectAll(".nv-noData").data([b]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",o.left+N/2).attr("y",o.top+C/2).text(function(e){return e}),x}p.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale();var A=p.selectAll("g.nv-wrap.nv-stackedAreaChart").data([f]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),M=A.select("g");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-stackedWrap"),O.append("g").attr("class","nv-legendWrap"),O.append("g").attr("class","nv-controlsWrap"),c&&(i.width(N-E),M.select(".nv-legendWrap").datum(f).call(i),o.top!=i.height()&&(o.top=i.height(),C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom),M.select(".nv-legendWrap").attr("transform","translate("+E+","+ -o.top+")"));if(l){var _=[{key:"Stacked",disabled
:t.offset()!="zero"},{key:"Stream",disabled:t.offset()!="wiggle"},{key:"Expanded",disabled:t.offset()!="expand"}];s.width(E).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(_).call(s),o.top!=Math.max(s.height(),i.height())&&(o.top=Math.max(s.height(),i.height()),C=(a||parseInt(p.style("height"))||400)-o.top-o.bottom),M.select(".nv-controlsWrap").attr("transform","translate(0,"+ -o.top+")")}A.attr("transform","translate("+o.left+","+o.top+")"),t.width(N).height(C);var D=M.select(".nv-stackedWrap").datum(f);D.call(t),n.scale(d).ticks(N/100).tickSize(-C,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+C+")"),M.select(".nv-x.nv-axis").transition().duration(0).call(n),r.scale(v).ticks(t.offset()=="wiggle"?0:C/36).tickSize(-N,0).setTickFormat(t.offset()=="expand"?d3.format("%"):m),M.select(".nv-y.nv-axis").transition().duration(0).call(r),t.dispatch.on("areaClick.toggle",function(t){f.filter(function(e){return!e.disabled}).length===1?f=f.map(function(e
){return e.disabled=!1,e}):f=f.map(function(e,n){return e.disabled=n!=t.seriesIndex,e}),g.disabled=f.map(function(e){return!!e.disabled}),w.stateChange(g),x(e)}),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,f.filter(function(e){return!e.disabled}).length||f.map(function(e){return e.disabled=!1,e}),g.disabled=f.map(function(e){return!!e.disabled}),w.stateChange(g),x(e)}),s.dispatch.on("legendClick",function(n,r){if(!n.disabled)return;_=_.map(function(e){return e.disabled=!0,e}),n.disabled=!1;switch(n.key){case"Stacked":t.style("stack");break;case"Stream":t.style("stream");break;case"Expanded":t.style("expand")}g.style=t.style(),w.stateChange(g),x(e)}),w.on("tooltipShow",function(e){h&&S(e,T.parentNode)}),w.on("changeState",function(n){typeof n.disabled!="undefined"&&(f.forEach(function(e,t){e.disabled=n.disabled[t]}),g.disabled=n.disabled),typeof n.style!="undefined"&&t.style(n.style),e.call(x)})}),x}var t=e.models.stackedArea(),n=e.models.axis(),r=e.model
s.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:25,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=function(e,t,n,r,i){return"<h3>"+e+"</h3>"+"<p>"+n+" on "+t+"</p>"},d,v,m=d3.format(",.2f"),g={style:t.style()},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=250;n.orient("bottom").tickPadding(7),r.orient("left"),t.scatter.pointActive(function(e){return!!Math.round(t.y()(e)*100)});var S=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,x);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],w.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),x.dispatch=w,x.stacked=t,x.legend=i,x.c
ontrols=s,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"x","y","size","xScale","yScale","xDomain","yDomain","sizeDomain","interactive","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),x.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,x):o},x.width=function(e){return arguments.length?(u=e,x):getWidth},x.height=function(e){return arguments.length?(a=e,x):getHeight},x.color=function(n){return arguments.length?(f=e.utils.getColor(n),i.color(f),t.color(f),x):f},x.showControls=function(e){return arguments.length?(l=e,x):l},x.showLegend=function(e){return arguments.length?(c=e,x):c},x.tooltip=function(e){return arguments.length?(p=e,x):p},x.tooltips=function(e){return arguments.length?(h=e,x):h},x.tooltipContent=function(e){return arguments.length?(p=e,x):p},x.state=fu
nction(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments
+.length?(b=e,x):b},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(m=e,r):m},x}})();
\ No newline at end of file
commit 5910881f73a934e84dd80572b40142154483e2eb
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 14:14:40 2013 -0700
Update the d3 javascript libraries to 3.1.10.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
old mode 100644
new mode 100755
index 04cba44..94cb5d4
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.js
@@ -1,17 +1,11 @@
d3 = function() {
- var π = Math.PI, ε = 1e-6, d3 = {
- version: "3.0.6"
- }, d3_radians = π / 180, d3_degrees = 180 / π, d3_document = document, d3_window = window;
- function d3_target(d) {
- return d.target;
- }
- function d3_source(d) {
- return d.source;
- }
- var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ];
+ var d3 = {
+ version: "3.1.10"
+ };
if (!Date.now) Date.now = function() {
return +new Date();
};
+ var d3_document = document, d3_window = window;
try {
d3_document.createElement("div").style.setProperty("opacity", 0, "");
} catch (error) {
@@ -20,133 +14,12 @@ d3 = function() {
d3_style_setProperty.call(this, name, value + "", priority);
};
}
- function d3_class(ctor, properties) {
- try {
- for (var key in properties) {
- Object.defineProperty(ctor.prototype, key, {
- value: properties[key],
- enumerable: false
- });
- }
- } catch (e) {
- ctor.prototype = properties;
- }
- }
- var d3_array = d3_arraySlice;
- function d3_arrayCopy(pseudoarray) {
- var i = -1, n = pseudoarray.length, array = [];
- while (++i < n) array.push(pseudoarray[i]);
- return array;
- }
- function d3_arraySlice(pseudoarray) {
- return Array.prototype.slice.call(pseudoarray);
- }
- try {
- d3_array(d3_document.documentElement.childNodes)[0].nodeType;
- } catch (e) {
- d3_array = d3_arrayCopy;
- }
- var d3_arraySubclass = [].__proto__ ? function(array, prototype) {
- array.__proto__ = prototype;
- } : function(array, prototype) {
- for (var property in prototype) array[property] = prototype[property];
- };
- d3.map = function(object) {
- var map = new d3_Map();
- for (var key in object) map.set(key, object[key]);
- return map;
- };
- function d3_Map() {}
- d3_class(d3_Map, {
- has: function(key) {
- return d3_map_prefix + key in this;
- },
- get: function(key) {
- return this[d3_map_prefix + key];
- },
- set: function(key, value) {
- return this[d3_map_prefix + key] = value;
- },
- remove: function(key) {
- key = d3_map_prefix + key;
- return key in this && delete this[key];
- },
- keys: function() {
- var keys = [];
- this.forEach(function(key) {
- keys.push(key);
- });
- return keys;
- },
- values: function() {
- var values = [];
- this.forEach(function(key, value) {
- values.push(value);
- });
- return values;
- },
- entries: function() {
- var entries = [];
- this.forEach(function(key, value) {
- entries.push({
- key: key,
- value: value
- });
- });
- return entries;
- },
- forEach: function(f) {
- for (var key in this) {
- if (key.charCodeAt(0) === d3_map_prefixCode) {
- f.call(this, key.substring(1), this[key]);
- }
- }
- }
- });
- var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
- function d3_identity(d) {
- return d;
- }
- function d3_true() {
- return true;
- }
- function d3_functor(v) {
- return typeof v === "function" ? v : function() {
- return v;
- };
- }
- d3.functor = d3_functor;
- d3.rebind = function(target, source) {
- var i = 1, n = arguments.length, method;
- while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
- return target;
- };
- function d3_rebind(target, source, method) {
- return function() {
- var value = method.apply(source, arguments);
- return arguments.length ? target : value;
- };
- }
d3.ascending = function(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
};
d3.descending = function(a, b) {
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
};
- d3.mean = function(array, f) {
- var n = array.length, a, m = 0, i = -1, j = 0;
- if (arguments.length === 1) {
- while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
- } else {
- while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
- }
- return j ? m : undefined;
- };
- d3.median = function(array, f) {
- if (arguments.length > 1) array = array.map(f);
- array = array.filter(d3_number);
- return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
- };
d3.min = function(array, f) {
var i = -1, n = array.length, a, b;
if (arguments.length === 1) {
@@ -186,37 +59,6 @@ d3 = function() {
}
return [ a, c ];
};
- d3.random = {
- normal: function(µ, σ) {
- var n = arguments.length;
- if (n < 2) σ = 1;
- if (n < 1) µ = 0;
- return function() {
- var x, y, r;
- do {
- x = Math.random() * 2 - 1;
- y = Math.random() * 2 - 1;
- r = x * x + y * y;
- } while (!r || r > 1);
- return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
- };
- },
- logNormal: function() {
- var random = d3.random.normal.apply(d3, arguments);
- return function() {
- return Math.exp(random());
- };
- },
- irwinHall: function(m) {
- return function() {
- for (var s = 0, j = 0; j < m; j++) s += Math.random();
- return s / m;
- };
- }
- };
- function d3_number(x) {
- return x != null && !isNaN(x);
- }
d3.sum = function(array, f) {
var s = 0, n = array.length, a, i = -1;
if (arguments.length === 1) {
@@ -226,33 +68,27 @@ d3 = function() {
}
return s;
};
+ function d3_number(x) {
+ return x != null && !isNaN(x);
+ }
+ d3.mean = function(array, f) {
+ var n = array.length, a, m = 0, i = -1, j = 0;
+ if (arguments.length === 1) {
+ while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
+ } else {
+ while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
+ }
+ return j ? m : undefined;
+ };
d3.quantile = function(values, p) {
var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
return e ? v + e * (values[h] - v) : v;
};
- d3.shuffle = function(array) {
- var m = array.length, t, i;
- while (m) {
- i = Math.random() * m-- | 0;
- t = array[m], array[m] = array[i], array[i] = t;
- }
- return array;
- };
- d3.transpose = function(matrix) {
- return d3.zip.apply(d3, matrix);
- };
- d3.zip = function() {
- if (!(n = arguments.length)) return [];
- for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
- for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
- zip[j] = arguments[j][i];
- }
- }
- return zips;
+ d3.median = function(array, f) {
+ if (arguments.length > 1) array = array.map(f);
+ array = array.filter(d3_number);
+ return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
};
- function d3_zipLength(d) {
- return d.length;
- }
d3.bisector = function(f) {
return {
left: function(a, x, lo, hi) {
@@ -280,65 +116,38 @@ d3 = function() {
});
d3.bisectLeft = d3_bisector.left;
d3.bisect = d3.bisectRight = d3_bisector.right;
- d3.nest = function() {
- var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
- function map(array, depth) {
- if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
- var i = -1, n = array.length, key = keys[depth++], keyValue, object, valuesByKey = new d3_Map(), values, o = {};
- while (++i < n) {
- if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
- values.push(object);
- } else {
- valuesByKey.set(keyValue, [ object ]);
- }
- }
- valuesByKey.forEach(function(keyValue, values) {
- o[keyValue] = map(values, depth);
- });
- return o;
+ d3.shuffle = function(array) {
+ var m = array.length, t, i;
+ while (m) {
+ i = Math.random() * m-- | 0;
+ t = array[m], array[m] = array[i], array[i] = t;
}
- function entries(map, depth) {
- if (depth >= keys.length) return map;
- var a = [], sortKey = sortKeys[depth++], key;
- for (key in map) {
- a.push({
- key: key,
- values: entries(map[key], depth)
- });
+ return array;
+ };
+ d3.permute = function(array, indexes) {
+ var permutes = [], i = -1, n = indexes.length;
+ while (++i < n) permutes[i] = array[indexes[i]];
+ return permutes;
+ };
+ d3.zip = function() {
+ if (!(n = arguments.length)) return [];
+ for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
+ for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
+ zip[j] = arguments[j][i];
}
- if (sortKey) a.sort(function(a, b) {
- return sortKey(a.key, b.key);
- });
- return a;
}
- nest.map = function(array) {
- return map(array, 0);
- };
- nest.entries = function(array) {
- return entries(map(array, 0), 0);
- };
- nest.key = function(d) {
- keys.push(d);
- return nest;
- };
- nest.sortKeys = function(order) {
- sortKeys[keys.length - 1] = order;
- return nest;
- };
- nest.sortValues = function(order) {
- sortValues = order;
- return nest;
- };
- nest.rollup = function(f) {
- rollup = f;
- return nest;
- };
- return nest;
+ return zips;
};
- d3.keys = function(map) {
- var keys = [];
- for (var key in map) keys.push(key);
- return keys;
+ function d3_zipLength(d) {
+ return d.length;
+ }
+ d3.transpose = function(matrix) {
+ return d3.zip.apply(d3, matrix);
+ };
+ d3.keys = function(map) {
+ var keys = [];
+ for (var key in map) keys.push(key);
+ return keys;
};
d3.values = function(map) {
var values = [];
@@ -353,17 +162,9 @@ d3 = function() {
});
return entries;
};
- d3.permute = function(array, indexes) {
- var permutes = [], i = -1, n = indexes.length;
- while (++i < n) permutes[i] = array[indexes[i]];
- return permutes;
- };
d3.merge = function(arrays) {
return Array.prototype.concat.apply([], arrays);
};
- function d3_collapse(s) {
- return s.trim().replace(/\s+/g, " ");
- }
d3.range = function(start, stop, step) {
if (arguments.length < 3) {
step = 1;
@@ -383,124 +184,179 @@ d3 = function() {
while (x * k % 1) k *= 10;
return k;
}
- d3.requote = function(s) {
- return s.replace(d3_requote_re, "\\$&");
- };
- var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
- d3.round = function(x, n) {
- return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+ function d3_class(ctor, properties) {
+ try {
+ for (var key in properties) {
+ Object.defineProperty(ctor.prototype, key, {
+ value: properties[key],
+ enumerable: false
+ });
+ }
+ } catch (e) {
+ ctor.prototype = properties;
+ }
+ }
+ d3.map = function(object) {
+ var map = new d3_Map();
+ for (var key in object) map.set(key, object[key]);
+ return map;
};
- d3.xhr = function(url, mimeType, callback) {
- var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, response = d3_identity, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)();
- "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
- request.readyState > 3 && respond();
- };
- function respond() {
- var s = request.status;
- !s && request.responseText || s >= 200 && s < 300 || s === 304 ? dispatch.load.call(xhr, response.call(xhr, request)) : dispatch.error.call(xhr, request);
+ function d3_Map() {}
+ d3_class(d3_Map, {
+ has: function(key) {
+ return d3_map_prefix + key in this;
+ },
+ get: function(key) {
+ return this[d3_map_prefix + key];
+ },
+ set: function(key, value) {
+ return this[d3_map_prefix + key] = value;
+ },
+ remove: function(key) {
+ key = d3_map_prefix + key;
+ return key in this && delete this[key];
+ },
+ keys: function() {
+ var keys = [];
+ this.forEach(function(key) {
+ keys.push(key);
+ });
+ return keys;
+ },
+ values: function() {
+ var values = [];
+ this.forEach(function(key, value) {
+ values.push(value);
+ });
+ return values;
+ },
+ entries: function() {
+ var entries = [];
+ this.forEach(function(key, value) {
+ entries.push({
+ key: key,
+ value: value
+ });
+ });
+ return entries;
+ },
+ forEach: function(f) {
+ for (var key in this) {
+ if (key.charCodeAt(0) === d3_map_prefixCode) {
+ f.call(this, key.substring(1), this[key]);
+ }
+ }
}
- request.onprogress = function(event) {
- var o = d3.event;
- d3.event = event;
- try {
- dispatch.progress.call(xhr, request);
- } finally {
- d3.event = o;
+ });
+ var d3_map_prefix = "\0", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
+ d3.nest = function() {
+ var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
+ function map(mapType, array, depth) {
+ if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
+ var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
+ while (++i < n) {
+ if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
+ values.push(object);
+ } else {
+ valuesByKey.set(keyValue, [ object ]);
+ }
+ }
+ if (mapType) {
+ object = mapType();
+ setter = function(keyValue, values) {
+ object.set(keyValue, map(mapType, values, depth));
+ };
+ } else {
+ object = {};
+ setter = function(keyValue, values) {
+ object[keyValue] = map(mapType, values, depth);
+ };
}
+ valuesByKey.forEach(setter);
+ return object;
+ }
+ function entries(map, depth) {
+ if (depth >= keys.length) return map;
+ var array = [], sortKey = sortKeys[depth++];
+ map.forEach(function(key, keyMap) {
+ array.push({
+ key: key,
+ values: entries(keyMap, depth)
+ });
+ });
+ return sortKey ? array.sort(function(a, b) {
+ return sortKey(a.key, b.key);
+ }) : array;
+ }
+ nest.map = function(array, mapType) {
+ return map(mapType, array, 0);
};
- xhr.header = function(name, value) {
- name = (name + "").toLowerCase();
- if (arguments.length < 2) return headers[name];
- if (value == null) delete headers[name]; else headers[name] = value + "";
- return xhr;
+ nest.entries = function(array) {
+ return entries(map(d3.map, array, 0), 0);
};
- xhr.mimeType = function(value) {
- if (!arguments.length) return mimeType;
- mimeType = value == null ? null : value + "";
- return xhr;
+ nest.key = function(d) {
+ keys.push(d);
+ return nest;
};
- xhr.response = function(value) {
- response = value;
- return xhr;
+ nest.sortKeys = function(order) {
+ sortKeys[keys.length - 1] = order;
+ return nest;
};
- [ "get", "post" ].forEach(function(method) {
- xhr[method] = function() {
- return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
- };
- });
- xhr.send = function(method, data, callback) {
- if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
- request.open(method, url, true);
- if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
- if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
- if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
- if (callback != null) xhr.on("error", callback).on("load", function(request) {
- callback(null, request);
- });
- request.send(data == null ? null : data);
- return xhr;
+ nest.sortValues = function(order) {
+ sortValues = order;
+ return nest;
};
- xhr.abort = function() {
- request.abort();
- return xhr;
+ nest.rollup = function(f) {
+ rollup = f;
+ return nest;
};
- d3.rebind(xhr, dispatch, "on");
- if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
- mimeType = null;
- return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
- };
- function d3_xhr_fixCallback(callback) {
- return callback.length === 1 ? function(error, request) {
- callback(error == null ? request : null);
- } : callback;
- }
- d3.text = function() {
- return d3.xhr.apply(d3, arguments).response(d3_text);
- };
- function d3_text(request) {
- return request.responseText;
- }
- d3.json = function(url, callback) {
- return d3.xhr(url, "application/json", callback).response(d3_json);
- };
- function d3_json(request) {
- return JSON.parse(request.responseText);
- }
- d3.html = function(url, callback) {
- return d3.xhr(url, "text/html", callback).response(d3_html);
- };
- function d3_html(request) {
- var range = d3_document.createRange();
- range.selectNode(d3_document.body);
- return range.createContextualFragment(request.responseText);
- }
- d3.xml = function() {
- return d3.xhr.apply(d3, arguments).response(d3_xml);
+ return nest;
};
- function d3_xml(request) {
- return request.responseXML;
- }
- var d3_nsPrefix = {
- svg: "http://www.w3.org/2000/svg",
- xhtml: "http://www.w3.org/1999/xhtml",
- xlink: "http://www.w3.org/1999/xlink",
- xml: "http://www.w3.org/XML/1998/namespace",
- xmlns: "http://www.w3.org/2000/xmlns/"
+ d3.set = function(array) {
+ var set = new d3_Set();
+ if (array) for (var i = 0; i < array.length; i++) set.add(array[i]);
+ return set;
};
- d3.ns = {
- prefix: d3_nsPrefix,
- qualify: function(name) {
- var i = name.indexOf(":"), prefix = name;
- if (i >= 0) {
- prefix = name.substring(0, i);
- name = name.substring(i + 1);
+ function d3_Set() {}
+ d3_class(d3_Set, {
+ has: function(value) {
+ return d3_map_prefix + value in this;
+ },
+ add: function(value) {
+ this[d3_map_prefix + value] = true;
+ return value;
+ },
+ remove: function(value) {
+ value = d3_map_prefix + value;
+ return value in this && delete this[value];
+ },
+ values: function() {
+ var values = [];
+ this.forEach(function(value) {
+ values.push(value);
+ });
+ return values;
+ },
+ forEach: function(f) {
+ for (var value in this) {
+ if (value.charCodeAt(0) === d3_map_prefixCode) {
+ f.call(this, value.substring(1));
+ }
}
- return d3_nsPrefix.hasOwnProperty(prefix) ? {
- space: d3_nsPrefix[prefix],
- local: name
- } : name;
}
+ });
+ d3.behavior = {};
+ d3.rebind = function(target, source) {
+ var i = 1, n = arguments.length, method;
+ while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
+ return target;
};
+ function d3_rebind(target, source, method) {
+ return function() {
+ var value = method.apply(source, arguments);
+ return value === source ? target : value;
+ };
+ }
d3.dispatch = function() {
var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
@@ -509,11 +365,17 @@ d3 = function() {
function d3_dispatch() {}
d3_dispatch.prototype.on = function(type, listener) {
var i = type.indexOf("."), name = "";
- if (i > 0) {
+ if (i >= 0) {
name = type.substring(i + 1);
type = type.substring(0, i);
}
- return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+ if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+ if (arguments.length === 2) {
+ if (listener == null) for (type in this) {
+ if (this.hasOwnProperty(type)) this[type].on(name, null);
+ }
+ return this;
+ }
};
function d3_dispatch_event(dispatch) {
var listeners = [], listenerByName = new d3_Map();
@@ -537,251 +399,25 @@ d3 = function() {
};
return event;
}
- d3.format = function(specifier) {
- var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false;
- if (precision) precision = +precision.substring(1);
- if (zfill || fill === "0" && align === "=") {
- zfill = fill = "0";
- align = "=";
- if (comma) width -= Math.floor((width - 1) / 4);
+ d3.event = null;
+ function d3_eventCancel() {
+ d3.event.stopPropagation();
+ d3.event.preventDefault();
+ }
+ function d3_eventSource() {
+ var e = d3.event, s;
+ while (s = e.sourceEvent) e = s;
+ return e;
+ }
+ function d3_eventSuppress(target, type) {
+ function off() {
+ target.on(type, null);
}
- switch (type) {
- case "n":
- comma = true;
- type = "g";
- break;
-
- case "%":
- scale = 100;
- suffix = "%";
- type = "f";
- break;
-
- case "p":
- scale = 100;
- suffix = "%";
- type = "r";
- break;
-
- case "b":
- case "o":
- case "x":
- case "X":
- if (basePrefix) basePrefix = "0" + type.toLowerCase();
-
- case "c":
- case "d":
- integer = true;
- precision = 0;
- break;
-
- case "s":
- scale = -1;
- type = "r";
- break;
- }
- if (basePrefix === "#") basePrefix = "";
- if (type == "r" && !precision) type = "g";
- type = d3_format_types.get(type) || d3_format_typeDefault;
- var zcomma = zfill && comma;
- return function(value) {
- if (integer && value % 1) return "";
- var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
- if (scale < 0) {
- var prefix = d3.formatPrefix(value, precision);
- value = prefix.scale(value);
- suffix = prefix.symbol;
- } else {
- value *= scale;
- }
- value = type(value, precision);
- if (!zfill && comma) value = d3_format_group(value);
- var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
- if (zcomma) value = d3_format_group(padding + value);
- if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint);
- negative += basePrefix;
- return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix;
- };
- };
- var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/;
- var d3_format_types = d3.map({
- b: function(x) {
- return x.toString(2);
- },
- c: function(x) {
- return String.fromCharCode(x);
- },
- o: function(x) {
- return x.toString(8);
- },
- x: function(x) {
- return x.toString(16);
- },
- X: function(x) {
- return x.toString(16).toUpperCase();
- },
- g: function(x, p) {
- return x.toPrecision(p);
- },
- e: function(x, p) {
- return x.toExponential(p);
- },
- f: function(x, p) {
- return x.toFixed(p);
- },
- r: function(x, p) {
- return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
- }
- });
- function d3_format_precision(x, p) {
- return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
- }
- function d3_format_typeDefault(x) {
- return x + "";
- }
- var d3_format_group = d3_identity;
- if (d3_format_grouping) {
- var d3_format_groupingLength = d3_format_grouping.length;
- d3_format_group = function(value) {
- var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length,
- ""), t = [], j = 0, g = d3_format_grouping[0];
- while (i > 0 && g > 0) {
- t.push(value.substring(i -= g, i + g));
- g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength];
- }
- return t.reverse().join(d3_format_thousandsSeparator || "") + f;
- };
- }
- var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
- d3.formatPrefix = function(value, precision) {
- var i = 0;
- if (value) {
- if (value < 0) value *= -1;
- if (precision) value = d3.round(value, d3_format_precision(value, precision));
- i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
- i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
- }
- return d3_formatPrefixes[8 + i / 3];
- };
- function d3_formatPrefix(d, i) {
- var k = Math.pow(10, Math.abs(8 - i) * 3);
- return {
- scale: i > 8 ? function(d) {
- return d / k;
- } : function(d) {
- return d * k;
- },
- symbol: d
- };
- }
- var d3_ease_default = function() {
- return d3_identity;
- };
- var d3_ease = d3.map({
- linear: d3_ease_default,
- poly: d3_ease_poly,
- quad: function() {
- return d3_ease_quad;
- },
- cubic: function() {
- return d3_ease_cubic;
- },
- sin: function() {
- return d3_ease_sin;
- },
- exp: function() {
- return d3_ease_exp;
- },
- circle: function() {
- return d3_ease_circle;
- },
- elastic: d3_ease_elastic,
- back: d3_ease_back,
- bounce: function() {
- return d3_ease_bounce;
- }
- });
- var d3_ease_mode = d3.map({
- "in": d3_identity,
- out: d3_ease_reverse,
- "in-out": d3_ease_reflect,
- "out-in": function(f) {
- return d3_ease_reflect(d3_ease_reverse(f));
- }
- });
- d3.ease = function(name) {
- var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in";
- t = d3_ease.get(t) || d3_ease_default;
- m = d3_ease_mode.get(m) || d3_identity;
- return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));
- };
- function d3_ease_clamp(f) {
- return function(t) {
- return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
- };
- }
- function d3_ease_reverse(f) {
- return function(t) {
- return 1 - f(1 - t);
- };
- }
- function d3_ease_reflect(f) {
- return function(t) {
- return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
- };
- }
- function d3_ease_quad(t) {
- return t * t;
- }
- function d3_ease_cubic(t) {
- return t * t * t;
- }
- function d3_ease_cubicInOut(t) {
- if (t <= 0) return 0;
- if (t >= 1) return 1;
- var t2 = t * t, t3 = t2 * t;
- return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
- }
- function d3_ease_poly(e) {
- return function(t) {
- return Math.pow(t, e);
- };
- }
- function d3_ease_sin(t) {
- return 1 - Math.cos(t * π / 2);
- }
- function d3_ease_exp(t) {
- return Math.pow(2, 10 * (t - 1));
- }
- function d3_ease_circle(t) {
- return 1 - Math.sqrt(1 - t * t);
- }
- function d3_ease_elastic(a, p) {
- var s;
- if (arguments.length < 2) p = .45;
- if (arguments.length) s = p / (2 * π) * Math.asin(1 / a); else a = 1, s = p / 4;
- return function(t) {
- return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * π / p);
- };
- }
- function d3_ease_back(s) {
- if (!s) s = 1.70158;
- return function(t) {
- return t * t * ((s + 1) * t - s);
- };
- }
- function d3_ease_bounce(t) {
- return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
- }
- d3.event = null;
- function d3_eventCancel() {
- d3.event.stopPropagation();
- d3.event.preventDefault();
- }
- function d3_eventSource() {
- var e = d3.event, s;
- while (s = e.sourceEvent) e = s;
- return e;
+ target.on(type, function() {
+ d3_eventCancel();
+ off();
+ }, true);
+ setTimeout(off, 0);
}
function d3_eventDispatch(target) {
var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
@@ -800,368 +436,1032 @@ d3 = function() {
};
return dispatch;
}
- d3.transform = function(string) {
- var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
- return (d3.transform = function(string) {
- g.setAttribute("transform", string);
- var t = g.transform.baseVal.consolidate();
- return new d3_transform(t ? t.matrix : d3_transformIdentity);
- })(string);
- };
- function d3_transform(m) {
- var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
- if (r0[0] * r1[1] < r1[0] * r0[1]) {
- r0[0] *= -1;
- r0[1] *= -1;
- kx *= -1;
- kz *= -1;
- }
- this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
- this.translate = [ m.e, m.f ];
- this.scale = [ kx, ky ];
- this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
- }
- d3_transform.prototype.toString = function() {
- return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
+ d3.mouse = function(container) {
+ return d3_mousePoint(container, d3_eventSource());
};
- function d3_transformDot(a, b) {
- return a[0] * b[0] + a[1] * b[1];
- }
- function d3_transformNormalize(a) {
- var k = Math.sqrt(d3_transformDot(a, a));
- if (k) {
- a[0] /= k;
- a[1] /= k;
+ var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
+ function d3_mousePoint(container, e) {
+ var svg = container.ownerSVGElement || container;
+ if (svg.createSVGPoint) {
+ var point = svg.createSVGPoint();
+ if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {
+ svg = d3.select(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0);
+ var ctm = svg[0][0].getScreenCTM();
+ d3_mouse_bug44083 = !(ctm.f || ctm.e);
+ svg.remove();
+ }
+ if (d3_mouse_bug44083) {
+ point.x = e.pageX;
+ point.y = e.pageY;
+ } else {
+ point.x = e.clientX;
+ point.y = e.clientY;
+ }
+ point = point.matrixTransform(container.getScreenCTM().inverse());
+ return [ point.x, point.y ];
}
- return k;
+ var rect = container.getBoundingClientRect();
+ return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
}
- function d3_transformCombine(a, b, k) {
- a[0] += k * b[0];
- a[1] += k * b[1];
- return a;
+ var d3_array = d3_arraySlice;
+ function d3_arrayCopy(pseudoarray) {
+ var i = -1, n = pseudoarray.length, array = [];
+ while (++i < n) array.push(pseudoarray[i]);
+ return array;
}
- var d3_transformIdentity = {
- a: 1,
- b: 0,
- c: 0,
- d: 1,
- e: 0,
- f: 0
+ function d3_arraySlice(pseudoarray) {
+ return Array.prototype.slice.call(pseudoarray);
+ }
+ try {
+ d3_array(d3_document.documentElement.childNodes)[0].nodeType;
+ } catch (e) {
+ d3_array = d3_arrayCopy;
+ }
+ var d3_arraySubclass = [].__proto__ ? function(array, prototype) {
+ array.__proto__ = prototype;
+ } : function(array, prototype) {
+ for (var property in prototype) array[property] = prototype[property];
};
- d3.interpolate = function(a, b) {
- var i = d3.interpolators.length, f;
- while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
- return f;
+ d3.touches = function(container, touches) {
+ if (arguments.length < 2) touches = d3_eventSource().touches;
+ return touches ? d3_array(touches).map(function(touch) {
+ var point = d3_mousePoint(container, touch);
+ point.identifier = touch.identifier;
+ return point;
+ }) : [];
};
- d3.interpolateNumber = function(a, b) {
- b -= a;
- return function(t) {
- return a + b * t;
+ d3.behavior.drag = function() {
+ var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null;
+ function drag() {
+ this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown);
+ }
+ function mousedown() {
+ var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0;
+ var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
+ if (origin) {
+ offset = origin.apply(target, arguments);
+ offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
+ } else {
+ offset = [ 0, 0 ];
+ }
+ if (touchId == null) d3_eventCancel();
+ event_({
+ type: "dragstart"
+ });
+ function point() {
+ var p = target.parentNode;
+ return touchId != null ? d3.touches(p).filter(function(p) {
+ return p.identifier === touchId;
+ })[0] : d3.mouse(p);
+ }
+ function dragmove() {
+ if (!target.parentNode) return dragend();
+ var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
+ moved |= dx | dy;
+ origin_ = p;
+ d3_eventCancel();
+ event_({
+ type: "drag",
+ x: p[0] + offset[0],
+ y: p[1] + offset[1],
+ dx: dx,
+ dy: dy
+ });
+ }
+ function dragend() {
+ event_({
+ type: "dragend"
+ });
+ if (moved) {
+ d3_eventCancel();
+ if (d3.event.target === eventTarget) d3_eventSuppress(w, "click");
+ }
+ w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
+ }
+ }
+ drag.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return drag;
};
+ return d3.rebind(drag, event, "on");
};
- d3.interpolateRound = function(a, b) {
- b -= a;
- return function(t) {
- return Math.round(a + b * t);
+ function d3_selection(groups) {
+ d3_arraySubclass(groups, d3_selectionPrototype);
+ return groups;
+ }
+ var d3_select = function(s, n) {
+ return n.querySelector(s);
+ }, d3_selectAll = function(s, n) {
+ return n.querySelectorAll(s);
+ }, d3_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) {
+ return d3_selectMatcher.call(n, s);
+ };
+ if (typeof Sizzle === "function") {
+ d3_select = function(s, n) {
+ return Sizzle(s, n)[0] || null;
+ };
+ d3_selectAll = function(s, n) {
+ return Sizzle.uniqueSort(Sizzle(s, n));
};
+ d3_selectMatches = Sizzle.matchesSelector;
+ }
+ d3.selection = function() {
+ return d3_selectionRoot;
};
- d3.interpolateString = function(a, b) {
- var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
- d3_interpolate_number.lastIndex = 0;
- for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
- if (m.index) s.push(b.substring(s0, s1 = m.index));
- q.push({
- i: s.length,
- x: m[0]
- });
- s.push(null);
- s0 = d3_interpolate_number.lastIndex;
- }
- if (s0 < b.length) s.push(b.substring(s0));
- for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
- o = q[i];
- if (o.x == m[0]) {
- if (o.i) {
- if (s[o.i + 1] == null) {
- s[o.i - 1] += o.x;
- s.splice(o.i, 1);
- for (j = i + 1; j < n; ++j) q[j].i--;
- } else {
- s[o.i - 1] += o.x + s[o.i + 1];
- s.splice(o.i, 2);
- for (j = i + 1; j < n; ++j) q[j].i -= 2;
- }
+ var d3_selectionPrototype = d3.selection.prototype = [];
+ d3_selectionPrototype.select = function(selector) {
+ var subgroups = [], subgroup, subnode, group, node;
+ if (typeof selector !== "function") selector = d3_selection_selector(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = (group = this[j]).parentNode;
+ for (var i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroup.push(subnode = selector.call(node, node.__data__, i));
+ if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
} else {
- if (s[o.i + 1] == null) {
- s[o.i] = o.x;
- } else {
- s[o.i] = o.x + s[o.i + 1];
- s.splice(o.i + 1, 1);
- for (j = i + 1; j < n; ++j) q[j].i--;
- }
+ subgroup.push(null);
}
- q.splice(i, 1);
- n--;
- i--;
- } else {
- o.x = d3.interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
}
}
- while (i < n) {
- o = q.pop();
- if (s[o.i + 1] == null) {
- s[o.i] = o.x;
- } else {
- s[o.i] = o.x + s[o.i + 1];
- s.splice(o.i + 1, 1);
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selector(selector) {
+ return function() {
+ return d3_select(selector, this);
+ };
+ }
+ d3_selectionPrototype.selectAll = function(selector) {
+ var subgroups = [], subgroup, node;
+ if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));
+ subgroup.parentNode = node;
+ }
}
- n--;
- }
- if (s.length === 1) {
- return s[0] == null ? q[0].x : function() {
- return b;
- };
}
- return function(t) {
- for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
- return s.join("");
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selectorAll(selector) {
+ return function() {
+ return d3_selectAll(selector, this);
};
+ }
+ var d3_nsPrefix = {
+ svg: "http://www.w3.org/2000/svg",
+ xhtml: "http://www.w3.org/1999/xhtml",
+ xlink: "http://www.w3.org/1999/xlink",
+ xml: "http://www.w3.org/XML/1998/namespace",
+ xmlns: "http://www.w3.org/2000/xmlns/"
};
- d3.interpolateTransform = function(a, b) {
- var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
- if (ta[0] != tb[0] || ta[1] != tb[1]) {
- s.push("translate(", null, ",", null, ")");
- q.push({
- i: 1,
- x: d3.interpolateNumber(ta[0], tb[0])
- }, {
- i: 3,
- x: d3.interpolateNumber(ta[1], tb[1])
- });
- } else if (tb[0] || tb[1]) {
- s.push("translate(" + tb + ")");
- } else {
- s.push("");
- }
- if (ra != rb) {
- if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
- q.push({
- i: s.push(s.pop() + "rotate(", null, ")") - 2,
- x: d3.interpolateNumber(ra, rb)
- });
- } else if (rb) {
- s.push(s.pop() + "rotate(" + rb + ")");
- }
- if (wa != wb) {
- q.push({
- i: s.push(s.pop() + "skewX(", null, ")") - 2,
- x: d3.interpolateNumber(wa, wb)
- });
- } else if (wb) {
- s.push(s.pop() + "skewX(" + wb + ")");
- }
- if (ka[0] != kb[0] || ka[1] != kb[1]) {
- n = s.push(s.pop() + "scale(", null, ",", null, ")");
- q.push({
- i: n - 4,
- x: d3.interpolateNumber(ka[0], kb[0])
- }, {
- i: n - 2,
- x: d3.interpolateNumber(ka[1], kb[1])
- });
- } else if (kb[0] != 1 || kb[1] != 1) {
- s.push(s.pop() + "scale(" + kb + ")");
- }
- n = q.length;
- return function(t) {
- var i = -1, o;
- while (++i < n) s[(o = q[i]).i] = o.x(t);
- return s.join("");
- };
- };
- d3.interpolateRgb = function(a, b) {
- a = d3.rgb(a);
- b = d3.rgb(b);
- var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
- return function(t) {
- return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
- };
- };
- d3.interpolateHsl = function(a, b) {
- a = d3.hsl(a);
- b = d3.hsl(b);
- var h0 = a.h, s0 = a.s, l0 = a.l, h1 = b.h - h0, s1 = b.s - s0, l1 = b.l - l0;
- if (h1 > 180) h1 -= 360; else if (h1 < -180) h1 += 360;
- return function(t) {
- return d3_hsl_rgb(h0 + h1 * t, s0 + s1 * t, l0 + l1 * t) + "";
- };
- };
- d3.interpolateLab = function(a, b) {
- a = d3.lab(a);
- b = d3.lab(b);
- var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
- return function(t) {
- return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
- };
- };
- d3.interpolateHcl = function(a, b) {
- a = d3.hcl(a);
- b = d3.hcl(b);
- var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
- if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
- return function(t) {
- return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
- };
- };
- d3.interpolateArray = function(a, b) {
- var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
- for (i = 0; i < n0; ++i) x.push(d3.interpolate(a[i], b[i]));
- for (;i < na; ++i) c[i] = a[i];
- for (;i < nb; ++i) c[i] = b[i];
- return function(t) {
- for (i = 0; i < n0; ++i) c[i] = x[i](t);
- return c;
- };
- };
- d3.interpolateObject = function(a, b) {
- var i = {}, c = {}, k;
- for (k in a) {
- if (k in b) {
- i[k] = d3_interpolateByName(k)(a[k], b[k]);
- } else {
- c[k] = a[k];
+ d3.ns = {
+ prefix: d3_nsPrefix,
+ qualify: function(name) {
+ var i = name.indexOf(":"), prefix = name;
+ if (i >= 0) {
+ prefix = name.substring(0, i);
+ name = name.substring(i + 1);
}
+ return d3_nsPrefix.hasOwnProperty(prefix) ? {
+ space: d3_nsPrefix[prefix],
+ local: name
+ } : name;
}
- for (k in b) {
- if (!(k in a)) {
- c[k] = b[k];
+ };
+ d3_selectionPrototype.attr = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") {
+ var node = this.node();
+ name = d3.ns.qualify(name);
+ return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
}
+ for (value in name) this.each(d3_selection_attr(value, name[value]));
+ return this;
}
- return function(t) {
- for (k in i) c[k] = i[k](t);
- return c;
- };
- };
- var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
- function d3_interpolateByName(name) {
- return name == "transform" ? d3.interpolateTransform : d3.interpolate;
- }
- d3.interpolators = [ d3.interpolateObject, function(a, b) {
- return b instanceof Array && d3.interpolateArray(a, b);
- }, function(a, b) {
- return (typeof a === "string" || typeof b === "string") && d3.interpolateString(a + "", b + "");
- }, function(a, b) {
- return (typeof b === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Color) && d3.interpolateRgb(a, b);
- }, function(a, b) {
- return !isNaN(a = +a) && !isNaN(b = +b) && d3.interpolateNumber(a, b);
- } ];
- function d3_uninterpolateNumber(a, b) {
- b = b - (a = +a) ? 1 / (b - a) : 0;
- return function(x) {
- return (x - a) * b;
- };
- }
- function d3_uninterpolateClamp(a, b) {
- b = b - (a = +a) ? 1 / (b - a) : 0;
- return function(x) {
- return Math.max(0, Math.min(1, (x - a) * b));
- };
- }
- function d3_Color() {}
- d3_Color.prototype.toString = function() {
- return this.rgb() + "";
- };
- d3.rgb = function(r, g, b) {
- return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+ return this.each(d3_selection_attr(name, value));
};
- function d3_rgb(r, g, b) {
- return new d3_Rgb(r, g, b);
+ function d3_selection_attr(name, value) {
+ name = d3.ns.qualify(name);
+ function attrNull() {
+ this.removeAttribute(name);
+ }
+ function attrNullNS() {
+ this.removeAttributeNS(name.space, name.local);
+ }
+ function attrConstant() {
+ this.setAttribute(name, value);
+ }
+ function attrConstantNS() {
+ this.setAttributeNS(name.space, name.local, value);
+ }
+ function attrFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
+ }
+ function attrFunctionNS() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
+ }
+ return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
}
- function d3_Rgb(r, g, b) {
- this.r = r;
- this.g = g;
- this.b = b;
+ function d3_collapse(s) {
+ return s.trim().replace(/\s+/g, " ");
}
- var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();
- d3_rgbPrototype.brighter = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- var r = this.r, g = this.g, b = this.b, i = 30;
- if (!r && !g && !b) return d3_rgb(i, i, i);
- if (r && r < i) r = i;
- if (g && g < i) g = i;
- if (b && b < i) b = i;
- return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));
- };
- d3_rgbPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b));
- };
- d3_rgbPrototype.hsl = function() {
- return d3_rgb_hsl(this.r, this.g, this.b);
- };
- d3_rgbPrototype.toString = function() {
- return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+ d3.requote = function(s) {
+ return s.replace(d3_requote_re, "\\$&");
};
- function d3_rgb_hex(v) {
- return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
- }
- function d3_rgb_parse(format, rgb, hsl) {
- var r = 0, g = 0, b = 0, m1, m2, name;
- m1 = /([a-z]+)\((.*)\)/i.exec(format);
- if (m1) {
- m2 = m1[2].split(",");
- switch (m1[1]) {
- case "hsl":
- {
- return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
- }
-
- case "rgb":
- {
- return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+ var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+ d3_selectionPrototype.classed = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") {
+ var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1;
+ if (value = node.classList) {
+ while (++i < n) if (!value.contains(name[i])) return false;
+ } else {
+ value = node.getAttribute("class");
+ while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
}
+ return true;
}
+ for (value in name) this.each(d3_selection_classed(value, name[value]));
+ return this;
}
- if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
- if (format != null && format.charAt(0) === "#") {
- if (format.length === 4) {
- r = format.charAt(1);
- r += r;
- g = format.charAt(2);
- g += g;
- b = format.charAt(3);
- b += b;
- } else if (format.length === 7) {
- r = format.substring(1, 3);
- g = format.substring(3, 5);
- b = format.substring(5, 7);
- }
- r = parseInt(r, 16);
- g = parseInt(g, 16);
- b = parseInt(b, 16);
- }
- return rgb(r, g, b);
+ return this.each(d3_selection_classed(name, value));
+ };
+ function d3_selection_classedRe(name) {
+ return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
}
- function d3_rgb_hsl(r, g, b) {
- var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
- if (d) {
- s = l < .5 ? d / (max + min) : d / (2 - max - min);
- if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
- h *= 60;
- } else {
- s = h = 0;
+ function d3_selection_classed(name, value) {
+ name = name.trim().split(/\s+/).map(d3_selection_classedName);
+ var n = name.length;
+ function classedConstant() {
+ var i = -1;
+ while (++i < n) name[i](this, value);
}
- return d3_hsl(h, s, l);
- }
- function d3_rgb_lab(r, g, b) {
- r = d3_rgb_xyz(r);
- g = d3_rgb_xyz(g);
- b = d3_rgb_xyz(b);
- var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
- return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+ function classedFunction() {
+ var i = -1, x = value.apply(this, arguments);
+ while (++i < n) name[i](this, x);
+ }
+ return typeof value === "function" ? classedFunction : classedConstant;
}
- function d3_rgb_xyz(r) {
- return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+ function d3_selection_classedName(name) {
+ var re = d3_selection_classedRe(name);
+ return function(node, value) {
+ if (c = node.classList) return value ? c.add(name) : c.remove(name);
+ var c = node.getAttribute("class") || "";
+ if (value) {
+ re.lastIndex = 0;
+ if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
+ } else {
+ node.setAttribute("class", d3_collapse(c.replace(re, " ")));
+ }
+ };
+ }
+ d3_selectionPrototype.style = function(name, value, priority) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof name !== "string") {
+ if (n < 2) value = "";
+ for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
+ return this;
+ }
+ if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
+ priority = "";
+ }
+ return this.each(d3_selection_style(name, value, priority));
+ };
+ function d3_selection_style(name, value, priority) {
+ function styleNull() {
+ this.style.removeProperty(name);
+ }
+ function styleConstant() {
+ this.style.setProperty(name, value, priority);
+ }
+ function styleFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
+ }
+ return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
+ }
+ d3_selectionPrototype.property = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") return this.node()[name];
+ for (value in name) this.each(d3_selection_property(value, name[value]));
+ return this;
+ }
+ return this.each(d3_selection_property(name, value));
+ };
+ function d3_selection_property(name, value) {
+ function propertyNull() {
+ delete this[name];
+ }
+ function propertyConstant() {
+ this[name] = value;
+ }
+ function propertyFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) delete this[name]; else this[name] = x;
+ }
+ return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
+ }
+ d3_selectionPrototype.text = function(value) {
+ return arguments.length ? this.each(typeof value === "function" ? function() {
+ var v = value.apply(this, arguments);
+ this.textContent = v == null ? "" : v;
+ } : value == null ? function() {
+ this.textContent = "";
+ } : function() {
+ this.textContent = value;
+ }) : this.node().textContent;
+ };
+ d3_selectionPrototype.html = function(value) {
+ return arguments.length ? this.each(typeof value === "function" ? function() {
+ var v = value.apply(this, arguments);
+ this.innerHTML = v == null ? "" : v;
+ } : value == null ? function() {
+ this.innerHTML = "";
+ } : function() {
+ this.innerHTML = value;
+ }) : this.node().innerHTML;
+ };
+ d3_selectionPrototype.append = function(name) {
+ name = d3.ns.qualify(name);
+ function append() {
+ return this.appendChild(d3_document.createElementNS(this.namespaceURI, name));
+ }
+ function appendNS() {
+ return this.appendChild(d3_document.createElementNS(name.space, name.local));
+ }
+ return this.select(name.local ? appendNS : append);
+ };
+ d3_selectionPrototype.insert = function(name, before) {
+ name = d3.ns.qualify(name);
+ if (typeof before !== "function") before = d3_selection_selector(before);
+ function insert(d, i) {
+ return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), before.call(this, d, i));
+ }
+ function insertNS(d, i) {
+ return this.insertBefore(d3_document.createElementNS(name.space, name.local), before.call(this, d, i));
+ }
+ return this.select(name.local ? insertNS : insert);
+ };
+ d3_selectionPrototype.remove = function() {
+ return this.each(function() {
+ var parent = this.parentNode;
+ if (parent) parent.removeChild(this);
+ });
+ };
+ d3_selectionPrototype.data = function(value, key) {
+ var i = -1, n = this.length, group, node;
+ if (!arguments.length) {
+ value = new Array(n = (group = this[0]).length);
+ while (++i < n) {
+ if (node = group[i]) {
+ value[i] = node.__data__;
+ }
+ }
+ return value;
+ }
+ function bind(group, groupData) {
+ var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
+ if (key) {
+ var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
+ for (i = -1; ++i < n; ) {
+ keyValue = key.call(node = group[i], node.__data__, i);
+ if (nodeByKeyValue.has(keyValue)) {
+ exitNodes[i] = node;
+ } else {
+ nodeByKeyValue.set(keyValue, node);
+ }
+ keyValues.push(keyValue);
+ }
+ for (i = -1; ++i < m; ) {
+ keyValue = key.call(groupData, nodeData = groupData[i], i);
+ if (node = nodeByKeyValue.get(keyValue)) {
+ updateNodes[i] = node;
+ node.__data__ = nodeData;
+ } else if (!dataByKeyValue.has(keyValue)) {
+ enterNodes[i] = d3_selection_dataNode(nodeData);
+ }
+ dataByKeyValue.set(keyValue, nodeData);
+ nodeByKeyValue.remove(keyValue);
+ }
+ for (i = -1; ++i < n; ) {
+ if (nodeByKeyValue.has(keyValues[i])) {
+ exitNodes[i] = group[i];
+ }
+ }
+ } else {
+ for (i = -1; ++i < n0; ) {
+ node = group[i];
+ nodeData = groupData[i];
+ if (node) {
+ node.__data__ = nodeData;
+ updateNodes[i] = node;
+ } else {
+ enterNodes[i] = d3_selection_dataNode(nodeData);
+ }
+ }
+ for (;i < m; ++i) {
+ enterNodes[i] = d3_selection_dataNode(groupData[i]);
+ }
+ for (;i < n; ++i) {
+ exitNodes[i] = group[i];
+ }
+ }
+ enterNodes.update = updateNodes;
+ enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
+ enter.push(enterNodes);
+ update.push(updateNodes);
+ exit.push(exitNodes);
+ }
+ var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
+ if (typeof value === "function") {
+ while (++i < n) {
+ bind(group = this[i], value.call(group, group.parentNode.__data__, i));
+ }
+ } else {
+ while (++i < n) {
+ bind(group = this[i], value);
+ }
+ }
+ update.enter = function() {
+ return enter;
+ };
+ update.exit = function() {
+ return exit;
+ };
+ return update;
+ };
+ function d3_selection_dataNode(data) {
+ return {
+ __data__: data
+ };
+ }
+ d3_selectionPrototype.datum = function(value) {
+ return arguments.length ? this.property("__data__", value) : this.property("__data__");
+ };
+ d3_selectionPrototype.filter = function(filter) {
+ var subgroups = [], subgroup, group, node;
+ if (typeof filter !== "function") filter = d3_selection_filter(filter);
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = (group = this[j]).parentNode;
+ for (var i = 0, n = group.length; i < n; i++) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i)) {
+ subgroup.push(node);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ function d3_selection_filter(selector) {
+ return function() {
+ return d3_selectMatches(this, selector);
+ };
+ }
+ d3_selectionPrototype.order = function() {
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
+ if (node = group[i]) {
+ if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
+ next = node;
+ }
+ }
+ }
+ return this;
+ };
+ d3_selectionPrototype.sort = function(comparator) {
+ comparator = d3_selection_sortComparator.apply(this, arguments);
+ for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
+ return this.order();
+ };
+ function d3_selection_sortComparator(comparator) {
+ if (!arguments.length) comparator = d3.ascending;
+ return function(a, b) {
+ return !a - !b || comparator(a.__data__, b.__data__);
+ };
+ }
+ function d3_noop() {}
+ d3_selectionPrototype.on = function(type, listener, capture) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof type !== "string") {
+ if (n < 2) listener = false;
+ for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
+ return this;
+ }
+ if (n < 2) return (n = this.node()["__on" + type]) && n._;
+ capture = false;
+ }
+ return this.each(d3_selection_on(type, listener, capture));
+ };
+ function d3_selection_on(type, listener, capture) {
+ var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
+ if (i > 0) type = type.substring(0, i);
+ var filter = d3_selection_onFilters.get(type);
+ if (filter) type = filter, wrap = d3_selection_onFilter;
+ function onRemove() {
+ var l = this[name];
+ if (l) {
+ this.removeEventListener(type, l, l.$);
+ delete this[name];
+ }
+ }
+ function onAdd() {
+ var l = wrap(listener, d3_array(arguments));
+ onRemove.call(this);
+ this.addEventListener(type, this[name] = l, l.$ = capture);
+ l._ = listener;
+ }
+ function removeAll() {
+ var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
+ for (var name in this) {
+ if (match = name.match(re)) {
+ var l = this[name];
+ this.removeEventListener(match[1], l, l.$);
+ delete this[name];
+ }
+ }
+ }
+ return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
+ }
+ var d3_selection_onFilters = d3.map({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+ });
+ d3_selection_onFilters.forEach(function(k) {
+ if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
+ });
+ function d3_selection_onListener(listener, argumentz) {
+ return function(e) {
+ var o = d3.event;
+ d3.event = e;
+ argumentz[0] = this.__data__;
+ try {
+ listener.apply(this, argumentz);
+ } finally {
+ d3.event = o;
+ }
+ };
+ }
+ function d3_selection_onFilter(listener, argumentz) {
+ var l = d3_selection_onListener(listener, argumentz);
+ return function(e) {
+ var target = this, related = e.relatedTarget;
+ if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
+ l.call(target, e);
+ }
+ };
+ }
+ d3_selectionPrototype.each = function(callback) {
+ return d3_selection_each(this, function(node, i, j) {
+ callback.call(node, node.__data__, i, j);
+ });
+ };
+ function d3_selection_each(groups, callback) {
+ for (var j = 0, m = groups.length; j < m; j++) {
+ for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
+ if (node = group[i]) callback(node, i, j);
+ }
+ }
+ return groups;
+ }
+ d3_selectionPrototype.call = function(callback) {
+ var args = d3_array(arguments);
+ callback.apply(args[0] = this, args);
+ return this;
+ };
+ d3_selectionPrototype.empty = function() {
+ return !this.node();
+ };
+ d3_selectionPrototype.node = function() {
+ for (var j = 0, m = this.length; j < m; j++) {
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ var node = group[i];
+ if (node) return node;
+ }
+ }
+ return null;
+ };
+ function d3_selection_enter(selection) {
+ d3_arraySubclass(selection, d3_selection_enterPrototype);
+ return selection;
+ }
+ var d3_selection_enterPrototype = [];
+ d3.selection.enter = d3_selection_enter;
+ d3.selection.enter.prototype = d3_selection_enterPrototype;
+ d3_selection_enterPrototype.append = d3_selectionPrototype.append;
+ d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;
+ d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+ d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+ d3_selection_enterPrototype.select = function(selector) {
+ var subgroups = [], subgroup, subnode, upgroup, group, node;
+ for (var j = -1, m = this.length; ++j < m; ) {
+ upgroup = (group = this[j]).update;
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = group.parentNode;
+ for (var i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));
+ subnode.__data__ = node.__data__;
+ } else {
+ subgroup.push(null);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ d3_selectionPrototype.transition = function() {
+ var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit);
+ transition.time = Date.now();
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) d3_transitionNode(node, i, id, transition);
+ subgroup.push(node);
+ }
+ }
+ return d3_transition(subgroups, id);
+ };
+ d3.select = function(node) {
+ var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ];
+ group.parentNode = d3_selectRoot;
+ return d3_selection([ group ]);
+ };
+ d3.selectAll = function(nodes) {
+ var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
+ group.parentNode = d3_selectRoot;
+ return d3_selection([ group ]);
+ };
+ var d3_selectionRoot = d3.select(d3_selectRoot);
+ d3.behavior.zoom = function() {
+ var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime;
+ function zoom() {
+ this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart);
+ }
+ zoom.translate = function(x) {
+ if (!arguments.length) return translate;
+ translate = x.map(Number);
+ rescale();
+ return zoom;
+ };
+ zoom.scale = function(x) {
+ if (!arguments.length) return scale;
+ scale = +x;
+ rescale();
+ return zoom;
+ };
+ zoom.scaleExtent = function(x) {
+ if (!arguments.length) return scaleExtent;
+ scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
+ return zoom;
+ };
+ zoom.x = function(z) {
+ if (!arguments.length) return x1;
+ x1 = z;
+ x0 = z.copy();
+ translate = [ 0, 0 ];
+ scale = 1;
+ return zoom;
+ };
+ zoom.y = function(z) {
+ if (!arguments.length) return y1;
+ y1 = z;
+ y0 = z.copy();
+ translate = [ 0, 0 ];
+ scale = 1;
+ return zoom;
+ };
+ function location(p) {
+ return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];
+ }
+ function point(l) {
+ return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];
+ }
+ function scaleTo(s) {
+ scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+ }
+ function translateTo(p, l) {
+ l = point(l);
+ translate[0] += p[0] - l[0];
+ translate[1] += p[1] - l[1];
+ }
+ function rescale() {
+ if (x1) x1.domain(x0.range().map(function(x) {
+ return (x - translate[0]) / scale;
+ }).map(x0.invert));
+ if (y1) y1.domain(y0.range().map(function(y) {
+ return (y - translate[1]) / scale;
+ }).map(y0.invert));
+ }
+ function dispatch(event) {
+ rescale();
+ d3.event.preventDefault();
+ event({
+ type: "zoom",
+ scale: scale,
+ translate: translate
+ });
+ }
+ function mousedown() {
+ var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target));
+ d3_window.focus();
+ d3_eventCancel();
+ function mousemove() {
+ moved = 1;
+ translateTo(d3.mouse(target), l);
+ dispatch(event_);
+ }
+ function mouseup() {
+ if (moved) d3_eventCancel();
+ w.on("mousemove.zoom", null).on("mouseup.zoom", null);
+ if (moved && d3.event.target === eventTarget) d3_eventSuppress(w, "click.zoom");
+ }
+ }
+ function mousewheel() {
+ if (!translate0) translate0 = location(d3.mouse(this));
+ scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
+ translateTo(d3.mouse(this), translate0);
+ dispatch(event.of(this, arguments));
+ }
+ function mousemove() {
+ translate0 = null;
+ }
+ function dblclick() {
+ var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;
+ scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
+ translateTo(p, l);
+ dispatch(event.of(this, arguments));
+ }
+ function touchstart() {
+ var touches = d3.touches(this), now = Date.now();
+ scale0 = scale;
+ translate0 = {};
+ touches.forEach(function(t) {
+ translate0[t.identifier] = location(t);
+ });
+ d3_eventCancel();
+ if (touches.length === 1) {
+ if (now - touchtime < 500) {
+ var p = touches[0], l = location(touches[0]);
+ scaleTo(scale * 2);
+ translateTo(p, l);
+ dispatch(event.of(this, arguments));
+ }
+ touchtime = now;
+ }
+ }
+ function touchmove() {
+ var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];
+ if (p1 = touches[1]) {
+ var p1, l1 = translate0[p1.identifier];
+ p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+ l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+ scaleTo(d3.event.scale * scale0);
+ }
+ translateTo(p0, l0);
+ touchtime = null;
+ dispatch(event.of(this, arguments));
+ }
+ return d3.rebind(zoom, event, "on");
+ };
+ var d3_behavior_zoomInfinity = [ 0, Infinity ];
+ var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+ return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
+ }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+ return d3.event.wheelDelta;
+ }, "mousewheel") : (d3_behavior_zoomDelta = function() {
+ return -d3.event.detail;
+ }, "MozMousePixelScroll");
+ function d3_Color() {}
+ d3_Color.prototype.toString = function() {
+ return this.rgb() + "";
+ };
+ d3.hsl = function(h, s, l) {
+ return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
+ };
+ function d3_hsl(h, s, l) {
+ return new d3_Hsl(h, s, l);
+ }
+ function d3_Hsl(h, s, l) {
+ this.h = h;
+ this.s = s;
+ this.l = l;
+ }
+ var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
+ d3_hslPrototype.brighter = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return d3_hsl(this.h, this.s, this.l / k);
+ };
+ d3_hslPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return d3_hsl(this.h, this.s, k * this.l);
+ };
+ d3_hslPrototype.rgb = function() {
+ return d3_hsl_rgb(this.h, this.s, this.l);
+ };
+ function d3_hsl_rgb(h, s, l) {
+ var m1, m2;
+ h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
+ s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
+ l = l < 0 ? 0 : l > 1 ? 1 : l;
+ m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
+ m1 = 2 * l - m2;
+ function v(h) {
+ if (h > 360) h -= 360; else if (h < 0) h += 360;
+ if (h < 60) return m1 + (m2 - m1) * h / 60;
+ if (h < 180) return m2;
+ if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
+ return m1;
+ }
+ function vv(h) {
+ return Math.round(v(h) * 255);
+ }
+ return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+ }
+ var π = Math.PI, ε = 1e-6, d3_radians = π / 180, d3_degrees = 180 / π;
+ function d3_sgn(x) {
+ return x > 0 ? 1 : x < 0 ? -1 : 0;
+ }
+ function d3_acos(x) {
+ return Math.acos(Math.max(-1, Math.min(1, x)));
+ }
+ function d3_asin(x) {
+ return x > 1 ? π / 2 : x < -1 ? -π / 2 : Math.asin(x);
+ }
+ function d3_sinh(x) {
+ return (Math.exp(x) - Math.exp(-x)) / 2;
+ }
+ function d3_cosh(x) {
+ return (Math.exp(x) + Math.exp(-x)) / 2;
+ }
+ function d3_haversin(x) {
+ return (x = Math.sin(x / 2)) * x;
+ }
+ d3.hcl = function(h, c, l) {
+ return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);
+ };
+ function d3_hcl(h, c, l) {
+ return new d3_Hcl(h, c, l);
+ }
+ function d3_Hcl(h, c, l) {
+ this.h = h;
+ this.c = c;
+ this.l = l;
+ }
+ var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
+ d3_hclPrototype.brighter = function(k) {
+ return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+ };
+ d3_hclPrototype.darker = function(k) {
+ return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+ };
+ d3_hclPrototype.rgb = function() {
+ return d3_hcl_lab(this.h, this.c, this.l).rgb();
+ };
+ function d3_hcl_lab(h, c, l) {
+ if (isNaN(h)) h = 0;
+ if (isNaN(c)) c = 0;
+ return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+ }
+ d3.lab = function(l, a, b) {
+ return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
+ };
+ function d3_lab(l, a, b) {
+ return new d3_Lab(l, a, b);
+ }
+ function d3_Lab(l, a, b) {
+ this.l = l;
+ this.a = a;
+ this.b = b;
+ }
+ var d3_lab_K = 18;
+ var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
+ var d3_labPrototype = d3_Lab.prototype = new d3_Color();
+ d3_labPrototype.brighter = function(k) {
+ return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+ };
+ d3_labPrototype.darker = function(k) {
+ return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+ };
+ d3_labPrototype.rgb = function() {
+ return d3_lab_rgb(this.l, this.a, this.b);
+ };
+ function d3_lab_rgb(l, a, b) {
+ var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
+ x = d3_lab_xyz(x) * d3_lab_X;
+ y = d3_lab_xyz(y) * d3_lab_Y;
+ z = d3_lab_xyz(z) * d3_lab_Z;
+ return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+ }
+ function d3_lab_hcl(l, a, b) {
+ return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l);
+ }
+ function d3_lab_xyz(x) {
+ return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
+ }
+ function d3_xyz_lab(x) {
+ return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
+ }
+ function d3_xyz_rgb(r) {
+ return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
+ }
+ d3.rgb = function(r, g, b) {
+ return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+ };
+ function d3_rgb(r, g, b) {
+ return new d3_Rgb(r, g, b);
+ }
+ function d3_Rgb(r, g, b) {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ }
+ var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();
+ d3_rgbPrototype.brighter = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ var r = this.r, g = this.g, b = this.b, i = 30;
+ if (!r && !g && !b) return d3_rgb(i, i, i);
+ if (r && r < i) r = i;
+ if (g && g < i) g = i;
+ if (b && b < i) b = i;
+ return d3_rgb(Math.min(255, Math.floor(r / k)), Math.min(255, Math.floor(g / k)), Math.min(255, Math.floor(b / k)));
+ };
+ d3_rgbPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return d3_rgb(Math.floor(k * this.r), Math.floor(k * this.g), Math.floor(k * this.b));
+ };
+ d3_rgbPrototype.hsl = function() {
+ return d3_rgb_hsl(this.r, this.g, this.b);
+ };
+ d3_rgbPrototype.toString = function() {
+ return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+ };
+ function d3_rgb_hex(v) {
+ return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
+ }
+ function d3_rgb_parse(format, rgb, hsl) {
+ var r = 0, g = 0, b = 0, m1, m2, name;
+ m1 = /([a-z]+)\((.*)\)/i.exec(format);
+ if (m1) {
+ m2 = m1[2].split(",");
+ switch (m1[1]) {
+ case "hsl":
+ {
+ return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
+ }
+
+ case "rgb":
+ {
+ return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+ }
+ }
+ }
+ if (name = d3_rgb_names.get(format)) return rgb(name.r, name.g, name.b);
+ if (format != null && format.charAt(0) === "#") {
+ if (format.length === 4) {
+ r = format.charAt(1);
+ r += r;
+ g = format.charAt(2);
+ g += g;
+ b = format.charAt(3);
+ b += b;
+ } else if (format.length === 7) {
+ r = format.substring(1, 3);
+ g = format.substring(3, 5);
+ b = format.substring(5, 7);
+ }
+ r = parseInt(r, 16);
+ g = parseInt(g, 16);
+ b = parseInt(b, 16);
+ }
+ return rgb(r, g, b);
+ }
+ function d3_rgb_hsl(r, g, b) {
+ var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
+ if (d) {
+ s = l < .5 ? d / (max + min) : d / (2 - max - min);
+ if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
+ h *= 60;
+ } else {
+ h = NaN;
+ s = l > 0 && l < 1 ? 0 : h;
+ }
+ return d3_hsl(h, s, l);
+ }
+ function d3_rgb_lab(r, g, b) {
+ r = d3_rgb_xyz(r);
+ g = d3_rgb_xyz(g);
+ b = d3_rgb_xyz(b);
+ var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
+ return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+ }
+ function d3_rgb_xyz(r) {
+ return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
}
function d3_rgb_parseNumber(c) {
var f = parseFloat(c);
@@ -1319,2595 +1619,3537 @@ d3 = function() {
d3_rgb_names.forEach(function(key, value) {
d3_rgb_names.set(key, d3_rgb_parse(value, d3_rgb, d3_hsl_rgb));
});
- d3.hsl = function(h, s, l) {
- return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
- };
- function d3_hsl(h, s, l) {
- return new d3_Hsl(h, s, l);
- }
- function d3_Hsl(h, s, l) {
- this.h = h;
- this.s = s;
- this.l = l;
- }
- var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
- d3_hslPrototype.brighter = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return d3_hsl(this.h, this.s, this.l / k);
- };
- d3_hslPrototype.darker = function(k) {
- k = Math.pow(.7, arguments.length ? k : 1);
- return d3_hsl(this.h, this.s, k * this.l);
- };
- d3_hslPrototype.rgb = function() {
- return d3_hsl_rgb(this.h, this.s, this.l);
- };
- function d3_hsl_rgb(h, s, l) {
- var m1, m2;
- h = h % 360;
- if (h < 0) h += 360;
- s = s < 0 ? 0 : s > 1 ? 1 : s;
- l = l < 0 ? 0 : l > 1 ? 1 : l;
- m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
- m1 = 2 * l - m2;
- function v(h) {
- if (h > 360) h -= 360; else if (h < 0) h += 360;
- if (h < 60) return m1 + (m2 - m1) * h / 60;
- if (h < 180) return m2;
- if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
- return m1;
- }
- function vv(h) {
- return Math.round(v(h) * 255);
- }
- return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
- }
- d3.hcl = function(h, c, l) {
- return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);
- };
- function d3_hcl(h, c, l) {
- return new d3_Hcl(h, c, l);
- }
- function d3_Hcl(h, c, l) {
- this.h = h;
- this.c = c;
- this.l = l;
- }
- var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
- d3_hclPrototype.brighter = function(k) {
- return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
- };
- d3_hclPrototype.darker = function(k) {
- return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
- };
- d3_hclPrototype.rgb = function() {
- return d3_hcl_lab(this.h, this.c, this.l).rgb();
- };
- function d3_hcl_lab(h, c, l) {
- return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
- }
- d3.lab = function(l, a, b) {
- return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
- };
- function d3_lab(l, a, b) {
- return new d3_Lab(l, a, b);
- }
- function d3_Lab(l, a, b) {
- this.l = l;
- this.a = a;
- this.b = b;
- }
- var d3_lab_K = 18;
- var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
- var d3_labPrototype = d3_Lab.prototype = new d3_Color();
- d3_labPrototype.brighter = function(k) {
- return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
- };
- d3_labPrototype.darker = function(k) {
- return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
- };
- d3_labPrototype.rgb = function() {
- return d3_lab_rgb(this.l, this.a, this.b);
- };
- function d3_lab_rgb(l, a, b) {
- var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
- x = d3_lab_xyz(x) * d3_lab_X;
- y = d3_lab_xyz(y) * d3_lab_Y;
- z = d3_lab_xyz(z) * d3_lab_Z;
- return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
- }
- function d3_lab_hcl(l, a, b) {
- return d3_hcl(Math.atan2(b, a) / π * 180, Math.sqrt(a * a + b * b), l);
- }
- function d3_lab_xyz(x) {
- return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
- }
- function d3_xyz_lab(x) {
- return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
- }
- function d3_xyz_rgb(r) {
- return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
- }
- function d3_selection(groups) {
- d3_arraySubclass(groups, d3_selectionPrototype);
- return groups;
- }
- var d3_select = function(s, n) {
- return n.querySelector(s);
- }, d3_selectAll = function(s, n) {
- return n.querySelectorAll(s);
- }, d3_selectRoot = d3_document.documentElement, d3_selectMatcher = d3_selectRoot.matchesSelector || d3_selectRoot.webkitMatchesSelector || d3_selectRoot.mozMatchesSelector || d3_selectRoot.msMatchesSelector || d3_selectRoot.oMatchesSelector, d3_selectMatches = function(n, s) {
- return d3_selectMatcher.call(n, s);
- };
- if (typeof Sizzle === "function") {
- d3_select = function(s, n) {
- return Sizzle(s, n)[0] || null;
- };
- d3_selectAll = function(s, n) {
- return Sizzle.uniqueSort(Sizzle(s, n));
- };
- d3_selectMatches = Sizzle.matchesSelector;
- }
- var d3_selectionPrototype = [];
- d3.selection = function() {
- return d3_selectionRoot;
- };
- d3.selection.prototype = d3_selectionPrototype;
- d3_selectionPrototype.select = function(selector) {
- var subgroups = [], subgroup, subnode, group, node;
- if (typeof selector !== "function") selector = d3_selection_selector(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- subgroups.push(subgroup = []);
- subgroup.parentNode = (group = this[j]).parentNode;
- for (var i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroup.push(subnode = selector.call(node, node.__data__, i));
- if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selector(selector) {
- return function() {
- return d3_select(selector, this);
- };
- }
- d3_selectionPrototype.selectAll = function(selector) {
- var subgroups = [], subgroup, node;
- if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));
- subgroup.parentNode = node;
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_selection_selectorAll(selector) {
- return function() {
- return d3_selectAll(selector, this);
- };
- }
- d3_selectionPrototype.attr = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") {
- var node = this.node();
- name = d3.ns.qualify(name);
- return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
- }
- for (value in name) this.each(d3_selection_attr(value, name[value]));
- return this;
- }
- return this.each(d3_selection_attr(name, value));
- };
- function d3_selection_attr(name, value) {
- name = d3.ns.qualify(name);
- function attrNull() {
- this.removeAttribute(name);
- }
- function attrNullNS() {
- this.removeAttributeNS(name.space, name.local);
- }
- function attrConstant() {
- this.setAttribute(name, value);
- }
- function attrConstantNS() {
- this.setAttributeNS(name.space, name.local, value);
- }
- function attrFunction() {
- var x = value.apply(this, arguments);
- if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
- }
- function attrFunctionNS() {
- var x = value.apply(this, arguments);
- if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
- }
- return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
- }
- d3_selectionPrototype.classed = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") {
- var node = this.node(), n = (name = name.trim().split(/^|\s+/g)).length, i = -1;
- if (value = node.classList) {
- while (++i < n) if (!value.contains(name[i])) return false;
- } else {
- value = node.className;
- if (value.baseVal != null) value = value.baseVal;
- while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
- }
- return true;
- }
- for (value in name) this.each(d3_selection_classed(value, name[value]));
- return this;
- }
- return this.each(d3_selection_classed(name, value));
- };
- function d3_selection_classedRe(name) {
- return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
+ function d3_functor(v) {
+ return typeof v === "function" ? v : function() {
+ return v;
+ };
}
- function d3_selection_classed(name, value) {
- name = name.trim().split(/\s+/).map(d3_selection_classedName);
- var n = name.length;
- function classedConstant() {
- var i = -1;
- while (++i < n) name[i](this, value);
- }
- function classedFunction() {
- var i = -1, x = value.apply(this, arguments);
- while (++i < n) name[i](this, x);
- }
- return typeof value === "function" ? classedFunction : classedConstant;
+ d3.functor = d3_functor;
+ function d3_identity(d) {
+ return d;
}
- function d3_selection_classedName(name) {
- var re = d3_selection_classedRe(name);
- return function(node, value) {
- if (c = node.classList) return value ? c.add(name) : c.remove(name);
- var c = node.className, cb = c.baseVal != null, cv = cb ? c.baseVal : c;
- if (value) {
- re.lastIndex = 0;
- if (!re.test(cv)) {
- cv = d3_collapse(cv + " " + name);
- if (cb) c.baseVal = cv; else node.className = cv;
- }
- } else if (cv) {
- cv = d3_collapse(cv.replace(re, " "));
- if (cb) c.baseVal = cv; else node.className = cv;
- }
+ d3.xhr = d3_xhrType(d3_identity);
+ function d3_xhrType(response) {
+ return function(url, mimeType, callback) {
+ if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
+ mimeType = null;
+ return d3_xhr(url, mimeType, response, callback);
};
}
- d3_selectionPrototype.style = function(name, value, priority) {
- var n = arguments.length;
- if (n < 3) {
- if (typeof name !== "string") {
- if (n < 2) value = "";
- for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
- return this;
+ function d3_xhr(url, mimeType, response, callback) {
+ var xhr = {}, dispatch = d3.dispatch("progress", "load", "error"), headers = {}, request = new (d3_window.XDomainRequest && /^(http(s)?:)?\/\//.test(url) ? XDomainRequest : XMLHttpRequest)();
+ "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+ request.readyState > 3 && respond();
+ };
+ function respond() {
+ var status = request.status, result;
+ if (!status && request.responseText || status >= 200 && status < 300 || status === 304) {
+ try {
+ result = response.call(xhr, request);
+ } catch (e) {
+ dispatch.error.call(xhr, e);
+ return;
+ }
+ dispatch.load.call(xhr, result);
+ } else {
+ dispatch.error.call(xhr, request);
}
- if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
- priority = "";
- }
- return this.each(d3_selection_style(name, value, priority));
- };
- function d3_selection_style(name, value, priority) {
- function styleNull() {
- this.style.removeProperty(name);
- }
- function styleConstant() {
- this.style.setProperty(name, value, priority);
- }
- function styleFunction() {
- var x = value.apply(this, arguments);
- if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
}
- return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
+ request.onprogress = function(event) {
+ var o = d3.event;
+ d3.event = event;
+ try {
+ dispatch.progress.call(xhr, request);
+ } finally {
+ d3.event = o;
+ }
+ };
+ xhr.header = function(name, value) {
+ name = (name + "").toLowerCase();
+ if (arguments.length < 2) return headers[name];
+ if (value == null) delete headers[name]; else headers[name] = value + "";
+ return xhr;
+ };
+ xhr.mimeType = function(value) {
+ if (!arguments.length) return mimeType;
+ mimeType = value == null ? null : value + "";
+ return xhr;
+ };
+ xhr.response = function(value) {
+ response = value;
+ return xhr;
+ };
+ [ "get", "post" ].forEach(function(method) {
+ xhr[method] = function() {
+ return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
+ };
+ });
+ xhr.send = function(method, data, callback) {
+ if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
+ request.open(method, url, true);
+ if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
+ if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
+ if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
+ if (callback != null) xhr.on("error", callback).on("load", function(request) {
+ callback(null, request);
+ });
+ request.send(data == null ? null : data);
+ return xhr;
+ };
+ xhr.abort = function() {
+ request.abort();
+ return xhr;
+ };
+ d3.rebind(xhr, dispatch, "on");
+ return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
}
- d3_selectionPrototype.property = function(name, value) {
- if (arguments.length < 2) {
- if (typeof name === "string") return this.node()[name];
- for (value in name) this.each(d3_selection_property(value, name[value]));
- return this;
- }
- return this.each(d3_selection_property(name, value));
- };
- function d3_selection_property(name, value) {
- function propertyNull() {
- delete this[name];
- }
- function propertyConstant() {
- this[name] = value;
- }
- function propertyFunction() {
- var x = value.apply(this, arguments);
- if (x == null) delete this[name]; else this[name] = x;
- }
- return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
+ function d3_xhr_fixCallback(callback) {
+ return callback.length === 1 ? function(error, request) {
+ callback(error == null ? request : null);
+ } : callback;
}
- d3_selectionPrototype.text = function(value) {
- return arguments.length ? this.each(typeof value === "function" ? function() {
- var v = value.apply(this, arguments);
- this.textContent = v == null ? "" : v;
- } : value == null ? function() {
- this.textContent = "";
- } : function() {
- this.textContent = value;
- }) : this.node().textContent;
- };
- d3_selectionPrototype.html = function(value) {
- return arguments.length ? this.each(typeof value === "function" ? function() {
- var v = value.apply(this, arguments);
- this.innerHTML = v == null ? "" : v;
- } : value == null ? function() {
- this.innerHTML = "";
- } : function() {
- this.innerHTML = value;
- }) : this.node().innerHTML;
- };
- d3_selectionPrototype.append = function(name) {
- name = d3.ns.qualify(name);
- function append() {
- return this.appendChild(d3_document.createElementNS(this.namespaceURI, name));
- }
- function appendNS() {
- return this.appendChild(d3_document.createElementNS(name.space, name.local));
- }
- return this.select(name.local ? appendNS : append);
- };
- d3_selectionPrototype.insert = function(name, before) {
- name = d3.ns.qualify(name);
- function insert() {
- return this.insertBefore(d3_document.createElementNS(this.namespaceURI, name), d3_select(before, this));
+ function d3_dsv(delimiter, mimeType) {
+ var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
+ function dsv(url, row, callback) {
+ if (arguments.length < 3) callback = row, row = null;
+ var xhr = d3.xhr(url, mimeType, callback);
+ xhr.row = function(_) {
+ return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+ };
+ return xhr.row(row);
}
- function insertNS() {
- return this.insertBefore(d3_document.createElementNS(name.space, name.local), d3_select(before, this));
+ function response(request) {
+ return dsv.parse(request.responseText);
}
- return this.select(name.local ? insertNS : insert);
- };
- d3_selectionPrototype.remove = function() {
- return this.each(function() {
- var parent = this.parentNode;
- if (parent) parent.removeChild(this);
- });
- };
- d3_selectionPrototype.data = function(value, key) {
- var i = -1, n = this.length, group, node;
- if (!arguments.length) {
- value = new Array(n = (group = this[0]).length);
- while (++i < n) {
- if (node = group[i]) {
- value[i] = node.__data__;
- }
- }
- return value;
+ function typedResponse(f) {
+ return function(request) {
+ return dsv.parse(request.responseText, f);
+ };
}
- function bind(group, groupData) {
- var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
- if (key) {
- var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
- for (i = -1; ++i < n; ) {
- keyValue = key.call(node = group[i], node.__data__, i);
- if (nodeByKeyValue.has(keyValue)) {
- exitNodes[i] = node;
- } else {
- nodeByKeyValue.set(keyValue, node);
- }
- keyValues.push(keyValue);
- }
- for (i = -1; ++i < m; ) {
- keyValue = key.call(groupData, nodeData = groupData[i], i);
- if (node = nodeByKeyValue.get(keyValue)) {
- updateNodes[i] = node;
- node.__data__ = nodeData;
- } else if (!dataByKeyValue.has(keyValue)) {
- enterNodes[i] = d3_selection_dataNode(nodeData);
- }
- dataByKeyValue.set(keyValue, nodeData);
- nodeByKeyValue.remove(keyValue);
- }
- for (i = -1; ++i < n; ) {
- if (nodeByKeyValue.has(keyValues[i])) {
- exitNodes[i] = group[i];
+ dsv.parse = function(text, f) {
+ var o;
+ return dsv.parseRows(text, function(row, i) {
+ if (o) return o(row, i - 1);
+ var a = new Function("d", "return {" + row.map(function(name, i) {
+ return JSON.stringify(name) + ": d[" + i + "]";
+ }).join(",") + "}");
+ o = f ? function(row, i) {
+ return f(a(row), i);
+ } : a;
+ });
+ };
+ dsv.parseRows = function(text, f) {
+ var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
+ function token() {
+ if (I >= N) return EOF;
+ if (eol) return eol = false, EOL;
+ var j = I;
+ if (text.charCodeAt(j) === 34) {
+ var i = j;
+ while (i++ < N) {
+ if (text.charCodeAt(i) === 34) {
+ if (text.charCodeAt(i + 1) !== 34) break;
+ ++i;
+ }
}
- }
- } else {
- for (i = -1; ++i < n0; ) {
- node = group[i];
- nodeData = groupData[i];
- if (node) {
- node.__data__ = nodeData;
- updateNodes[i] = node;
- } else {
- enterNodes[i] = d3_selection_dataNode(nodeData);
+ I = i + 2;
+ var c = text.charCodeAt(i + 1);
+ if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(i + 2) === 10) ++I;
+ } else if (c === 10) {
+ eol = true;
}
+ return text.substring(j + 1, i).replace(/""/g, '"');
}
- for (;i < m; ++i) {
- enterNodes[i] = d3_selection_dataNode(groupData[i]);
- }
- for (;i < n; ++i) {
- exitNodes[i] = group[i];
+ while (I < N) {
+ var c = text.charCodeAt(I++), k = 1;
+ if (c === 10) eol = true; else if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(I) === 10) ++I, ++k;
+ } else if (c !== delimiterCode) continue;
+ return text.substring(j, I - k);
}
+ return text.substring(j);
}
- enterNodes.update = updateNodes;
- enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
- enter.push(enterNodes);
- update.push(updateNodes);
- exit.push(exitNodes);
- }
- var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
- if (typeof value === "function") {
- while (++i < n) {
- bind(group = this[i], value.call(group, group.parentNode.__data__, i));
- }
- } else {
- while (++i < n) {
- bind(group = this[i], value);
+ while ((t = token()) !== EOF) {
+ var a = [];
+ while (t !== EOL && t !== EOF) {
+ a.push(t);
+ t = token();
+ }
+ if (f && !(a = f(a, n++))) continue;
+ rows.push(a);
}
- }
- update.enter = function() {
- return enter;
+ return rows;
};
- update.exit = function() {
- return exit;
+ dsv.format = function(rows) {
+ if (Array.isArray(rows[0])) return dsv.formatRows(rows);
+ var fieldSet = new d3_Set(), fields = [];
+ rows.forEach(function(row) {
+ for (var field in row) {
+ if (!fieldSet.has(field)) {
+ fields.push(fieldSet.add(field));
+ }
+ }
+ });
+ return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
+ return fields.map(function(field) {
+ return formatValue(row[field]);
+ }).join(delimiter);
+ })).join("\n");
};
- return update;
- };
- function d3_selection_dataNode(data) {
- return {
- __data__: data
+ dsv.formatRows = function(rows) {
+ return rows.map(formatRow).join("\n");
};
+ function formatRow(row) {
+ return row.map(formatValue).join(delimiter);
+ }
+ function formatValue(text) {
+ return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
+ }
+ return dsv;
}
- d3_selectionPrototype.datum = function(value) {
- return arguments.length ? this.property("__data__", value) : this.property("__data__");
+ d3.csv = d3_dsv(",", "text/csv");
+ d3.tsv = d3_dsv(" ", "text/tab-separated-values");
+ var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout;
+ d3.timer = function(callback, delay, then) {
+ if (arguments.length < 3) {
+ if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
+ then = Date.now();
+ }
+ var time = then + delay;
+ var timer = {
+ callback: callback,
+ time: time,
+ next: null
+ };
+ if (d3_timer_queueTail) d3_timer_queueTail.next = timer; else d3_timer_queueHead = timer;
+ d3_timer_queueTail = timer;
+ if (!d3_timer_interval) {
+ d3_timer_timeout = clearTimeout(d3_timer_timeout);
+ d3_timer_interval = 1;
+ d3_timer_frame(d3_timer_step);
+ }
};
- d3_selectionPrototype.filter = function(filter) {
- var subgroups = [], subgroup, group, node;
- if (typeof filter !== "function") filter = d3_selection_filter(filter);
- for (var j = 0, m = this.length; j < m; j++) {
- subgroups.push(subgroup = []);
- subgroup.parentNode = (group = this[j]).parentNode;
- for (var i = 0, n = group.length; i < n; i++) {
- if ((node = group[i]) && filter.call(node, node.__data__, i)) {
- subgroup.push(node);
- }
+ function d3_timer_step() {
+ var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
+ if (delay > 24) {
+ if (isFinite(delay)) {
+ clearTimeout(d3_timer_timeout);
+ d3_timer_timeout = setTimeout(d3_timer_step, delay);
}
+ d3_timer_interval = 0;
+ } else {
+ d3_timer_interval = 1;
+ d3_timer_frame(d3_timer_step);
}
- return d3_selection(subgroups);
+ }
+ d3.timer.flush = function() {
+ d3_timer_mark();
+ d3_timer_sweep();
};
- function d3_selection_filter(selector) {
- return function() {
- return d3_selectMatches(this, selector);
- };
+ function d3_timer_mark() {
+ var now = Date.now(), timer = d3_timer_queueHead;
+ while (timer) {
+ if (now >= timer.time) timer.flush = timer.callback(now - timer.time);
+ timer = timer.next;
+ }
+ return now;
}
- d3_selectionPrototype.order = function() {
- for (var j = -1, m = this.length; ++j < m; ) {
- for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
- if (node = group[i]) {
- if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
- next = node;
- }
+ function d3_timer_sweep() {
+ var t0, t1 = d3_timer_queueHead, time = Infinity;
+ while (t1) {
+ if (t1.flush) {
+ t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
+ } else {
+ if (t1.time < time) time = t1.time;
+ t1 = (t0 = t1).next;
}
}
- return this;
+ d3_timer_queueTail = t0;
+ return time;
+ }
+ var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {
+ setTimeout(callback, 17);
};
- d3_selectionPrototype.sort = function(comparator) {
- comparator = d3_selection_sortComparator.apply(this, arguments);
- for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
- return this.order();
+ var d3_format_decimalPoint = ".", d3_format_thousandsSeparator = ",", d3_format_grouping = [ 3, 3 ];
+ var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
+ d3.formatPrefix = function(value, precision) {
+ var i = 0;
+ if (value) {
+ if (value < 0) value *= -1;
+ if (precision) value = d3.round(value, d3_format_precision(value, precision));
+ i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
+ i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
+ }
+ return d3_formatPrefixes[8 + i / 3];
};
- function d3_selection_sortComparator(comparator) {
- if (!arguments.length) comparator = d3.ascending;
- return function(a, b) {
- return !a - !b || comparator(a.__data__, b.__data__);
+ function d3_formatPrefix(d, i) {
+ var k = Math.pow(10, Math.abs(8 - i) * 3);
+ return {
+ scale: i > 8 ? function(d) {
+ return d / k;
+ } : function(d) {
+ return d * k;
+ },
+ symbol: d
};
}
- d3_selectionPrototype.on = function(type, listener, capture) {
- var n = arguments.length;
- if (n < 3) {
- if (typeof type !== "string") {
- if (n < 2) listener = false;
- for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
- return this;
- }
- if (n < 2) return (n = this.node()["__on" + type]) && n._;
- capture = false;
- }
- return this.each(d3_selection_on(type, listener, capture));
+ d3.round = function(x, n) {
+ return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
};
- function d3_selection_on(type, listener, capture) {
- var name = "__on" + type, i = type.indexOf(".");
- if (i > 0) type = type.substring(0, i);
- function onRemove() {
- var wrapper = this[name];
- if (wrapper) {
- this.removeEventListener(type, wrapper, wrapper.$);
- delete this[name];
+ d3.format = function(specifier) {
+ var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", basePrefix = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, suffix = "", integer = false;
+ if (precision) precision = +precision.substring(1);
+ if (zfill || fill === "0" && align === "=") {
+ zfill = fill = "0";
+ align = "=";
+ if (comma) width -= Math.floor((width - 1) / 4);
+ }
+ switch (type) {
+ case "n":
+ comma = true;
+ type = "g";
+ break;
+
+ case "%":
+ scale = 100;
+ suffix = "%";
+ type = "f";
+ break;
+
+ case "p":
+ scale = 100;
+ suffix = "%";
+ type = "r";
+ break;
+
+ case "b":
+ case "o":
+ case "x":
+ case "X":
+ if (basePrefix) basePrefix = "0" + type.toLowerCase();
+
+ case "c":
+ case "d":
+ integer = true;
+ precision = 0;
+ break;
+
+ case "s":
+ scale = -1;
+ type = "r";
+ break;
+ }
+ if (basePrefix === "#") basePrefix = "";
+ if (type == "r" && !precision) type = "g";
+ if (precision != null) {
+ if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
+ }
+ type = d3_format_types.get(type) || d3_format_typeDefault;
+ var zcomma = zfill && comma;
+ return function(value) {
+ if (integer && value % 1) return "";
+ var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
+ if (scale < 0) {
+ var prefix = d3.formatPrefix(value, precision);
+ value = prefix.scale(value);
+ suffix = prefix.symbol;
+ } else {
+ value *= scale;
}
+ value = type(value, precision);
+ if (!zfill && comma) value = d3_format_group(value);
+ var length = basePrefix.length + value.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
+ if (zcomma) value = d3_format_group(padding + value);
+ if (d3_format_decimalPoint) value.replace(".", d3_format_decimalPoint);
+ negative += basePrefix;
+ return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + suffix;
+ };
+ };
+ var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
+ var d3_format_types = d3.map({
+ b: function(x) {
+ return x.toString(2);
+ },
+ c: function(x) {
+ return String.fromCharCode(x);
+ },
+ o: function(x) {
+ return x.toString(8);
+ },
+ x: function(x) {
+ return x.toString(16);
+ },
+ X: function(x) {
+ return x.toString(16).toUpperCase();
+ },
+ g: function(x, p) {
+ return x.toPrecision(p);
+ },
+ e: function(x, p) {
+ return x.toExponential(p);
+ },
+ f: function(x, p) {
+ return x.toFixed(p);
+ },
+ r: function(x, p) {
+ return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
}
- function onAdd() {
- var node = this, args = d3_array(arguments);
- onRemove.call(this);
- this.addEventListener(type, this[name] = wrapper, wrapper.$ = capture);
- wrapper._ = listener;
- function wrapper(e) {
- var o = d3.event;
- d3.event = e;
- args[0] = node.__data__;
- try {
- listener.apply(node, args);
- } finally {
- d3.event = o;
- }
+ });
+ function d3_format_precision(x, p) {
+ return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+ }
+ function d3_format_typeDefault(x) {
+ return x + "";
+ }
+ var d3_format_group = d3_identity;
+ if (d3_format_grouping) {
+ var d3_format_groupingLength = d3_format_grouping.length;
+ d3_format_group = function(value) {
+ var i = value.lastIndexOf("."), f = i >= 0 ? "." + value.substring(i + 1) : (i = value.length,
+ ""), t = [], j = 0, g = d3_format_grouping[0];
+ while (i > 0 && g > 0) {
+ t.push(value.substring(i -= g, i + g));
+ g = d3_format_grouping[j = (j + 1) % d3_format_groupingLength];
}
- }
- return listener ? onAdd : onRemove;
+ return t.reverse().join(d3_format_thousandsSeparator || "") + f;
+ };
}
- d3_selectionPrototype.each = function(callback) {
- return d3_selection_each(this, function(node, i, j) {
- callback.call(node, node.__data__, i, j);
- });
+ d3.geo = {};
+ d3.geo.stream = function(object, listener) {
+ if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
+ d3_geo_streamObjectType[object.type](object, listener);
+ } else {
+ d3_geo_streamGeometry(object, listener);
+ }
};
- function d3_selection_each(groups, callback) {
- for (var j = 0, m = groups.length; j < m; j++) {
- for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
- if (node = group[i]) callback(node, i, j);
- }
+ function d3_geo_streamGeometry(geometry, listener) {
+ if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+ d3_geo_streamGeometryType[geometry.type](geometry, listener);
}
- return groups;
}
- d3_selectionPrototype.call = function(callback) {
- var args = d3_array(arguments);
- callback.apply(args[0] = this, args);
- return this;
- };
- d3_selectionPrototype.empty = function() {
- return !this.node();
- };
- d3_selectionPrototype.node = function() {
- for (var j = 0, m = this.length; j < m; j++) {
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
- var node = group[i];
- if (node) return node;
- }
+ var d3_geo_streamObjectType = {
+ Feature: function(feature, listener) {
+ d3_geo_streamGeometry(feature.geometry, listener);
+ },
+ FeatureCollection: function(object, listener) {
+ var features = object.features, i = -1, n = features.length;
+ while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
}
- return null;
};
- d3_selectionPrototype.transition = function() {
- var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = Object.create(d3_transitionInherit);
- transition.time = Date.now();
- for (var j = -1, m = this.length; ++j < m; ) {
- subgroups.push(subgroup = []);
- for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) d3_transitionNode(node, i, id, transition);
- subgroup.push(node);
- }
+ var d3_geo_streamGeometryType = {
+ Sphere: function(object, listener) {
+ listener.sphere();
+ },
+ Point: function(object, listener) {
+ var coordinate = object.coordinates;
+ listener.point(coordinate[0], coordinate[1]);
+ },
+ MultiPoint: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;
+ while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
+ },
+ LineString: function(object, listener) {
+ d3_geo_streamLine(object.coordinates, listener, 0);
+ },
+ MultiLineString: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length;
+ while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
+ },
+ Polygon: function(object, listener) {
+ d3_geo_streamPolygon(object.coordinates, listener);
+ },
+ MultiPolygon: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length;
+ while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
+ },
+ GeometryCollection: function(object, listener) {
+ var geometries = object.geometries, i = -1, n = geometries.length;
+ while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
}
- return d3_transition(subgroups, id);
- };
- var d3_selectionRoot = d3_selection([ [ d3_document ] ]);
- d3_selectionRoot[0].parentNode = d3_selectRoot;
- d3.select = function(selector) {
- return typeof selector === "string" ? d3_selectionRoot.select(selector) : d3_selection([ [ selector ] ]);
};
- d3.selectAll = function(selector) {
- return typeof selector === "string" ? d3_selectionRoot.selectAll(selector) : d3_selection([ d3_array(selector) ]);
- };
- function d3_selection_enter(selection) {
- d3_arraySubclass(selection, d3_selection_enterPrototype);
- return selection;
+ function d3_geo_streamLine(coordinates, listener, closed) {
+ var i = -1, n = coordinates.length - closed, coordinate;
+ listener.lineStart();
+ while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
+ listener.lineEnd();
}
- var d3_selection_enterPrototype = [];
- d3.selection.enter = d3_selection_enter;
- d3.selection.enter.prototype = d3_selection_enterPrototype;
- d3_selection_enterPrototype.append = d3_selectionPrototype.append;
- d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;
- d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
- d3_selection_enterPrototype.node = d3_selectionPrototype.node;
- d3_selection_enterPrototype.select = function(selector) {
- var subgroups = [], subgroup, subnode, upgroup, group, node;
- for (var j = -1, m = this.length; ++j < m; ) {
- upgroup = (group = this[j]).update;
- subgroups.push(subgroup = []);
- subgroup.parentNode = group.parentNode;
- for (var i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i));
- subnode.__data__ = node.__data__;
- } else {
- subgroup.push(null);
- }
- }
- }
- return d3_selection(subgroups);
- };
- function d3_transition(groups, id) {
- d3_arraySubclass(groups, d3_transitionPrototype);
- groups.id = id;
- return groups;
+ function d3_geo_streamPolygon(coordinates, listener) {
+ var i = -1, n = coordinates.length;
+ listener.polygonStart();
+ while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
+ listener.polygonEnd();
}
- var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = {
- ease: d3_ease_cubicInOut,
- delay: 0,
- duration: 250
+ d3.geo.area = function(object) {
+ d3_geo_areaSum = 0;
+ d3.geo.stream(object, d3_geo_area);
+ return d3_geo_areaSum;
};
- d3_transitionPrototype.call = d3_selectionPrototype.call;
- d3_transitionPrototype.empty = d3_selectionPrototype.empty;
- d3_transitionPrototype.node = d3_selectionPrototype.node;
- d3.transition = function(selection) {
- return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+ var d3_geo_areaSum, d3_geo_areaRingSum;
+ var d3_geo_area = {
+ sphere: function() {
+ d3_geo_areaSum += 4 * π;
+ },
+ point: d3_noop,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: function() {
+ d3_geo_areaRingSum = 0;
+ d3_geo_area.lineStart = d3_geo_areaRingStart;
+ },
+ polygonEnd: function() {
+ var area = 2 * d3_geo_areaRingSum;
+ d3_geo_areaSum += area < 0 ? 4 * π + area : area;
+ d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
+ }
};
- d3.transition.prototype = d3_transitionPrototype;
- function d3_transitionNode(node, i, id, inherit) {
- var lock = node.__transition__ || (node.__transition__ = {
- active: 0,
- count: 0
- }), transition = lock[id];
- if (!transition) {
- var time = inherit.time;
- transition = lock[id] = {
- tween: new d3_Map(),
- event: d3.dispatch("start", "end"),
- time: time,
- ease: inherit.ease,
- delay: inherit.delay,
- duration: inherit.duration
- };
- ++lock.count;
- d3.timer(function(elapsed) {
- var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = [];
- return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1;
- function start(elapsed) {
- if (lock.active > id) return stop();
- lock.active = id;
- event.start.call(node, d, i);
- transition.tween.forEach(function(key, value) {
- if (value = value.call(node, d, i)) {
- tweened.push(value);
- }
- });
- if (!tick(elapsed)) d3.timer(tick, 0, time);
- return 1;
- }
- function tick(elapsed) {
- if (lock.active !== id) return stop();
- var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;
- while (n > 0) {
- tweened[--n].call(node, e);
- }
- if (t >= 1) {
- stop();
- event.end.call(node, d, i);
- return 1;
- }
- }
- function stop() {
- if (--lock.count) delete lock[id]; else delete node.__transition__;
- return 1;
- }
- }, 0, time);
- return transition;
+ function d3_geo_areaRingStart() {
+ var λ00, φ00, λ0, cosφ0, sinφ0;
+ d3_geo_area.point = function(λ, φ) {
+ d3_geo_area.point = nextPoint;
+ λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4),
+ sinφ0 = Math.sin(φ);
+ };
+ function nextPoint(λ, φ) {
+ λ *= d3_radians;
+ φ = φ * d3_radians / 2 + π / 4;
+ var dλ = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ);
+ d3_geo_areaRingSum += Math.atan2(v, u);
+ λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
}
+ d3_geo_area.lineEnd = function() {
+ nextPoint(λ00, φ00);
+ };
+ }
+ function d3_geo_cartesian(spherical) {
+ var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
+ return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+ }
+ function d3_geo_cartesianDot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+ function d3_geo_cartesianCross(a, b) {
+ return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+ }
+ function d3_geo_cartesianAdd(a, b) {
+ a[0] += b[0];
+ a[1] += b[1];
+ a[2] += b[2];
+ }
+ function d3_geo_cartesianScale(vector, k) {
+ return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+ }
+ function d3_geo_cartesianNormalize(d) {
+ var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+ d[0] /= l;
+ d[1] /= l;
+ d[2] /= l;
+ }
+ function d3_geo_spherical(cartesian) {
+ return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ];
+ }
+ function d3_geo_sphericalEqual(a, b) {
+ return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
}
- d3_transitionPrototype.select = function(selector) {
- var id = this.id, subgroups = [], subgroup, subnode, node;
- if (typeof selector !== "function") selector = d3_selection_selector(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- subgroups.push(subgroup = []);
- for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
- if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i))) {
- if ("__data__" in node) subnode.__data__ = node.__data__;
- d3_transitionNode(subnode, i, id, node.__transition__[id]);
- subgroup.push(subnode);
+ d3.geo.bounds = function() {
+ var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
+ var bound = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ bound.point = ringPoint;
+ bound.lineStart = ringStart;
+ bound.lineEnd = ringEnd;
+ dλSum = 0;
+ d3_geo_area.polygonStart();
+ },
+ polygonEnd: function() {
+ d3_geo_area.polygonEnd();
+ bound.point = point;
+ bound.lineStart = lineStart;
+ bound.lineEnd = lineEnd;
+ if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
+ range[0] = λ0, range[1] = λ1;
+ }
+ };
+ function point(λ, φ) {
+ ranges.push(range = [ λ0 = λ, λ1 = λ ]);
+ if (φ < φ0) φ0 = φ;
+ if (φ > φ1) φ1 = φ;
+ }
+ function linePoint(λ, φ) {
+ var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
+ if (p0) {
+ var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
+ d3_geo_cartesianNormalize(inflection);
+ inflection = d3_geo_spherical(inflection);
+ var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = Math.abs(dλ) > 180;
+ if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+ var φi = inflection[1] * d3_degrees;
+ if (φi > φ1) φ1 = φi;
+ } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+ var φi = -inflection[1] * d3_degrees;
+ if (φi < φ0) φ0 = φi;
} else {
- subgroup.push(null);
+ if (φ < φ0) φ0 = φ;
+ if (φ > φ1) φ1 = φ;
}
- }
- }
- return d3_transition(subgroups, id);
- };
- d3_transitionPrototype.selectAll = function(selector) {
- var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
- if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
- for (var j = -1, m = this.length; ++j < m; ) {
- for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
- if (node = group[i]) {
- transition = node.__transition__[id];
- subnodes = selector.call(node, node.__data__, i);
- subgroups.push(subgroup = []);
- for (var k = -1, o = subnodes.length; ++k < o; ) {
- d3_transitionNode(subnode = subnodes[k], k, id, transition);
- subgroup.push(subnode);
+ if (antimeridian) {
+ if (λ < λ_) {
+ if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+ } else {
+ if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+ }
+ } else {
+ if (λ1 >= λ0) {
+ if (λ < λ0) λ0 = λ;
+ if (λ > λ1) λ1 = λ;
+ } else {
+ if (λ > λ_) {
+ if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+ } else {
+ if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+ }
}
}
+ } else {
+ point(λ, φ);
}
+ p0 = p, λ_ = λ;
}
- return d3_transition(subgroups, id);
- };
- d3_transitionPrototype.filter = function(filter) {
- var subgroups = [], subgroup, group, node;
- if (typeof filter !== "function") filter = d3_selection_filter(filter);
- for (var j = 0, m = this.length; j < m; j++) {
- subgroups.push(subgroup = []);
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
- if ((node = group[i]) && filter.call(node, node.__data__, i)) {
- subgroup.push(node);
- }
- }
+ function lineStart() {
+ bound.point = linePoint;
}
- return d3_transition(subgroups, this.id, this.time).ease(this.ease());
- };
- d3_transitionPrototype.attr = function(nameNS, value) {
- if (arguments.length < 2) {
- for (value in nameNS) this.attr(value, nameNS[value]);
- return this;
+ function lineEnd() {
+ range[0] = λ0, range[1] = λ1;
+ bound.point = point;
+ p0 = null;
}
- var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS);
- function attrNull() {
- this.removeAttribute(name);
+ function ringPoint(λ, φ) {
+ if (p0) {
+ var dλ = λ - λ_;
+ dλSum += Math.abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
+ } else λ__ = λ, φ__ = φ;
+ d3_geo_area.point(λ, φ);
+ linePoint(λ, φ);
}
- function attrNullNS() {
- this.removeAttributeNS(name.space, name.local);
+ function ringStart() {
+ d3_geo_area.lineStart();
}
- return d3_transition_tween(this, "attr." + nameNS, value, function(b) {
- function attrString() {
- var a = this.getAttribute(name), i;
- return a !== b && (i = interpolate(a, b), function(t) {
- this.setAttribute(name, i(t));
- });
- }
- function attrStringNS() {
- var a = this.getAttributeNS(name.space, name.local), i;
- return a !== b && (i = interpolate(a, b), function(t) {
- this.setAttributeNS(name.space, name.local, i(t));
- });
- }
- return b == null ? name.local ? attrNullNS : attrNull : (b += "", name.local ? attrStringNS : attrString);
- });
- };
- d3_transitionPrototype.attrTween = function(nameNS, tween) {
- var name = d3.ns.qualify(nameNS);
- function attrTween(d, i) {
- var f = tween.call(this, d, i, this.getAttribute(name));
- return f && function(t) {
- this.setAttribute(name, f(t));
- };
+ function ringEnd() {
+ ringPoint(λ__, φ__);
+ d3_geo_area.lineEnd();
+ if (Math.abs(dλSum) > ε) λ0 = -(λ1 = 180);
+ range[0] = λ0, range[1] = λ1;
+ p0 = null;
}
- function attrTweenNS(d, i) {
- var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
- return f && function(t) {
- this.setAttributeNS(name.space, name.local, f(t));
- };
+ function angle(λ0, λ1) {
+ return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
}
- return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
- };
- d3_transitionPrototype.style = function(name, value, priority) {
- var n = arguments.length;
- if (n < 3) {
- if (typeof name !== "string") {
- if (n < 2) value = "";
- for (priority in name) this.style(priority, name[priority], value);
- return this;
- }
- priority = "";
+ function compareRanges(a, b) {
+ return a[0] - b[0];
}
- var interpolate = d3_interpolateByName(name);
- function styleNull() {
- this.style.removeProperty(name);
+ function withinRange(x, range) {
+ return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
}
- return d3_transition_tween(this, "style." + name, value, function(b) {
- function styleString() {
- var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
- return a !== b && (i = interpolate(a, b), function(t) {
- this.style.setProperty(name, i(t), priority);
- });
+ return function(feature) {
+ φ1 = λ1 = -(λ0 = φ0 = Infinity);
+ ranges = [];
+ d3.geo.stream(feature, bound);
+ ranges.sort(compareRanges);
+ for (var i = 1, n = ranges.length, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
+ b = ranges[i];
+ if (withinRange(b[0], a) || withinRange(b[1], a)) {
+ if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
+ if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
+ } else {
+ merged.push(a = b);
+ }
}
- return b == null ? styleNull : (b += "", styleString);
- });
- };
- d3_transitionPrototype.styleTween = function(name, tween, priority) {
- if (arguments.length < 3) priority = "";
- return this.tween("style." + name, function(d, i) {
- var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
- return f && function(t) {
- this.style.setProperty(name, f(t), priority);
- };
- });
- };
- d3_transitionPrototype.text = function(value) {
- return d3_transition_tween(this, "text", value, d3_transition_text);
- };
- function d3_transition_text(b) {
- if (b == null) b = "";
- return function() {
- this.textContent = b;
+ var best = -Infinity, dλ;
+ for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
+ b = merged[i];
+ if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
+ }
+ ranges = range = null;
+ return [ [ λ0, φ0 ], [ λ1, φ1 ] ];
};
- }
- d3_transitionPrototype.remove = function() {
- return this.each("end.transition", function() {
- var p;
- if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
- });
- };
- d3_transitionPrototype.ease = function(value) {
- var id = this.id;
- if (arguments.length < 1) return this.node().__transition__[id].ease;
- if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
- return d3_selection_each(this, function(node) {
- node.__transition__[id].ease = value;
- });
- };
- d3_transitionPrototype.delay = function(value) {
- var id = this.id;
- return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0;
- } : (value |= 0, function(node) {
- node.__transition__[id].delay = value;
- }));
- };
- d3_transitionPrototype.duration = function(value) {
- var id = this.id;
- return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0);
- } : (value = Math.max(1, value | 0), function(node) {
- node.__transition__[id].duration = value;
- }));
- };
- d3_transitionPrototype.each = function(type, listener) {
- var id = this.id;
- if (arguments.length < 2) {
- var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
- d3_transitionInheritId = id;
- d3_selection_each(this, function(node, i, j) {
- d3_transitionInherit = node.__transition__[id];
- type.call(node, node.__data__, i, j);
- });
- d3_transitionInherit = inherit;
- d3_transitionInheritId = inheritId;
- } else {
- d3_selection_each(this, function(node) {
- node.__transition__[id].event.on(type, listener);
- });
+ }();
+ d3.geo.centroid = function(object) {
+ d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ d3.geo.stream(object, d3_geo_centroid);
+ var m;
+ if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
+ return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];
}
- return this;
};
- d3_transitionPrototype.transition = function() {
- var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
- for (var j = 0, m = this.length; j < m; j++) {
- subgroups.push(subgroup = []);
- for (var group = this[j], i = 0, n = group.length; i < n; i++) {
- if (node = group[i]) {
- transition = Object.create(node.__transition__[id0]);
- transition.delay += transition.duration;
- d3_transitionNode(node, i, id1, transition);
- }
- subgroup.push(node);
+ var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
+ var d3_geo_centroid = {
+ sphere: function() {
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ }
+ },
+ point: d3_geo_centroidPoint,
+ lineStart: d3_geo_centroidLineStart,
+ lineEnd: d3_geo_centroidLineEnd,
+ polygonStart: function() {
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
+ d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
}
- return d3_transition(subgroups, id1);
- };
- d3_transitionPrototype.tween = function(name, tween) {
- var id = this.id;
- if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
- return d3_selection_each(this, tween == null ? function(node) {
- node.__transition__[id].tween.remove(name);
- } : function(node) {
- node.__transition__[id].tween.set(name, tween);
- });
};
- function d3_transition_tween(groups, name, value, tween) {
- var id = groups.id;
- return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
- node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
- } : (value = tween(value), function(node) {
- node.__transition__[id].tween.set(name, value);
- }));
+ function d3_geo_centroidPoint(λ, φ) {
+ if (d3_geo_centroidDimension) return;
+ ++d3_geo_centroidW;
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians);
+ d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW;
+ d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW;
+ d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW;
}
- var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
- d3.timer = function(callback, delay, then) {
- if (arguments.length < 3) {
- if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
- then = Date.now();
+ function d3_geo_centroidRingStart() {
+ var λ00, φ00;
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidLineStart();
+ d3_geo_centroidDimension = 2;
+ var linePoint = d3_geo_centroid.point;
+ d3_geo_centroid.point = function(λ, φ) {
+ linePoint(λ00 = λ, φ00 = φ);
+ };
+ d3_geo_centroid.lineEnd = function() {
+ d3_geo_centroid.point(λ00, φ00);
+ d3_geo_centroidLineEnd();
+ d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+ };
+ }
+ function d3_geo_centroidLineStart() {
+ var x0, y0, z0;
+ if (d3_geo_centroidDimension > 1) return;
+ if (d3_geo_centroidDimension < 1) {
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
- var timer = d3_timer_byId[callback.id];
- if (timer && timer.callback === callback) {
- timer.then = then;
- timer.delay = delay;
- } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
- callback: callback,
- then: then,
- delay: delay,
- next: d3_timer_queue
+ d3_geo_centroid.point = function(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians);
+ x0 = cosφ * Math.cos(λ);
+ y0 = cosφ * Math.sin(λ);
+ z0 = Math.sin(φ);
+ d3_geo_centroid.point = nextPoint;
};
- if (!d3_timer_interval) {
- d3_timer_timeout = clearTimeout(d3_timer_timeout);
- d3_timer_interval = 1;
- d3_timer_frame(d3_timer_step);
- }
- };
- function d3_timer_step() {
- var elapsed, now = Date.now(), t1 = d3_timer_queue;
- while (t1) {
- elapsed = now - t1.then;
- if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
- t1 = t1.next;
+ function nextPoint(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
+ d3_geo_centroidW += w;
+ d3_geo_centroidX += w * (x0 + (x0 = x));
+ d3_geo_centroidY += w * (y0 + (y0 = y));
+ d3_geo_centroidZ += w * (z0 + (z0 = z));
}
- var delay = d3_timer_flush() - now;
- if (delay > 24) {
- if (isFinite(delay)) {
- clearTimeout(d3_timer_timeout);
- d3_timer_timeout = setTimeout(d3_timer_step, delay);
+ }
+ function d3_geo_centroidLineEnd() {
+ d3_geo_centroid.point = d3_geo_centroidPoint;
+ }
+ function d3_true() {
+ return true;
+ }
+ function d3_geo_clipPolygon(segments, compare, inside, interpolate, listener) {
+ var subject = [], clip = [];
+ segments.forEach(function(segment) {
+ if ((n = segment.length - 1) <= 0) return;
+ var n, p0 = segment[0], p1 = segment[n];
+ if (d3_geo_sphericalEqual(p0, p1)) {
+ listener.lineStart();
+ for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
+ listener.lineEnd();
+ return;
}
- d3_timer_interval = 0;
- } else {
- d3_timer_interval = 1;
- d3_timer_frame(d3_timer_step);
+ var a = {
+ point: p0,
+ points: segment,
+ other: null,
+ visited: false,
+ entry: true,
+ subject: true
+ }, b = {
+ point: p0,
+ points: [ p0 ],
+ other: a,
+ visited: false,
+ entry: false,
+ subject: false
+ };
+ a.other = b;
+ subject.push(a);
+ clip.push(b);
+ a = {
+ point: p1,
+ points: [ p1 ],
+ other: null,
+ visited: false,
+ entry: false,
+ subject: true
+ };
+ b = {
+ point: p1,
+ points: [ p1 ],
+ other: a,
+ visited: false,
+ entry: true,
+ subject: false
+ };
+ a.other = b;
+ subject.push(a);
+ clip.push(b);
+ });
+ clip.sort(compare);
+ d3_geo_clipPolygonLinkCircular(subject);
+ d3_geo_clipPolygonLinkCircular(clip);
+ if (!subject.length) return;
+ if (inside) for (var i = 1, e = !inside(clip[0].point), n = clip.length; i < n; ++i) {
+ clip[i].entry = e = !e;
}
- }
- d3.timer.flush = function() {
- var elapsed, now = Date.now(), t1 = d3_timer_queue;
- while (t1) {
- elapsed = now - t1.then;
- if (!t1.delay) t1.flush = t1.callback(elapsed);
- t1 = t1.next;
+ var start = subject[0], current, points, point;
+ while (1) {
+ current = start;
+ while (current.visited) if ((current = current.next) === start) return;
+ points = current.points;
+ listener.lineStart();
+ do {
+ current.visited = current.other.visited = true;
+ if (current.entry) {
+ if (current.subject) {
+ for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.point, current.next.point, 1, listener);
+ }
+ current = current.next;
+ } else {
+ if (current.subject) {
+ points = current.prev.points;
+ for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.point, current.prev.point, -1, listener);
+ }
+ current = current.prev;
+ }
+ current = current.other;
+ points = current.points;
+ } while (!current.visited);
+ listener.lineEnd();
}
- d3_timer_flush();
- };
- function d3_timer_flush() {
- var t0 = null, t1 = d3_timer_queue, then = Infinity;
- while (t1) {
- if (t1.flush) {
- delete d3_timer_byId[t1.callback.id];
- t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
- } else {
- then = Math.min(then, t1.then + t1.delay);
- t1 = (t0 = t1).next;
- }
+ }
+ function d3_geo_clipPolygonLinkCircular(array) {
+ if (!(n = array.length)) return;
+ var n, i = 0, a = array[0], b;
+ while (++i < n) {
+ a.next = b = array[i];
+ b.prev = a;
+ a = b;
}
- return then;
+ a.next = b = array[0];
+ b.prev = a;
}
- var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {
- setTimeout(callback, 17);
- };
- d3.mouse = function(container) {
- return d3_mousePoint(container, d3_eventSource());
- };
- var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0;
- function d3_mousePoint(container, e) {
- var svg = container.ownerSVGElement || container;
- if (svg.createSVGPoint) {
- var point = svg.createSVGPoint();
- if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) {
- svg = d3.select(d3_document.body).append("svg").style("position", "absolute").style("top", 0).style("left", 0);
- var ctm = svg[0][0].getScreenCTM();
- d3_mouse_bug44083 = !(ctm.f || ctm.e);
- svg.remove();
+ function d3_geo_clip(pointVisible, clipLine, interpolate) {
+ return function(listener) {
+ var line = clipLine(listener);
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ clip.point = pointRing;
+ clip.lineStart = ringStart;
+ clip.lineEnd = ringEnd;
+ invisible = false;
+ invisibleArea = visibleArea = 0;
+ segments = [];
+ listener.polygonStart();
+ },
+ polygonEnd: function() {
+ clip.point = point;
+ clip.lineStart = lineStart;
+ clip.lineEnd = lineEnd;
+ segments = d3.merge(segments);
+ if (segments.length) {
+ d3_geo_clipPolygon(segments, d3_geo_clipSort, null, interpolate, listener);
+ } else if (visibleArea < -ε || invisible && invisibleArea < -ε) {
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ }
+ listener.polygonEnd();
+ segments = null;
+ },
+ sphere: function() {
+ listener.polygonStart();
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ listener.polygonEnd();
+ }
+ };
+ function point(λ, φ) {
+ if (pointVisible(λ, φ)) listener.point(λ, φ);
}
- if (d3_mouse_bug44083) {
- point.x = e.pageX;
- point.y = e.pageY;
- } else {
- point.x = e.clientX;
- point.y = e.clientY;
+ function pointLine(λ, φ) {
+ line.point(λ, φ);
+ }
+ function lineStart() {
+ clip.point = pointLine;
+ line.lineStart();
+ }
+ function lineEnd() {
+ clip.point = point;
+ line.lineEnd();
+ }
+ var segments, visibleArea, invisibleArea, invisible;
+ var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring;
+ function pointRing(λ, φ) {
+ ringListener.point(λ, φ);
+ ring.push([ λ, φ ]);
+ }
+ function ringStart() {
+ ringListener.lineStart();
+ ring = [];
+ }
+ function ringEnd() {
+ pointRing(ring[0][0], ring[0][1]);
+ ringListener.lineEnd();
+ var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
+ if (!n) {
+ invisible = true;
+ invisibleArea += d3_geo_clipAreaRing(ring, -1);
+ ring = null;
+ return;
+ }
+ ring = null;
+ if (clean & 1) {
+ segment = ringSegments[0];
+ visibleArea += d3_geo_clipAreaRing(segment, 1);
+ var n = segment.length - 1, i = -1, point;
+ listener.lineStart();
+ while (++i < n) listener.point((point = segment[i])[0], point[1]);
+ listener.lineEnd();
+ return;
+ }
+ if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
+ segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+ }
+ return clip;
+ };
+ }
+ function d3_geo_clipSegmentLength1(segment) {
+ return segment.length > 1;
+ }
+ function d3_geo_clipBufferListener() {
+ var lines = [], line;
+ return {
+ lineStart: function() {
+ lines.push(line = []);
+ },
+ point: function(λ, φ) {
+ line.push([ λ, φ ]);
+ },
+ lineEnd: d3_noop,
+ buffer: function() {
+ var buffer = lines;
+ lines = [];
+ line = null;
+ return buffer;
+ },
+ rejoin: function() {
+ if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
}
- point = point.matrixTransform(container.getScreenCTM().inverse());
- return [ point.x, point.y ];
+ };
+ }
+ function d3_geo_clipAreaRing(ring, invisible) {
+ if (!(n = ring.length)) return 0;
+ var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y;
+ while (++i < n) {
+ p = ring[i];
+ cosφ = Math.cos(φ = p[1]);
+ x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ));
+ y = 1 - invisible * Math.cos(λ) * cosφ;
+ if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue;
+ if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) {
+ if (y + y0 > 2) area += 4 * (x - x0);
+ } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y);
+ x1 = x0, x0 = x, y0 = y;
}
- var rect = container.getBoundingClientRect();
- return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+ return area;
}
- d3.touches = function(container, touches) {
- if (arguments.length < 2) touches = d3_eventSource().touches;
- return touches ? d3_array(touches).map(function(touch) {
- var point = d3_mousePoint(container, touch);
- point.identifier = touch.identifier;
- return point;
- }) : [];
- };
- function d3_noop() {}
- d3.scale = {};
- function d3_scaleExtent(domain) {
- var start = domain[0], stop = domain[domain.length - 1];
- return start < stop ? [ start, stop ] : [ stop, start ];
+ function d3_geo_clipSort(a, b) {
+ return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]);
}
- function d3_scaleRange(scale) {
- return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+ var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate);
+ function d3_geo_clipAntimeridianLine(listener) {
+ var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
+ return {
+ lineStart: function() {
+ listener.lineStart();
+ clean = 1;
+ },
+ point: function(λ1, φ1) {
+ var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0);
+ if (Math.abs(dλ - π) < ε) {
+ listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2);
+ listener.point(sλ0, φ0);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(sλ1, φ0);
+ listener.point(λ1, φ0);
+ clean = 0;
+ } else if (sλ0 !== sλ1 && dλ >= π) {
+ if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
+ if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
+ φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
+ listener.point(sλ0, φ0);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(sλ1, φ0);
+ clean = 0;
+ }
+ listener.point(λ0 = λ1, φ0 = φ1);
+ sλ0 = sλ1;
+ },
+ lineEnd: function() {
+ listener.lineEnd();
+ λ0 = φ0 = NaN;
+ },
+ clean: function() {
+ return 2 - clean;
+ }
+ };
}
- function d3_scale_nice(domain, nice) {
- var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
- if (x1 < x0) {
- dx = i0, i0 = i1, i1 = dx;
- dx = x0, x0 = x1, x1 = dx;
- }
- if (nice = nice(x1 - x0)) {
- domain[i0] = nice.floor(x0);
- domain[i1] = nice.ceil(x1);
- }
- return domain;
+ function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
+ var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+ return Math.abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
}
- function d3_scale_niceDefault() {
- return Math;
+ function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+ var φ;
+ if (from == null) {
+ φ = direction * π / 2;
+ listener.point(-π, φ);
+ listener.point(0, φ);
+ listener.point(π, φ);
+ listener.point(π, 0);
+ listener.point(π, -φ);
+ listener.point(0, -φ);
+ listener.point(-π, -φ);
+ listener.point(-π, 0);
+ listener.point(-π, φ);
+ } else if (Math.abs(from[0] - to[0]) > ε) {
+ var s = (from[0] < to[0] ? 1 : -1) * π;
+ φ = direction * s / 2;
+ listener.point(-s, φ);
+ listener.point(0, φ);
+ listener.point(s, φ);
+ } else {
+ listener.point(to[0], to[1]);
+ }
}
- d3.scale.linear = function() {
- return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3.interpolate, false);
- };
- function d3_scale_linear(domain, range, interpolate, clamp) {
- var output, input;
- function rescale() {
- var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
- output = linear(domain, range, uninterpolate, interpolate);
- input = linear(range, domain, uninterpolate, d3.interpolate);
- return scale;
+ function d3_geo_clipCircle(radius) {
+ var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = Math.abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+ return d3_geo_clip(visible, clipLine, interpolate);
+ function visible(λ, φ) {
+ return Math.cos(λ) * Math.cos(φ) > cr;
}
- function scale(x) {
- return output(x);
+ function clipLine(listener) {
+ var point0, c0, v0, v00, clean;
+ return {
+ lineStart: function() {
+ v00 = v0 = false;
+ clean = 1;
+ },
+ point: function(λ, φ) {
+ var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
+ if (!point0 && (v00 = v0 = v)) listener.lineStart();
+ if (v !== v0) {
+ point2 = intersect(point0, point1);
+ if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
+ point1[0] += ε;
+ point1[1] += ε;
+ v = visible(point1[0], point1[1]);
+ }
+ }
+ if (v !== v0) {
+ clean = 0;
+ if (v) {
+ listener.lineStart();
+ point2 = intersect(point1, point0);
+ listener.point(point2[0], point2[1]);
+ } else {
+ point2 = intersect(point0, point1);
+ listener.point(point2[0], point2[1]);
+ listener.lineEnd();
+ }
+ point0 = point2;
+ } else if (notHemisphere && point0 && smallRadius ^ v) {
+ var t;
+ if (!(c & c0) && (t = intersect(point1, point0, true))) {
+ clean = 0;
+ if (smallRadius) {
+ listener.lineStart();
+ listener.point(t[0][0], t[0][1]);
+ listener.point(t[1][0], t[1][1]);
+ listener.lineEnd();
+ } else {
+ listener.point(t[1][0], t[1][1]);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(t[0][0], t[0][1]);
+ }
+ }
+ }
+ if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
+ listener.point(point1[0], point1[1]);
+ }
+ point0 = point1, v0 = v, c0 = c;
+ },
+ lineEnd: function() {
+ if (v0) listener.lineEnd();
+ point0 = null;
+ },
+ clean: function() {
+ return clean | (v00 && v0) << 1;
+ }
+ };
}
- scale.invert = function(y) {
- return input(y);
- };
- scale.domain = function(x) {
- if (!arguments.length) return domain;
- domain = x.map(Number);
- return rescale();
- };
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- return rescale();
- };
- scale.rangeRound = function(x) {
- return scale.range(x).interpolate(d3.interpolateRound);
- };
- scale.clamp = function(x) {
- if (!arguments.length) return clamp;
- clamp = x;
- return rescale();
- };
- scale.interpolate = function(x) {
- if (!arguments.length) return interpolate;
- interpolate = x;
- return rescale();
- };
- scale.ticks = function(m) {
- return d3_scale_linearTicks(domain, m);
- };
- scale.tickFormat = function(m) {
- return d3_scale_linearTickFormat(domain, m);
- };
- scale.nice = function() {
- d3_scale_nice(domain, d3_scale_linearNice);
- return rescale();
- };
- scale.copy = function() {
- return d3_scale_linear(domain, range, interpolate, clamp);
- };
- return rescale();
- }
- function d3_scale_linearRebind(scale, linear) {
- return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
- }
- function d3_scale_linearNice(dx) {
- dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
- return dx && {
- floor: function(x) {
- return Math.floor(x / dx) * dx;
- },
- ceil: function(x) {
- return Math.ceil(x / dx) * dx;
+ function intersect(a, b, two) {
+ var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
+ var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
+ if (!determinant) return !two && a;
+ var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
+ d3_geo_cartesianAdd(A, B);
+ var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
+ if (t2 < 0) return;
+ var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
+ d3_geo_cartesianAdd(q, A);
+ q = d3_geo_spherical(q);
+ if (!two) return q;
+ var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
+ if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
+ var δλ = λ1 - λ0, polar = Math.abs(δλ - π) < ε, meridian = polar || δλ < ε;
+ if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
+ if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (Math.abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
+ var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
+ d3_geo_cartesianAdd(q1, A);
+ return [ q, d3_geo_spherical(q1) ];
+ }
+ }
+ function code(λ, φ) {
+ var r = smallRadius ? radius : π - radius, code = 0;
+ if (λ < -r) code |= 1; else if (λ > r) code |= 2;
+ if (φ < -r) code |= 4; else if (φ > r) code |= 8;
+ return code;
+ }
+ }
+ var d3_geo_clipViewMAX = 1e9;
+ function d3_geo_clipView(x0, y0, x1, y1) {
+ return function(listener) {
+ var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), segments, polygon, ring;
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ listener = bufferListener;
+ segments = [];
+ polygon = [];
+ },
+ polygonEnd: function() {
+ listener = listener_;
+ if ((segments = d3.merge(segments)).length) {
+ listener.polygonStart();
+ d3_geo_clipPolygon(segments, compare, inside, interpolate, listener);
+ listener.polygonEnd();
+ } else if (insidePolygon([ x0, y0 ])) {
+ listener.polygonStart(), listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd(), listener.polygonEnd();
+ }
+ segments = polygon = ring = null;
+ }
+ };
+ function inside(point) {
+ var a = corner(point, -1), i = insidePolygon([ a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0 ]);
+ return i;
+ }
+ function insidePolygon(p) {
+ var wn = 0, n = polygon.length, y = p[1];
+ for (var i = 0; i < n; ++i) {
+ for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
+ b = v[j];
+ if (a[1] <= y) {
+ if (b[1] > y && isLeft(a, b, p) > 0) ++wn;
+ } else {
+ if (b[1] <= y && isLeft(a, b, p) < 0) --wn;
+ }
+ a = b;
+ }
+ }
+ return wn !== 0;
+ }
+ function isLeft(a, b, c) {
+ return (b[0] - a[0]) * (c[1] - a[1]) - (c[0] - a[0]) * (b[1] - a[1]);
+ }
+ function interpolate(from, to, direction, listener) {
+ var a = 0, a1 = 0;
+ if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
+ do {
+ listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
+ } while ((a = (a + direction + 4) % 4) !== a1);
+ } else {
+ listener.point(to[0], to[1]);
+ }
+ }
+ function visible(x, y) {
+ return x0 <= x && x <= x1 && y0 <= y && y <= y1;
+ }
+ function point(x, y) {
+ if (visible(x, y)) listener.point(x, y);
+ }
+ var x__, y__, v__, x_, y_, v_, first;
+ function lineStart() {
+ clip.point = linePoint;
+ if (polygon) polygon.push(ring = []);
+ first = true;
+ v_ = false;
+ x_ = y_ = NaN;
+ }
+ function lineEnd() {
+ if (segments) {
+ linePoint(x__, y__);
+ if (v__ && v_) bufferListener.rejoin();
+ segments.push(bufferListener.buffer());
+ }
+ clip.point = point;
+ if (v_) listener.lineEnd();
+ }
+ function linePoint(x, y) {
+ x = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, x));
+ y = Math.max(-d3_geo_clipViewMAX, Math.min(d3_geo_clipViewMAX, y));
+ var v = visible(x, y);
+ if (polygon) ring.push([ x, y ]);
+ if (first) {
+ x__ = x, y__ = y, v__ = v;
+ first = false;
+ if (v) {
+ listener.lineStart();
+ listener.point(x, y);
+ }
+ } else {
+ if (v && v_) listener.point(x, y); else {
+ var a = [ x_, y_ ], b = [ x, y ];
+ if (clipLine(a, b)) {
+ if (!v_) {
+ listener.lineStart();
+ listener.point(a[0], a[1]);
+ }
+ listener.point(b[0], b[1]);
+ if (!v) listener.lineEnd();
+ } else if (v) {
+ listener.lineStart();
+ listener.point(x, y);
+ }
+ }
+ }
+ x_ = x, y_ = y, v_ = v;
}
+ return clip;
};
- }
- function d3_scale_linearTickRange(domain, m) {
- var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
- if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
- extent[0] = Math.ceil(extent[0] / step) * step;
- extent[1] = Math.floor(extent[1] / step) * step + step * .5;
- extent[2] = step;
- return extent;
- }
- function d3_scale_linearTicks(domain, m) {
- return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
- }
- function d3_scale_linearTickFormat(domain, m) {
- return d3.format(",." + Math.max(0, -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01)) + "f");
- }
- function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
- var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
- return function(x) {
- return i(u(x));
- };
- }
- function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
- var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
- if (domain[k] < domain[0]) {
- domain = domain.slice().reverse();
- range = range.slice().reverse();
+ function corner(p, direction) {
+ return Math.abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : Math.abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : Math.abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
}
- while (++j <= k) {
- u.push(uninterpolate(domain[j - 1], domain[j]));
- i.push(interpolate(range[j - 1], range[j]));
+ function compare(a, b) {
+ return comparePoints(a.point, b.point);
}
- return function(x) {
- var j = d3.bisect(domain, x, 1, k) - 1;
- return i[j](u[j](x));
- };
- }
- d3.scale.log = function() {
- return d3_scale_log(d3.scale.linear(), d3_scale_logp);
- };
- function d3_scale_log(linear, log) {
- var pow = log.pow;
- function scale(x) {
- return linear(log(x));
+ function comparePoints(a, b) {
+ var ca = corner(a, 1), cb = corner(b, 1);
+ return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
}
- scale.invert = function(x) {
- return pow(linear.invert(x));
- };
- scale.domain = function(x) {
- if (!arguments.length) return linear.domain().map(pow);
- log = x[0] < 0 ? d3_scale_logn : d3_scale_logp;
- pow = log.pow;
- linear.domain(x.map(log));
- return scale;
- };
- scale.nice = function() {
- linear.domain(d3_scale_nice(linear.domain(), d3_scale_niceDefault));
- return scale;
- };
- scale.ticks = function() {
- var extent = d3_scaleExtent(linear.domain()), ticks = [];
- if (extent.every(isFinite)) {
- var i = Math.floor(extent[0]), j = Math.ceil(extent[1]), u = pow(extent[0]), v = pow(extent[1]);
- if (log === d3_scale_logn) {
- ticks.push(pow(i));
- for (;i++ < j; ) for (var k = 9; k > 0; k--) ticks.push(pow(i) * k);
- } else {
- for (;i < j; i++) for (var k = 1; k < 10; k++) ticks.push(pow(i) * k);
- ticks.push(pow(i));
+ function clipLine(a, b) {
+ var dx = b[0] - a[0], dy = b[1] - a[1], t = [ 0, 1 ];
+ if (Math.abs(dx) < ε && Math.abs(dy) < ε) return x0 <= a[0] && a[0] <= x1 && y0 <= a[1] && a[1] <= y1;
+ if (d3_geo_clipViewT(x0 - a[0], dx, t) && d3_geo_clipViewT(a[0] - x1, -dx, t) && d3_geo_clipViewT(y0 - a[1], dy, t) && d3_geo_clipViewT(a[1] - y1, -dy, t)) {
+ if (t[1] < 1) {
+ b[0] = a[0] + t[1] * dx;
+ b[1] = a[1] + t[1] * dy;
}
- for (i = 0; ticks[i] < u; i++) {}
- for (j = ticks.length; ticks[j - 1] > v; j--) {}
- ticks = ticks.slice(i, j);
+ if (t[0] > 0) {
+ a[0] += t[0] * dx;
+ a[1] += t[0] * dy;
+ }
+ return true;
}
- return ticks;
- };
- scale.tickFormat = function(n, format) {
- if (arguments.length < 2) format = d3_scale_logFormat;
- if (!arguments.length) return format;
- var k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12,
- Math.floor) : (e = 1e-12, Math.ceil), e;
- return function(d) {
- return d / pow(f(log(d) + e)) <= k ? format(d) : "";
- };
- };
- scale.copy = function() {
- return d3_scale_log(linear.copy(), log);
- };
- return d3_scale_linearRebind(scale, linear);
- }
- var d3_scale_logFormat = d3.format(".0e");
- function d3_scale_logp(x) {
- return Math.log(x < 0 ? 0 : x) / Math.LN10;
+ return false;
+ }
}
- function d3_scale_logn(x) {
- return -Math.log(x > 0 ? 0 : -x) / Math.LN10;
+ function d3_geo_clipViewT(num, denominator, t) {
+ if (Math.abs(denominator) < ε) return num <= 0;
+ var u = num / denominator;
+ if (denominator > 0) {
+ if (u > t[1]) return false;
+ if (u > t[0]) t[0] = u;
+ } else {
+ if (u < t[0]) return false;
+ if (u < t[1]) t[1] = u;
+ }
+ return true;
}
- d3_scale_logp.pow = function(x) {
- return Math.pow(10, x);
- };
- d3_scale_logn.pow = function(x) {
- return -Math.pow(10, -x);
- };
- d3.scale.pow = function() {
- return d3_scale_pow(d3.scale.linear(), 1);
- };
- function d3_scale_pow(linear, exponent) {
- var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
- function scale(x) {
- return linear(powp(x));
+ function d3_geo_compose(a, b) {
+ function compose(x, y) {
+ return x = a(x, y), b(x[0], x[1]);
}
- scale.invert = function(x) {
- return powb(linear.invert(x));
- };
- scale.domain = function(x) {
- if (!arguments.length) return linear.domain().map(powb);
- linear.domain(x.map(powp));
- return scale;
- };
- scale.ticks = function(m) {
- return d3_scale_linearTicks(scale.domain(), m);
- };
- scale.tickFormat = function(m) {
- return d3_scale_linearTickFormat(scale.domain(), m);
- };
- scale.nice = function() {
- return scale.domain(d3_scale_nice(scale.domain(), d3_scale_linearNice));
- };
- scale.exponent = function(x) {
- if (!arguments.length) return exponent;
- var domain = scale.domain();
- powp = d3_scale_powPow(exponent = x);
- powb = d3_scale_powPow(1 / exponent);
- return scale.domain(domain);
- };
- scale.copy = function() {
- return d3_scale_pow(linear.copy(), exponent);
+ if (a.invert && b.invert) compose.invert = function(x, y) {
+ return x = b.invert(x, y), x && a.invert(x[0], x[1]);
};
- return d3_scale_linearRebind(scale, linear);
+ return compose;
}
- function d3_scale_powPow(e) {
- return function(x) {
- return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+ function d3_geo_resample(project) {
+ var δ2 = .5, maxDepth = 16;
+ function resample(stream) {
+ var λ0, x0, y0, a0, b0, c0;
+ var resample = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.polygonStart();
+ resample.lineStart = polygonLineStart;
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ resample.lineStart = lineStart;
+ }
+ };
+ function point(x, y) {
+ x = project(x, y);
+ stream.point(x[0], x[1]);
+ }
+ function lineStart() {
+ x0 = NaN;
+ resample.point = linePoint;
+ stream.lineStart();
+ }
+ function linePoint(λ, φ) {
+ var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
+ stream.point(x0, y0);
+ }
+ function lineEnd() {
+ resample.point = point;
+ stream.lineEnd();
+ }
+ function polygonLineStart() {
+ var λ00, φ00, x00, y00, a00, b00, c00;
+ lineStart();
+ resample.point = function(λ, φ) {
+ linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+ resample.point = linePoint;
+ };
+ resample.lineEnd = function() {
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
+ resample.lineEnd = lineEnd;
+ lineEnd();
+ };
+ }
+ return resample;
+ }
+ function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
+ var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
+ if (d2 > 4 * δ2 && depth--) {
+ var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
+ if (dz * dz / d2 > δ2 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) {
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
+ stream.point(x2, y2);
+ resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+ }
+ }
+ }
+ resample.precision = function(_) {
+ if (!arguments.length) return Math.sqrt(δ2);
+ maxDepth = (δ2 = _ * _) > 0 && 16;
+ return resample;
};
+ return resample;
}
- d3.scale.sqrt = function() {
- return d3.scale.pow().exponent(.5);
- };
- d3.scale.ordinal = function() {
- return d3_scale_ordinal([], {
- t: "range",
- a: [ [] ]
- });
- };
- function d3_scale_ordinal(domain, ranger) {
- var index, range, rangeBand;
- function scale(x) {
- return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];
+ d3.geo.projection = d3_geo_projection;
+ d3.geo.projectionMutator = d3_geo_projectionMutator;
+ function d3_geo_projection(project) {
+ return d3_geo_projectionMutator(function() {
+ return project;
+ })();
+ }
+ function d3_geo_projectionMutator(projectAt) {
+ var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
+ x = project(x, y);
+ return [ x[0] * k + δx, δy - x[1] * k ];
+ }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null;
+ function projection(point) {
+ point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+ return [ point[0] * k + δx, δy - point[1] * k ];
}
- function steps(start, step) {
- return d3.range(domain.length).map(function(i) {
- return start + step * i;
- });
+ function invert(point) {
+ point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
+ return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
}
- scale.domain = function(x) {
- if (!arguments.length) return domain;
- domain = [];
- index = new d3_Map();
- var i = -1, n = x.length, xi;
- while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
- return scale[ranger.t].apply(scale, ranger.a);
+ projection.stream = function(stream) {
+ return d3_geo_projectionRadiansRotate(rotate, preclip(projectResample(postclip(stream))));
};
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- rangeBand = 0;
- ranger = {
- t: "range",
- a: arguments
- };
- return scale;
+ projection.clipAngle = function(_) {
+ if (!arguments.length) return clipAngle;
+ preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+ return projection;
};
- scale.rangePoints = function(x, padding) {
- if (arguments.length < 2) padding = 0;
- var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
- range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
- rangeBand = 0;
- ranger = {
- t: "rangePoints",
- a: arguments
- };
- return scale;
+ projection.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent;
+ clipExtent = _;
+ postclip = _ == null ? d3_identity : d3_geo_clipView(_[0][0], _[0][1], _[1][0], _[1][1]);
+ return projection;
};
- scale.rangeBands = function(x, padding, outerPadding) {
- if (arguments.length < 2) padding = 0;
- if (arguments.length < 3) outerPadding = padding;
- var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
- range = steps(start + step * outerPadding, step);
- if (reverse) range.reverse();
- rangeBand = step * (1 - padding);
- ranger = {
- t: "rangeBands",
- a: arguments
- };
- return scale;
+ projection.scale = function(_) {
+ if (!arguments.length) return k;
+ k = +_;
+ return reset();
};
- scale.rangeRoundBands = function(x, padding, outerPadding) {
- if (arguments.length < 2) padding = 0;
- if (arguments.length < 3) outerPadding = padding;
- var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
- range = steps(start + Math.round(error / 2), step);
- if (reverse) range.reverse();
- rangeBand = Math.round(step * (1 - padding));
- ranger = {
- t: "rangeRoundBands",
- a: arguments
- };
- return scale;
+ projection.translate = function(_) {
+ if (!arguments.length) return [ x, y ];
+ x = +_[0];
+ y = +_[1];
+ return reset();
};
- scale.rangeBand = function() {
- return rangeBand;
+ projection.center = function(_) {
+ if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
+ λ = _[0] % 360 * d3_radians;
+ φ = _[1] % 360 * d3_radians;
+ return reset();
};
- scale.rangeExtent = function() {
- return d3_scaleExtent(ranger.a[0]);
+ projection.rotate = function(_) {
+ if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
+ δλ = _[0] % 360 * d3_radians;
+ δφ = _[1] % 360 * d3_radians;
+ δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
+ return reset();
};
- scale.copy = function() {
- return d3_scale_ordinal(domain, ranger);
+ d3.rebind(projection, projectResample, "precision");
+ function reset() {
+ projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
+ var center = project(λ, φ);
+ δx = x - center[0] * k;
+ δy = y + center[1] * k;
+ return projection;
+ }
+ return function() {
+ project = projectAt.apply(this, arguments);
+ projection.invert = project.invert && invert;
+ return reset();
};
- return scale.domain(domain);
}
- d3.scale.category10 = function() {
- return d3.scale.ordinal().range(d3_category10);
- };
- d3.scale.category20 = function() {
- return d3.scale.ordinal().range(d3_category20);
- };
- d3.scale.category20b = function() {
- return d3.scale.ordinal().range(d3_category20b);
- };
- d3.scale.category20c = function() {
- return d3.scale.ordinal().range(d3_category20c);
- };
- var d3_category10 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ];
- var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ];
- var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ];
- var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ];
- d3.scale.quantile = function() {
- return d3_scale_quantile([], []);
+ function d3_geo_projectionRadiansRotate(rotate, stream) {
+ return {
+ point: function(x, y) {
+ y = rotate(x * d3_radians, y * d3_radians), x = y[0];
+ stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]);
+ },
+ sphere: function() {
+ stream.sphere();
+ },
+ lineStart: function() {
+ stream.lineStart();
+ },
+ lineEnd: function() {
+ stream.lineEnd();
+ },
+ polygonStart: function() {
+ stream.polygonStart();
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ }
+ };
+ }
+ function d3_geo_equirectangular(λ, φ) {
+ return [ λ, φ ];
+ }
+ (d3.geo.equirectangular = function() {
+ return d3_geo_projection(d3_geo_equirectangular);
+ }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
+ d3.geo.rotation = function(rotate) {
+ rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
+ function forward(coordinates) {
+ coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+ return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+ }
+ forward.invert = function(coordinates) {
+ coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+ return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+ };
+ return forward;
};
- function d3_scale_quantile(domain, range) {
- var thresholds;
- function rescale() {
- var k = 0, q = range.length;
- thresholds = [];
- while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
- return scale;
+ function d3_geo_rotation(δλ, δφ, δγ) {
+ return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_equirectangular;
+ }
+ function d3_geo_forwardRotationλ(δλ) {
+ return function(λ, φ) {
+ return λ += δλ, [ λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ ];
+ };
+ }
+ function d3_geo_rotationλ(δλ) {
+ var rotation = d3_geo_forwardRotationλ(δλ);
+ rotation.invert = d3_geo_forwardRotationλ(-δλ);
+ return rotation;
+ }
+ function d3_geo_rotationφγ(δφ, δγ) {
+ var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
+ function rotation(λ, φ) {
+ var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
+ return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδγ + y * sinδγ))) ];
}
- function scale(x) {
- if (isNaN(x = +x)) return NaN;
- return range[d3.bisect(thresholds, x)];
+ rotation.invert = function(λ, φ) {
+ var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
+ return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδφ - x * sinδφ))) ];
+ };
+ return rotation;
+ }
+ d3.geo.circle = function() {
+ var origin = [ 0, 0 ], angle, precision = 6, interpolate;
+ function circle() {
+ var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
+ interpolate(null, null, 1, {
+ point: function(x, y) {
+ ring.push(x = rotate(x, y));
+ x[0] *= d3_degrees, x[1] *= d3_degrees;
+ }
+ });
+ return {
+ type: "Polygon",
+ coordinates: [ ring ]
+ };
}
- scale.domain = function(x) {
- if (!arguments.length) return domain;
- domain = x.filter(function(d) {
- return !isNaN(d);
- }).sort(d3.ascending);
- return rescale();
+ circle.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return circle;
};
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- return rescale();
+ circle.angle = function(x) {
+ if (!arguments.length) return angle;
+ interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+ return circle;
};
- scale.quantiles = function() {
- return thresholds;
+ circle.precision = function(_) {
+ if (!arguments.length) return precision;
+ interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+ return circle;
};
- scale.copy = function() {
- return d3_scale_quantile(domain, range);
+ return circle.angle(90);
+ };
+ function d3_geo_circleInterpolate(radius, precision) {
+ var cr = Math.cos(radius), sr = Math.sin(radius);
+ return function(from, to, direction, listener) {
+ if (from != null) {
+ from = d3_geo_circleAngle(cr, from);
+ to = d3_geo_circleAngle(cr, to);
+ if (direction > 0 ? from < to : from > to) from += direction * 2 * π;
+ } else {
+ from = radius + direction * 2 * π;
+ to = radius;
+ }
+ var point;
+ for (var step = direction * precision, t = from; direction > 0 ? t > to : t < to; t -= step) {
+ listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
+ }
};
- return rescale();
}
- d3.scale.quantize = function() {
- return d3_scale_quantize(0, 1, [ 0, 1 ]);
+ function d3_geo_circleAngle(cr, point) {
+ var a = d3_geo_cartesian(point);
+ a[0] -= cr;
+ d3_geo_cartesianNormalize(a);
+ var angle = d3_acos(-a[1]);
+ return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+ }
+ d3.geo.distance = function(a, b) {
+ var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
+ return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
};
- function d3_scale_quantize(x0, x1, range) {
- var kx, i;
- function scale(x) {
- return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
+ d3.geo.graticule = function() {
+ var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
+ function graticule() {
+ return {
+ type: "MultiLineString",
+ coordinates: lines()
+ };
}
- function rescale() {
- kx = range.length / (x1 - x0);
- i = range.length - 1;
- return scale;
+ function lines() {
+ return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
+ return Math.abs(x % DX) > ε;
+ }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+ return Math.abs(y % DY) > ε;
+ }).map(y));
}
- scale.domain = function(x) {
- if (!arguments.length) return [ x0, x1 ];
- x0 = +x[0];
- x1 = +x[x.length - 1];
- return rescale();
- };
- scale.range = function(x) {
- if (!arguments.length) return range;
- range = x;
- return rescale();
+ graticule.lines = function() {
+ return lines().map(function(coordinates) {
+ return {
+ type: "LineString",
+ coordinates: coordinates
+ };
+ });
};
- scale.copy = function() {
- return d3_scale_quantize(x0, x1, range);
+ graticule.outline = function() {
+ return {
+ type: "Polygon",
+ coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+ };
};
- return rescale();
- }
- d3.scale.threshold = function() {
- return d3_scale_threshold([ .5 ], [ 0, 1 ]);
- };
- function d3_scale_threshold(domain, range) {
- function scale(x) {
- return range[d3.bisect(domain, x)];
- }
- scale.domain = function(_) {
- if (!arguments.length) return domain;
- domain = _;
- return scale;
+ graticule.extent = function(_) {
+ if (!arguments.length) return graticule.minorExtent();
+ return graticule.majorExtent(_).minorExtent(_);
+ };
+ graticule.majorExtent = function(_) {
+ if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
+ X0 = +_[0][0], X1 = +_[1][0];
+ Y0 = +_[0][1], Y1 = +_[1][1];
+ if (X0 > X1) _ = X0, X0 = X1, X1 = _;
+ if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
+ return graticule.precision(precision);
};
- scale.range = function(_) {
- if (!arguments.length) return range;
- range = _;
- return scale;
+ graticule.minorExtent = function(_) {
+ if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+ x0 = +_[0][0], x1 = +_[1][0];
+ y0 = +_[0][1], y1 = +_[1][1];
+ if (x0 > x1) _ = x0, x0 = x1, x1 = _;
+ if (y0 > y1) _ = y0, y0 = y1, y1 = _;
+ return graticule.precision(precision);
};
- scale.copy = function() {
- return d3_scale_threshold(domain, range);
+ graticule.step = function(_) {
+ if (!arguments.length) return graticule.minorStep();
+ return graticule.majorStep(_).minorStep(_);
};
- return scale;
- }
- d3.scale.identity = function() {
- return d3_scale_identity([ 0, 1 ]);
- };
- function d3_scale_identity(domain) {
- function identity(x) {
- return +x;
- }
- identity.invert = identity;
- identity.domain = identity.range = function(x) {
- if (!arguments.length) return domain;
- domain = x.map(identity);
- return identity;
+ graticule.majorStep = function(_) {
+ if (!arguments.length) return [ DX, DY ];
+ DX = +_[0], DY = +_[1];
+ return graticule;
};
- identity.ticks = function(m) {
- return d3_scale_linearTicks(domain, m);
+ graticule.minorStep = function(_) {
+ if (!arguments.length) return [ dx, dy ];
+ dx = +_[0], dy = +_[1];
+ return graticule;
};
- identity.tickFormat = function(m) {
- return d3_scale_linearTickFormat(domain, m);
+ graticule.precision = function(_) {
+ if (!arguments.length) return precision;
+ precision = +_;
+ x = d3_geo_graticuleX(y0, y1, 90);
+ y = d3_geo_graticuleY(x0, x1, precision);
+ X = d3_geo_graticuleX(Y0, Y1, 90);
+ Y = d3_geo_graticuleY(X0, X1, precision);
+ return graticule;
};
- identity.copy = function() {
- return d3_scale_identity(domain);
+ return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
+ };
+ function d3_geo_graticuleX(y0, y1, dy) {
+ var y = d3.range(y0, y1 - ε, dy).concat(y1);
+ return function(x) {
+ return y.map(function(y) {
+ return [ x, y ];
+ });
};
- return identity;
}
- d3.svg = {};
- d3.svg.arc = function() {
- var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
- function arc() {
- var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0,
- a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
- return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
- }
- arc.innerRadius = function(v) {
- if (!arguments.length) return innerRadius;
- innerRadius = d3_functor(v);
- return arc;
+ function d3_geo_graticuleY(x0, x1, dx) {
+ var x = d3.range(x0, x1 - ε, dx).concat(x1);
+ return function(y) {
+ return x.map(function(x) {
+ return [ x, y ];
+ });
};
- arc.outerRadius = function(v) {
- if (!arguments.length) return outerRadius;
- outerRadius = d3_functor(v);
- return arc;
+ }
+ function d3_source(d) {
+ return d.source;
+ }
+ function d3_target(d) {
+ return d.target;
+ }
+ d3.geo.greatArc = function() {
+ var source = d3_source, source_, target = d3_target, target_;
+ function greatArc() {
+ return {
+ type: "LineString",
+ coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
+ };
+ }
+ greatArc.distance = function() {
+ return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
};
- arc.startAngle = function(v) {
- if (!arguments.length) return startAngle;
- startAngle = d3_functor(v);
- return arc;
+ greatArc.source = function(_) {
+ if (!arguments.length) return source;
+ source = _, source_ = typeof _ === "function" ? null : _;
+ return greatArc;
};
- arc.endAngle = function(v) {
- if (!arguments.length) return endAngle;
- endAngle = d3_functor(v);
- return arc;
+ greatArc.target = function(_) {
+ if (!arguments.length) return target;
+ target = _, target_ = typeof _ === "function" ? null : _;
+ return greatArc;
};
- arc.centroid = function() {
- var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
- return [ Math.cos(a) * r, Math.sin(a) * r ];
+ greatArc.precision = function() {
+ return arguments.length ? greatArc : 0;
};
- return arc;
+ return greatArc;
};
- var d3_svg_arcOffset = -π / 2, d3_svg_arcMax = 2 * π - 1e-6;
- function d3_svg_arcInnerRadius(d) {
- return d.innerRadius;
+ d3.geo.interpolate = function(source, target) {
+ return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
+ };
+ function d3_geo_interpolate(x0, y0, x1, y1) {
+ var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
+ var interpolate = d ? function(t) {
+ var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
+ return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
+ } : function() {
+ return [ x0 * d3_degrees, y0 * d3_degrees ];
+ };
+ interpolate.distance = d;
+ return interpolate;
}
- function d3_svg_arcOuterRadius(d) {
- return d.outerRadius;
+ d3.geo.length = function(object) {
+ d3_geo_lengthSum = 0;
+ d3.geo.stream(object, d3_geo_length);
+ return d3_geo_lengthSum;
+ };
+ var d3_geo_lengthSum;
+ var d3_geo_length = {
+ sphere: d3_noop,
+ point: d3_noop,
+ lineStart: d3_geo_lengthLineStart,
+ lineEnd: d3_noop,
+ polygonStart: d3_noop,
+ polygonEnd: d3_noop
+ };
+ function d3_geo_lengthLineStart() {
+ var λ0, sinφ0, cosφ0;
+ d3_geo_length.point = function(λ, φ) {
+ λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
+ d3_geo_length.point = nextPoint;
+ };
+ d3_geo_length.lineEnd = function() {
+ d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
+ };
+ function nextPoint(λ, φ) {
+ var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = Math.abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
+ d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
+ λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
+ }
}
- function d3_svg_arcStartAngle(d) {
- return d.startAngle;
+ function d3_geo_conic(projectAt) {
+ var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
+ p.parallels = function(_) {
+ if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
+ return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
+ };
+ return p;
}
- function d3_svg_arcEndAngle(d) {
- return d.endAngle;
+ function d3_geo_conicEqualArea(φ0, φ1) {
+ var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
+ function forward(λ, φ) {
+ var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
+ return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = ρ0 - y;
+ return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
+ };
+ return forward;
}
- function d3_svg_line(projection) {
- var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
- function line(data) {
- var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
- function segment() {
- segments.push("M", interpolate(projection(points), tension));
- }
- while (++i < n) {
- if (defined.call(this, d = data[i], i)) {
- points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
- } else if (points.length) {
- segment();
- points = [];
- }
+ (d3.geo.conicEqualArea = function() {
+ return d3_geo_conic(d3_geo_conicEqualArea);
+ }).raw = d3_geo_conicEqualArea;
+ d3.geo.albers = function() {
+ return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
+ };
+ d3.geo.albersUsa = function() {
+ var lower48 = d3.geo.albers();
+ var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
+ var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
+ var point, pointStream = {
+ point: function(x, y) {
+ point = [ x, y ];
}
- if (points.length) segment();
- return segments.length ? segments.join("") : null;
+ }, lower48Point, alaskaPoint, hawaiiPoint;
+ function albersUsa(coordinates) {
+ var x = coordinates[0], y = coordinates[1];
+ point = null;
+ (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
+ return point;
}
- line.x = function(_) {
- if (!arguments.length) return x;
- x = _;
- return line;
+ albersUsa.invert = function(coordinates) {
+ var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
+ return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
};
- line.y = function(_) {
- if (!arguments.length) return y;
- y = _;
- return line;
+ albersUsa.stream = function(stream) {
+ var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
+ return {
+ point: function(x, y) {
+ lower48Stream.point(x, y);
+ alaskaStream.point(x, y);
+ hawaiiStream.point(x, y);
+ },
+ sphere: function() {
+ lower48Stream.sphere();
+ alaskaStream.sphere();
+ hawaiiStream.sphere();
+ },
+ lineStart: function() {
+ lower48Stream.lineStart();
+ alaskaStream.lineStart();
+ hawaiiStream.lineStart();
+ },
+ lineEnd: function() {
+ lower48Stream.lineEnd();
+ alaskaStream.lineEnd();
+ hawaiiStream.lineEnd();
+ },
+ polygonStart: function() {
+ lower48Stream.polygonStart();
+ alaskaStream.polygonStart();
+ hawaiiStream.polygonStart();
+ },
+ polygonEnd: function() {
+ lower48Stream.polygonEnd();
+ alaskaStream.polygonEnd();
+ hawaiiStream.polygonEnd();
+ }
+ };
};
- line.defined = function(_) {
- if (!arguments.length) return defined;
- defined = _;
- return line;
+ albersUsa.precision = function(_) {
+ if (!arguments.length) return lower48.precision();
+ lower48.precision(_);
+ alaska.precision(_);
+ hawaii.precision(_);
+ return albersUsa;
};
- line.interpolate = function(_) {
- if (!arguments.length) return interpolateKey;
- if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
- return line;
+ albersUsa.scale = function(_) {
+ if (!arguments.length) return lower48.scale();
+ lower48.scale(_);
+ alaska.scale(_ * .35);
+ hawaii.scale(_);
+ return albersUsa.translate(lower48.translate());
};
- line.tension = function(_) {
- if (!arguments.length) return tension;
- tension = _;
- return line;
+ albersUsa.translate = function(_) {
+ if (!arguments.length) return lower48.translate();
+ var k = lower48.scale(), x = +_[0], y = +_[1];
+ lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
+ alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+ hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+ return albersUsa;
};
- return line;
- }
- d3.svg.line = function() {
- return d3_svg_line(d3_identity);
+ return albersUsa.scale(1070);
};
- function d3_svg_lineX(d) {
- return d[0];
- }
- function d3_svg_lineY(d) {
- return d[1];
- }
- var d3_svg_lineInterpolators = d3.map({
- linear: d3_svg_lineLinear,
- "linear-closed": d3_svg_lineLinearClosed,
- "step-before": d3_svg_lineStepBefore,
- "step-after": d3_svg_lineStepAfter,
- basis: d3_svg_lineBasis,
- "basis-open": d3_svg_lineBasisOpen,
- "basis-closed": d3_svg_lineBasisClosed,
- bundle: d3_svg_lineBundle,
- cardinal: d3_svg_lineCardinal,
- "cardinal-open": d3_svg_lineCardinalOpen,
- "cardinal-closed": d3_svg_lineCardinalClosed,
- monotone: d3_svg_lineMonotone
- });
- d3_svg_lineInterpolators.forEach(function(key, value) {
- value.key = key;
- value.closed = /-closed$/.test(key);
- });
- function d3_svg_lineLinear(points) {
- return points.join("L");
- }
- function d3_svg_lineLinearClosed(points) {
- return d3_svg_lineLinear(points) + "Z";
- }
- function d3_svg_lineStepBefore(points) {
- var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
- while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
- return path.join("");
- }
- function d3_svg_lineStepAfter(points) {
- var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
- while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
- return path.join("");
- }
- function d3_svg_lineCardinalOpen(points, tension) {
- return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
- }
- function d3_svg_lineCardinalClosed(points, tension) {
- return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]),
- points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+ var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
+ point: d3_noop,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: function() {
+ d3_geo_pathAreaPolygon = 0;
+ d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
+ d3_geo_pathAreaSum += Math.abs(d3_geo_pathAreaPolygon / 2);
+ }
+ };
+ function d3_geo_pathAreaRingStart() {
+ var x00, y00, x0, y0;
+ d3_geo_pathArea.point = function(x, y) {
+ d3_geo_pathArea.point = nextPoint;
+ x00 = x0 = x, y00 = y0 = y;
+ };
+ function nextPoint(x, y) {
+ d3_geo_pathAreaPolygon += y0 * x - x0 * y;
+ x0 = x, y0 = y;
+ }
+ d3_geo_pathArea.lineEnd = function() {
+ nextPoint(x00, y00);
+ };
}
- function d3_svg_lineCardinal(points, tension) {
- return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+ var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
+ var d3_geo_pathBounds = {
+ point: d3_geo_pathBoundsPoint,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: d3_noop,
+ polygonEnd: d3_noop
+ };
+ function d3_geo_pathBoundsPoint(x, y) {
+ if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
+ if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
+ if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
+ if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
}
- function d3_svg_lineHermite(points, tangents) {
- if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
- return d3_svg_lineLinear(points);
+ function d3_geo_pathBuffer() {
+ var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
+ var stream = {
+ point: point,
+ lineStart: function() {
+ stream.point = pointLineStart;
+ },
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.lineEnd = lineEndPolygon;
+ },
+ polygonEnd: function() {
+ stream.lineEnd = lineEnd;
+ stream.point = point;
+ },
+ pointRadius: function(_) {
+ pointCircle = d3_geo_pathBufferCircle(_);
+ return stream;
+ },
+ result: function() {
+ if (buffer.length) {
+ var result = buffer.join("");
+ buffer = [];
+ return result;
+ }
+ }
+ };
+ function point(x, y) {
+ buffer.push("M", x, ",", y, pointCircle);
}
- var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
- if (quad) {
- path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
- p0 = points[1];
- pi = 2;
+ function pointLineStart(x, y) {
+ buffer.push("M", x, ",", y);
+ stream.point = pointLine;
}
- if (tangents.length > 1) {
- t = tangents[1];
- p = points[pi];
- pi++;
- path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
- for (var i = 2; i < tangents.length; i++, pi++) {
- p = points[pi];
- t = tangents[i];
- path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
- }
+ function pointLine(x, y) {
+ buffer.push("L", x, ",", y);
}
- if (quad) {
- var lp = points[pi];
- path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
+ function lineEnd() {
+ stream.point = point;
}
- return path;
+ function lineEndPolygon() {
+ buffer.push("Z");
+ }
+ return stream;
}
- function d3_svg_lineCardinalTangents(points, tension) {
- var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
- while (++i < n) {
- p0 = p1;
- p1 = p2;
- p2 = points[i];
- tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
+ function d3_geo_pathBufferCircle(radius) {
+ return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
+ }
+ var d3_geo_pathCentroid = {
+ point: d3_geo_pathCentroidPoint,
+ lineStart: d3_geo_pathCentroidLineStart,
+ lineEnd: d3_geo_pathCentroidLineEnd,
+ polygonStart: function() {
+ d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
+ d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
}
- return tangents;
+ };
+ function d3_geo_pathCentroidPoint(x, y) {
+ if (d3_geo_centroidDimension) return;
+ d3_geo_centroidX += x;
+ d3_geo_centroidY += y;
+ ++d3_geo_centroidZ;
}
- function d3_svg_lineBasis(points) {
- if (points.length < 3) return d3_svg_lineLinear(points);
- var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0 ];
- d3_svg_lineBasisBezier(path, px, py);
- while (++i < n) {
- pi = points[i];
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ function d3_geo_pathCentroidLineStart() {
+ var x0, y0;
+ if (d3_geo_centroidDimension !== 1) {
+ if (d3_geo_centroidDimension < 1) {
+ d3_geo_centroidDimension = 1;
+ d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ } else return;
}
- i = -1;
- while (++i < 2) {
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ x0 = x, y0 = y;
+ };
+ function nextPoint(x, y) {
+ var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+ d3_geo_centroidX += z * (x0 + x) / 2;
+ d3_geo_centroidY += z * (y0 + y) / 2;
+ d3_geo_centroidZ += z;
+ x0 = x, y0 = y;
}
- return path.join("");
}
- function d3_svg_lineBasisOpen(points) {
- if (points.length < 4) return d3_svg_lineLinear(points);
- var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
- while (++i < 3) {
- pi = points[i];
- px.push(pi[0]);
- py.push(pi[1]);
+ function d3_geo_pathCentroidLineEnd() {
+ d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ }
+ function d3_geo_pathCentroidRingStart() {
+ var x00, y00, x0, y0;
+ if (d3_geo_centroidDimension < 2) {
+ d3_geo_centroidDimension = 2;
+ d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
}
- path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
- --i;
- while (++i < n) {
- pi = points[i];
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ x00 = x0 = x, y00 = y0 = y;
+ };
+ function nextPoint(x, y) {
+ var z = y0 * x - x0 * y;
+ d3_geo_centroidX += z * (x0 + x);
+ d3_geo_centroidY += z * (y0 + y);
+ d3_geo_centroidZ += z * 3;
+ x0 = x, y0 = y;
}
- return path.join("");
+ d3_geo_pathCentroid.lineEnd = function() {
+ nextPoint(x00, y00);
+ };
}
- function d3_svg_lineBasisClosed(points) {
- var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
- while (++i < 4) {
- pi = points[i % n];
- px.push(pi[0]);
- py.push(pi[1]);
+ function d3_geo_pathContext(context) {
+ var pointRadius = 4.5;
+ var stream = {
+ point: point,
+ lineStart: function() {
+ stream.point = pointLineStart;
+ },
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.lineEnd = lineEndPolygon;
+ },
+ polygonEnd: function() {
+ stream.lineEnd = lineEnd;
+ stream.point = point;
+ },
+ pointRadius: function(_) {
+ pointRadius = _;
+ return stream;
+ },
+ result: d3_noop
+ };
+ function point(x, y) {
+ context.moveTo(x, y);
+ context.arc(x, y, pointRadius, 0, 2 * π);
}
- path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
- --i;
- while (++i < m) {
- pi = points[i % n];
- px.shift();
- px.push(pi[0]);
- py.shift();
- py.push(pi[1]);
- d3_svg_lineBasisBezier(path, px, py);
+ function pointLineStart(x, y) {
+ context.moveTo(x, y);
+ stream.point = pointLine;
}
- return path.join("");
+ function pointLine(x, y) {
+ context.lineTo(x, y);
+ }
+ function lineEnd() {
+ stream.point = point;
+ }
+ function lineEndPolygon() {
+ context.closePath();
+ }
+ return stream;
+ }
+ d3.geo.path = function() {
+ var pointRadius = 4.5, projection, context, projectStream, contextStream;
+ function path(object) {
+ if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius)));
+ return contextStream.result();
+ }
+ path.area = function(object) {
+ d3_geo_pathAreaSum = 0;
+ d3.geo.stream(object, projectStream(d3_geo_pathArea));
+ return d3_geo_pathAreaSum;
+ };
+ path.centroid = function(object) {
+ d3_geo_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+ return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined;
+ };
+ path.bounds = function(object) {
+ d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
+ d3.geo.stream(object, projectStream(d3_geo_pathBounds));
+ return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
+ };
+ path.projection = function(_) {
+ if (!arguments.length) return projection;
+ projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
+ return path;
+ };
+ path.context = function(_) {
+ if (!arguments.length) return context;
+ contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+ return path;
+ };
+ path.pointRadius = function(_) {
+ if (!arguments.length) return pointRadius;
+ pointRadius = typeof _ === "function" ? _ : +_;
+ return path;
+ };
+ return path.projection(d3.geo.albersUsa()).context(null);
+ };
+ function d3_geo_pathProjectStream(project) {
+ var resample = d3_geo_resample(function(λ, φ) {
+ return project([ λ * d3_degrees, φ * d3_degrees ]);
+ });
+ return function(stream) {
+ stream = resample(stream);
+ return {
+ point: function(λ, φ) {
+ stream.point(λ * d3_radians, φ * d3_radians);
+ },
+ sphere: function() {
+ stream.sphere();
+ },
+ lineStart: function() {
+ stream.lineStart();
+ },
+ lineEnd: function() {
+ stream.lineEnd();
+ },
+ polygonStart: function() {
+ stream.polygonStart();
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ }
+ };
+ };
}
- function d3_svg_lineBundle(points, tension) {
- var n = points.length - 1;
- if (n) {
- var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
- while (++i <= n) {
- p = points[i];
- t = i / n;
- p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
- p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
- }
+ function d3_geo_azimuthal(scale, angle) {
+ function azimuthal(λ, φ) {
+ var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
+ return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
}
- return d3_svg_lineBasis(points);
- }
- function d3_svg_lineDot4(a, b) {
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
- }
- var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
- function d3_svg_lineBasisBezier(path, x, y) {
- path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
- }
- function d3_svg_lineSlope(p0, p1) {
- return (p1[1] - p0[1]) / (p1[0] - p0[0]);
+ azimuthal.invert = function(x, y) {
+ var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
+ return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
+ };
+ return azimuthal;
}
- function d3_svg_lineFiniteDifferences(points) {
- var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
- while (++i < j) {
- m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
- }
- m[i] = d;
- return m;
+ var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
+ return Math.sqrt(2 / (1 + cosλcosφ));
+ }, function(ρ) {
+ return 2 * Math.asin(ρ / 2);
+ });
+ (d3.geo.azimuthalEqualArea = function() {
+ return d3_geo_projection(d3_geo_azimuthalEqualArea);
+ }).raw = d3_geo_azimuthalEqualArea;
+ var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
+ var c = Math.acos(cosλcosφ);
+ return c && c / Math.sin(c);
+ }, d3_identity);
+ (d3.geo.azimuthalEquidistant = function() {
+ return d3_geo_projection(d3_geo_azimuthalEquidistant);
+ }).raw = d3_geo_azimuthalEquidistant;
+ function d3_geo_conicConformal(φ0, φ1) {
+ var cosφ0 = Math.cos(φ0), t = function(φ) {
+ return Math.tan(π / 4 + φ / 2);
+ }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
+ if (!n) return d3_geo_mercator;
+ function forward(λ, φ) {
+ var ρ = Math.abs(Math.abs(φ) - π / 2) < ε ? 0 : F / Math.pow(t(φ), n);
+ return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
+ return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - π / 2 ];
+ };
+ return forward;
+ }
+ (d3.geo.conicConformal = function() {
+ return d3_geo_conic(d3_geo_conicConformal);
+ }).raw = d3_geo_conicConformal;
+ function d3_geo_conicEquidistant(φ0, φ1) {
+ var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
+ if (Math.abs(n) < ε) return d3_geo_equirectangular;
+ function forward(λ, φ) {
+ var ρ = G - φ;
+ return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = G - y;
+ return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
+ };
+ return forward;
+ }
+ (d3.geo.conicEquidistant = function() {
+ return d3_geo_conic(d3_geo_conicEquidistant);
+ }).raw = d3_geo_conicEquidistant;
+ var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
+ return 1 / cosλcosφ;
+ }, Math.atan);
+ (d3.geo.gnomonic = function() {
+ return d3_geo_projection(d3_geo_gnomonic);
+ }).raw = d3_geo_gnomonic;
+ function d3_geo_mercator(λ, φ) {
+ return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
}
- function d3_svg_lineMonotoneTangents(points) {
- var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
- while (++i < j) {
- d = d3_svg_lineSlope(points[i], points[i + 1]);
- if (Math.abs(d) < 1e-6) {
- m[i] = m[i + 1] = 0;
- } else {
- a = m[i] / d;
- b = m[i + 1] / d;
- s = a * a + b * b;
- if (s > 9) {
- s = d * 3 / Math.sqrt(s);
- m[i] = s * a;
- m[i + 1] = s * b;
+ d3_geo_mercator.invert = function(x, y) {
+ return [ x, 2 * Math.atan(Math.exp(y)) - π / 2 ];
+ };
+ function d3_geo_mercatorProjection(project) {
+ var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
+ m.scale = function() {
+ var v = scale.apply(m, arguments);
+ return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+ };
+ m.translate = function() {
+ var v = translate.apply(m, arguments);
+ return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+ };
+ m.clipExtent = function(_) {
+ var v = clipExtent.apply(m, arguments);
+ if (v === m) {
+ if (clipAuto = _ == null) {
+ var k = π * scale(), t = translate();
+ clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
}
+ } else if (clipAuto) {
+ v = null;
}
- }
- i = -1;
- while (++i <= j) {
- s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
- tangents.push([ s || 0, m[i] * s || 0 ]);
- }
- return tangents;
+ return v;
+ };
+ return m.clipExtent(null);
}
- function d3_svg_lineMonotone(points) {
- return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+ (d3.geo.mercator = function() {
+ return d3_geo_mercatorProjection(d3_geo_mercator);
+ }).raw = d3_geo_mercator;
+ var d3_geo_orthographic = d3_geo_azimuthal(function() {
+ return 1;
+ }, Math.asin);
+ (d3.geo.orthographic = function() {
+ return d3_geo_projection(d3_geo_orthographic);
+ }).raw = d3_geo_orthographic;
+ var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
+ return 1 / (1 + cosλcosφ);
+ }, function(ρ) {
+ return 2 * Math.atan(ρ);
+ });
+ (d3.geo.stereographic = function() {
+ return d3_geo_projection(d3_geo_stereographic);
+ }).raw = d3_geo_stereographic;
+ function d3_geo_transverseMercator(λ, φ) {
+ var B = Math.cos(φ) * Math.sin(λ);
+ return [ Math.log((1 + B) / (1 - B)) / 2, Math.atan2(Math.tan(φ), Math.cos(λ)) ];
}
- d3.svg.line.radial = function() {
- var line = d3_svg_line(d3_svg_lineRadial);
- line.radius = line.x, delete line.x;
- line.angle = line.y, delete line.y;
- return line;
+ d3_geo_transverseMercator.invert = function(x, y) {
+ return [ Math.atan2(d3_sinh(x), Math.cos(y)), d3_asin(Math.sin(y) / d3_cosh(x)) ];
};
- function d3_svg_lineRadial(points) {
- var point, i = -1, n = points.length, r, a;
- while (++i < n) {
- point = points[i];
- r = point[0];
- a = point[1] + d3_svg_arcOffset;
- point[0] = r * Math.cos(a);
- point[1] = r * Math.sin(a);
- }
- return points;
- }
- function d3_svg_area(projection) {
- var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
- function area(data) {
- var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
- return x;
- } : d3_functor(x1), fy1 = y0 === y1 ? function() {
- return y;
- } : d3_functor(y1), x, y;
+ (d3.geo.transverseMercator = function() {
+ return d3_geo_mercatorProjection(d3_geo_transverseMercator);
+ }).raw = d3_geo_transverseMercator;
+ d3.geom = {};
+ d3.svg = {};
+ function d3_svg_line(projection) {
+ var x = d3_svg_lineX, y = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
+ function line(data) {
+ var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
function segment() {
- segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+ segments.push("M", interpolate(projection(points), tension));
}
while (++i < n) {
if (defined.call(this, d = data[i], i)) {
- points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
- points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
- } else if (points0.length) {
+ points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+ } else if (points.length) {
segment();
- points0 = [];
- points1 = [];
+ points = [];
}
}
- if (points0.length) segment();
+ if (points.length) segment();
return segments.length ? segments.join("") : null;
}
- area.x = function(_) {
- if (!arguments.length) return x1;
- x0 = x1 = _;
- return area;
- };
- area.x0 = function(_) {
- if (!arguments.length) return x0;
- x0 = _;
- return area;
- };
- area.x1 = function(_) {
- if (!arguments.length) return x1;
- x1 = _;
- return area;
- };
- area.y = function(_) {
- if (!arguments.length) return y1;
- y0 = y1 = _;
- return area;
- };
- area.y0 = function(_) {
- if (!arguments.length) return y0;
- y0 = _;
- return area;
+ line.x = function(_) {
+ if (!arguments.length) return x;
+ x = _;
+ return line;
};
- area.y1 = function(_) {
- if (!arguments.length) return y1;
- y1 = _;
- return area;
+ line.y = function(_) {
+ if (!arguments.length) return y;
+ y = _;
+ return line;
};
- area.defined = function(_) {
+ line.defined = function(_) {
if (!arguments.length) return defined;
defined = _;
- return area;
+ return line;
};
- area.interpolate = function(_) {
+ line.interpolate = function(_) {
if (!arguments.length) return interpolateKey;
if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
- interpolateReverse = interpolate.reverse || interpolate;
- L = interpolate.closed ? "M" : "L";
- return area;
+ return line;
};
- area.tension = function(_) {
+ line.tension = function(_) {
if (!arguments.length) return tension;
tension = _;
- return area;
+ return line;
};
- return area;
+ return line;
+ }
+ d3.svg.line = function() {
+ return d3_svg_line(d3_identity);
+ };
+ function d3_svg_lineX(d) {
+ return d[0];
+ }
+ function d3_svg_lineY(d) {
+ return d[1];
+ }
+ var d3_svg_lineInterpolators = d3.map({
+ linear: d3_svg_lineLinear,
+ "linear-closed": d3_svg_lineLinearClosed,
+ "step-before": d3_svg_lineStepBefore,
+ "step-after": d3_svg_lineStepAfter,
+ basis: d3_svg_lineBasis,
+ "basis-open": d3_svg_lineBasisOpen,
+ "basis-closed": d3_svg_lineBasisClosed,
+ bundle: d3_svg_lineBundle,
+ cardinal: d3_svg_lineCardinal,
+ "cardinal-open": d3_svg_lineCardinalOpen,
+ "cardinal-closed": d3_svg_lineCardinalClosed,
+ monotone: d3_svg_lineMonotone
+ });
+ d3_svg_lineInterpolators.forEach(function(key, value) {
+ value.key = key;
+ value.closed = /-closed$/.test(key);
+ });
+ function d3_svg_lineLinear(points) {
+ return points.join("L");
}
- d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
- d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
- d3.svg.area = function() {
- return d3_svg_area(d3_identity);
- };
- d3.svg.area.radial = function() {
- var area = d3_svg_area(d3_svg_lineRadial);
- area.radius = area.x, delete area.x;
- area.innerRadius = area.x0, delete area.x0;
- area.outerRadius = area.x1, delete area.x1;
- area.angle = area.y, delete area.y;
- area.startAngle = area.y0, delete area.y0;
- area.endAngle = area.y1, delete area.y1;
- return area;
- };
- d3.svg.chord = function() {
- var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
- function chord(d, i) {
- var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
- return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
+ function d3_svg_lineLinearClosed(points) {
+ return d3_svg_lineLinear(points) + "Z";
+ }
+ function d3_svg_lineStepBefore(points) {
+ var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+ while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
+ return path.join("");
+ }
+ function d3_svg_lineStepAfter(points) {
+ var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+ while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
+ return path.join("");
+ }
+ function d3_svg_lineCardinalOpen(points, tension) {
+ return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
+ }
+ function d3_svg_lineCardinalClosed(points, tension) {
+ return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]),
+ points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+ }
+ function d3_svg_lineCardinal(points, tension) {
+ return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+ }
+ function d3_svg_lineHermite(points, tangents) {
+ if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
+ return d3_svg_lineLinear(points);
}
- function subgroup(self, f, d, i) {
- var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
- return {
- r: r,
- a0: a0,
- a1: a1,
- p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
- p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
- };
+ var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
+ if (quad) {
+ path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
+ p0 = points[1];
+ pi = 2;
}
- function equals(a, b) {
- return a.a0 == b.a0 && a.a1 == b.a1;
+ if (tangents.length > 1) {
+ t = tangents[1];
+ p = points[pi];
+ pi++;
+ path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+ for (var i = 2; i < tangents.length; i++, pi++) {
+ p = points[pi];
+ t = tangents[i];
+ path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+ }
}
- function arc(r, p, a) {
- return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
+ if (quad) {
+ var lp = points[pi];
+ path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
}
- function curve(r0, p0, r1, p1) {
- return "Q 0,0 " + p1;
+ return path;
+ }
+ function d3_svg_lineCardinalTangents(points, tension) {
+ var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
+ while (++i < n) {
+ p0 = p1;
+ p1 = p2;
+ p2 = points[i];
+ tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
}
- chord.radius = function(v) {
- if (!arguments.length) return radius;
- radius = d3_functor(v);
- return chord;
- };
- chord.source = function(v) {
- if (!arguments.length) return source;
- source = d3_functor(v);
- return chord;
- };
- chord.target = function(v) {
- if (!arguments.length) return target;
- target = d3_functor(v);
- return chord;
- };
- chord.startAngle = function(v) {
- if (!arguments.length) return startAngle;
- startAngle = d3_functor(v);
- return chord;
- };
- chord.endAngle = function(v) {
- if (!arguments.length) return endAngle;
- endAngle = d3_functor(v);
- return chord;
- };
- return chord;
- };
- function d3_svg_chordRadius(d) {
- return d.radius;
+ return tangents;
}
- d3.svg.diagonal = function() {
- var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
- function diagonal(d, i) {
- var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
- x: p0.x,
- y: m
- }, {
- x: p3.x,
- y: m
- }, p3 ];
- p = p.map(projection);
- return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
+ function d3_svg_lineBasis(points) {
+ if (points.length < 3) return d3_svg_lineLinear(points);
+ var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0 ];
+ d3_svg_lineBasisBezier(path, px, py);
+ while (++i < n) {
+ pi = points[i];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
}
- diagonal.source = function(x) {
- if (!arguments.length) return source;
- source = d3_functor(x);
- return diagonal;
- };
- diagonal.target = function(x) {
- if (!arguments.length) return target;
- target = d3_functor(x);
- return diagonal;
- };
- diagonal.projection = function(x) {
- if (!arguments.length) return projection;
- projection = x;
- return diagonal;
- };
- return diagonal;
- };
- function d3_svg_diagonalProjection(d) {
- return [ d.x, d.y ];
+ i = -1;
+ while (++i < 2) {
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
}
- d3.svg.diagonal.radial = function() {
- var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
- diagonal.projection = function(x) {
- return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
- };
- return diagonal;
- };
- function d3_svg_diagonalRadialProjection(projection) {
- return function() {
- var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
- return [ r * Math.cos(a), r * Math.sin(a) ];
- };
+ function d3_svg_lineBasisOpen(points) {
+ if (points.length < 4) return d3_svg_lineLinear(points);
+ var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
+ while (++i < 3) {
+ pi = points[i];
+ px.push(pi[0]);
+ py.push(pi[1]);
+ }
+ path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
+ --i;
+ while (++i < n) {
+ pi = points[i];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
}
- d3.svg.symbol = function() {
- var type = d3_svg_symbolType, size = d3_svg_symbolSize;
- function symbol(d, i) {
- return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
+ function d3_svg_lineBasisClosed(points) {
+ var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
+ while (++i < 4) {
+ pi = points[i % n];
+ px.push(pi[0]);
+ py.push(pi[1]);
}
- symbol.type = function(x) {
- if (!arguments.length) return type;
- type = d3_functor(x);
- return symbol;
- };
- symbol.size = function(x) {
- if (!arguments.length) return size;
- size = d3_functor(x);
- return symbol;
- };
- return symbol;
- };
- function d3_svg_symbolSize() {
- return 64;
+ path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+ --i;
+ while (++i < m) {
+ pi = points[i % n];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
+ }
+ function d3_svg_lineBundle(points, tension) {
+ var n = points.length - 1;
+ if (n) {
+ var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
+ while (++i <= n) {
+ p = points[i];
+ t = i / n;
+ p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
+ p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
+ }
+ }
+ return d3_svg_lineBasis(points);
+ }
+ function d3_svg_lineDot4(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}
- function d3_svg_symbolType() {
- return "circle";
+ var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
+ function d3_svg_lineBasisBezier(path, x, y) {
+ path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
}
- function d3_svg_symbolCircle(size) {
- var r = Math.sqrt(size / π);
- return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
+ function d3_svg_lineSlope(p0, p1) {
+ return (p1[1] - p0[1]) / (p1[0] - p0[0]);
}
- var d3_svg_symbols = d3.map({
- circle: d3_svg_symbolCircle,
- cross: function(size) {
- var r = Math.sqrt(size / 5) / 2;
- return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
- },
- diamond: function(size) {
- var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
- return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
- },
- square: function(size) {
- var r = Math.sqrt(size) / 2;
- return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
- },
- "triangle-down": function(size) {
- var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
- return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
- },
- "triangle-up": function(size) {
- var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
- return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
+ function d3_svg_lineFiniteDifferences(points) {
+ var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
+ while (++i < j) {
+ m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
}
- });
- d3.svg.symbolTypes = d3_svg_symbols.keys();
- var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
- d3.svg.axis = function() {
- var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;
- function axis(g) {
- g.each(function() {
- var g = d3.select(this);
- var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;
- var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".tick.minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", ".tick").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1);
- var tick = g.selectAll(".tick.major").data(ticks, String), tickEnter = tick.enter().insert("g", "path").attr("class", "tick major").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
- var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
- d3.transition(path));
- var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;
- this.__chart__ = scale1;
- tickEnter.append("line");
- tickEnter.append("text");
- var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
- switch (orient) {
- case "bottom":
- {
- tickTransform = d3_svg_axisX;
- subtickEnter.attr("y2", tickMinorSize);
- subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
- lineEnter.attr("y2", tickMajorSize);
- textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding);
- lineUpdate.attr("x2", 0).attr("y2", tickMajorSize);
- textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding);
- text.attr("dy", ".71em").style("text-anchor", "middle");
- pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
- break;
- }
-
- case "top":
- {
- tickTransform = d3_svg_axisX;
- subtickEnter.attr("y2", -tickMinorSize);
- subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
- lineEnter.attr("y2", -tickMajorSize);
- textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
- lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize);
- textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
- text.attr("dy", "0em").style("text-anchor", "middle");
- pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
- break;
- }
-
- case "left":
- {
- tickTransform = d3_svg_axisY;
- subtickEnter.attr("x2", -tickMinorSize);
- subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
- lineEnter.attr("x2", -tickMajorSize);
- textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding));
- lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0);
- textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0);
- text.attr("dy", ".32em").style("text-anchor", "end");
- pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
- break;
- }
-
- case "right":
- {
- tickTransform = d3_svg_axisY;
- subtickEnter.attr("x2", tickMinorSize);
- subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
- lineEnter.attr("x2", tickMajorSize);
- textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding);
- lineUpdate.attr("x2", tickMajorSize).attr("y2", 0);
- textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0);
- text.attr("dy", ".32em").style("text-anchor", "start");
- pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
- break;
+ m[i] = d;
+ return m;
+ }
+ function d3_svg_lineMonotoneTangents(points) {
+ var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
+ while (++i < j) {
+ d = d3_svg_lineSlope(points[i], points[i + 1]);
+ if (Math.abs(d) < 1e-6) {
+ m[i] = m[i + 1] = 0;
+ } else {
+ a = m[i] / d;
+ b = m[i + 1] / d;
+ s = a * a + b * b;
+ if (s > 9) {
+ s = d * 3 / Math.sqrt(s);
+ m[i] = s * a;
+ m[i + 1] = s * b;
+ }
+ }
+ }
+ i = -1;
+ while (++i <= j) {
+ s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
+ tangents.push([ s || 0, m[i] * s || 0 ]);
+ }
+ return tangents;
+ }
+ function d3_svg_lineMonotone(points) {
+ return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+ }
+ d3.geom.hull = function(vertices) {
+ var x = d3_svg_lineX, y = d3_svg_lineY;
+ if (arguments.length) return hull(vertices);
+ function hull(data) {
+ if (data.length < 3) return [];
+ var fx = d3_functor(x), fy = d3_functor(y), n = data.length, vertices, plen = n - 1, points = [], stack = [], d, i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;
+ if (fx === d3_svg_lineX && y === d3_svg_lineY) vertices = data; else for (i = 0,
+ vertices = []; i < n; ++i) {
+ vertices.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ for (i = 1; i < n; ++i) {
+ if (vertices[i][1] < vertices[h][1] || vertices[i][1] == vertices[h][1] && vertices[i][0] < vertices[h][0]) h = i;
+ }
+ for (i = 0; i < n; ++i) {
+ if (i === h) continue;
+ y1 = vertices[i][1] - vertices[h][1];
+ x1 = vertices[i][0] - vertices[h][0];
+ points.push({
+ angle: Math.atan2(y1, x1),
+ index: i
+ });
+ }
+ points.sort(function(a, b) {
+ return a.angle - b.angle;
+ });
+ a = points[0].angle;
+ v = points[0].index;
+ u = 0;
+ for (i = 1; i < plen; ++i) {
+ j = points[i].index;
+ if (a == points[i].angle) {
+ x1 = vertices[v][0] - vertices[h][0];
+ y1 = vertices[v][1] - vertices[h][1];
+ x2 = vertices[j][0] - vertices[h][0];
+ y2 = vertices[j][1] - vertices[h][1];
+ if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {
+ points[i].index = -1;
+ continue;
+ } else {
+ points[u].index = -1;
}
}
- if (scale.ticks) {
- tickEnter.call(tickTransform, scale0);
- tickUpdate.call(tickTransform, scale1);
- tickExit.call(tickTransform, scale1);
- subtickEnter.call(tickTransform, scale0);
- subtickUpdate.call(tickTransform, scale1);
- subtickExit.call(tickTransform, scale1);
- } else {
- var dx = scale1.rangeBand() / 2, x = function(d) {
- return scale1(d) + dx;
- };
- tickEnter.call(tickTransform, x);
- tickUpdate.call(tickTransform, x);
+ a = points[i].angle;
+ u = i;
+ v = j;
+ }
+ stack.push(h);
+ for (i = 0, j = 0; i < 2; ++j) {
+ if (points[j].index > -1) {
+ stack.push(points[j].index);
+ i++;
}
- });
+ }
+ sp = stack.length;
+ for (;j < plen; ++j) {
+ if (points[j].index < 0) continue;
+ while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {
+ --sp;
+ }
+ stack[sp++] = points[j].index;
+ }
+ var poly = [];
+ for (i = sp - 1; i >= 0; --i) poly.push(data[stack[i]]);
+ return poly;
}
- axis.scale = function(x) {
- if (!arguments.length) return scale;
- scale = x;
- return axis;
- };
- axis.orient = function(x) {
- if (!arguments.length) return orient;
- orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
- return axis;
- };
- axis.ticks = function() {
- if (!arguments.length) return tickArguments_;
- tickArguments_ = arguments;
- return axis;
- };
- axis.tickValues = function(x) {
- if (!arguments.length) return tickValues;
- tickValues = x;
- return axis;
- };
- axis.tickFormat = function(x) {
- if (!arguments.length) return tickFormat_;
- tickFormat_ = x;
- return axis;
- };
- axis.tickSize = function(x, y) {
- if (!arguments.length) return tickMajorSize;
- var n = arguments.length - 1;
- tickMajorSize = +x;
- tickMinorSize = n > 1 ? +y : tickMajorSize;
- tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
- return axis;
- };
- axis.tickPadding = function(x) {
- if (!arguments.length) return tickPadding;
- tickPadding = +x;
- return axis;
+ hull.x = function(_) {
+ return arguments.length ? (x = _, hull) : x;
};
- axis.tickSubdivide = function(x) {
- if (!arguments.length) return tickSubdivide;
- tickSubdivide = +x;
- return axis;
+ hull.y = function(_) {
+ return arguments.length ? (y = _, hull) : y;
};
- return axis;
- };
- var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
- top: 1,
- right: 1,
- bottom: 1,
- left: 1
+ return hull;
};
- function d3_svg_axisX(selection, x) {
- selection.attr("transform", function(d) {
- return "translate(" + x(d) + ",0)";
- });
- }
- function d3_svg_axisY(selection, y) {
- selection.attr("transform", function(d) {
- return "translate(0," + y(d) + ")";
- });
+ function d3_geom_hullCCW(i1, i2, i3, v) {
+ var t, a, b, c, d, e, f;
+ t = v[i1];
+ a = t[0];
+ b = t[1];
+ t = v[i2];
+ c = t[0];
+ d = t[1];
+ t = v[i3];
+ e = t[0];
+ f = t[1];
+ return (f - b) * (c - a) - (d - b) * (e - a) > 0;
}
- function d3_svg_axisSubdivide(scale, ticks, m) {
- subticks = [];
- if (m && ticks.length > 1) {
- var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;
+ d3.geom.polygon = function(coordinates) {
+ coordinates.area = function() {
+ var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1];
+ while (++i < n) {
+ area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1];
+ }
+ return area * .5;
+ };
+ coordinates.centroid = function(k) {
+ var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;
+ if (!arguments.length) k = -1 / (6 * coordinates.area());
+ while (++i < n) {
+ a = b;
+ b = coordinates[i];
+ c = a[0] * b[1] - b[0] * a[1];
+ x += (a[0] + b[0]) * c;
+ y += (a[1] + b[1]) * c;
+ }
+ return [ x * k, y * k ];
+ };
+ coordinates.clip = function(subject) {
+ var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;
while (++i < n) {
- for (j = m; --j > 0; ) {
- if ((v = +ticks[i] - j * d) >= extent[0]) {
- subticks.push(v);
+ input = subject.slice();
+ subject.length = 0;
+ b = coordinates[i];
+ c = input[(m = input.length) - 1];
+ j = -1;
+ while (++j < m) {
+ d = input[j];
+ if (d3_geom_polygonInside(d, a, b)) {
+ if (!d3_geom_polygonInside(c, a, b)) {
+ subject.push(d3_geom_polygonIntersect(c, d, a, b));
+ }
+ subject.push(d);
+ } else if (d3_geom_polygonInside(c, a, b)) {
+ subject.push(d3_geom_polygonIntersect(c, d, a, b));
}
+ c = d;
}
+ a = b;
}
- for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {
- subticks.push(v);
- }
- }
- return subticks;
+ return subject;
+ };
+ return coordinates;
+ };
+ function d3_geom_polygonInside(p, a, b) {
+ return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
}
- d3.svg.brush = function() {
- var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;
- function brush(g) {
- g.each(function() {
- var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e;
- g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
- bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
- fg.enter().append("rect").attr("class", "extent").style("cursor", "move");
- tz.enter().append("g").attr("class", function(d) {
- return "resize " + d;
- }).style("cursor", function(d) {
- return d3_svg_brushCursor[d];
- }).append("rect").attr("x", function(d) {
- return /[ew]$/.test(d) ? -3 : null;
- }).attr("y", function(d) {
- return /^[ns]/.test(d) ? -3 : null;
- }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
- tz.style("display", brush.empty() ? "none" : null);
- tz.exit().remove();
- if (x) {
- e = d3_scaleRange(x);
- bg.attr("x", e[0]).attr("width", e[1] - e[0]);
- redrawX(g);
+ function d3_geom_polygonIntersect(c, d, a, b) {
+ var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
+ return [ x1 + ua * x21, y1 + ua * y21 ];
+ }
+ d3.geom.delaunay = function(vertices) {
+ var edges = vertices.map(function() {
+ return [];
+ }), triangles = [];
+ d3_geom_voronoiTessellate(vertices, function(e) {
+ edges[e.region.l.index].push(vertices[e.region.r.index]);
+ });
+ edges.forEach(function(edge, i) {
+ var v = vertices[i], cx = v[0], cy = v[1];
+ edge.forEach(function(v) {
+ v.angle = Math.atan2(v[0] - cx, v[1] - cy);
+ });
+ edge.sort(function(a, b) {
+ return a.angle - b.angle;
+ });
+ for (var j = 0, m = edge.length - 1; j < m; j++) {
+ triangles.push([ v, edge[j], edge[j + 1] ]);
+ }
+ });
+ return triangles;
+ };
+ d3.geom.voronoi = function(points) {
+ var size = null, x = d3_svg_lineX, y = d3_svg_lineY, clip;
+ if (arguments.length) return voronoi(points);
+ function voronoi(data) {
+ var points, polygons = data.map(function() {
+ return [];
+ }), fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length, Z = 1e6;
+ if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (points = [],
+ i = 0; i < n; ++i) {
+ points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ d3_geom_voronoiTessellate(points, function(e) {
+ var s1, s2, x1, x2, y1, y2;
+ if (e.a === 1 && e.b >= 0) {
+ s1 = e.ep.r;
+ s2 = e.ep.l;
+ } else {
+ s1 = e.ep.l;
+ s2 = e.ep.r;
}
- if (y) {
- e = d3_scaleRange(y);
- bg.attr("y", e[0]).attr("height", e[1] - e[0]);
- redrawY(g);
+ if (e.a === 1) {
+ y1 = s1 ? s1.y : -Z;
+ x1 = e.c - e.b * y1;
+ y2 = s2 ? s2.y : Z;
+ x2 = e.c - e.b * y2;
+ } else {
+ x1 = s1 ? s1.x : -Z;
+ y1 = e.c - e.a * x1;
+ x2 = s2 ? s2.x : Z;
+ y2 = e.c - e.a * x2;
}
- redraw(g);
+ var v1 = [ x1, y1 ], v2 = [ x2, y2 ];
+ polygons[e.region.l.index].push(v1, v2);
+ polygons[e.region.r.index].push(v1, v2);
});
- }
- function redraw(g) {
- g.selectAll(".resize").attr("transform", function(d) {
- return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")";
+ polygons = polygons.map(function(polygon, i) {
+ var cx = points[i][0], cy = points[i][1], angle = polygon.map(function(v) {
+ return Math.atan2(v[0] - cx, v[1] - cy);
+ }), order = d3.range(polygon.length).sort(function(a, b) {
+ return angle[a] - angle[b];
+ });
+ return order.filter(function(d, i) {
+ return !i || angle[d] - angle[order[i - 1]] > ε;
+ }).map(function(d) {
+ return polygon[d];
+ });
});
+ polygons.forEach(function(polygon, i) {
+ var n = polygon.length;
+ if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]);
+ if (n > 2) return;
+ var p0 = points[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1;
+ if (Math.abs(dy) < ε) {
+ var y = y0 < y1 ? -Z : Z;
+ polygon.push([ -Z, y ], [ Z, y ]);
+ } else if (dx < ε) {
+ var x = x0 < x1 ? -Z : Z;
+ polygon.push([ x, -Z ], [ x, Z ]);
+ } else {
+ var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx;
+ if (Math.abs(z) < ε) {
+ polygon.push([ dy < 0 ? y : -y, y ]);
+ } else {
+ if (z > 0) y *= -1;
+ polygon.push([ -Z, y ], [ Z, y ]);
+ }
+ }
+ });
+ if (clip) for (i = 0; i < n; ++i) clip(polygons[i]);
+ for (i = 0; i < n; ++i) polygons[i].point = data[i];
+ return polygons;
}
- function redrawX(g) {
- g.select(".extent").attr("x", extent[0][0]);
- g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]);
- }
- function redrawY(g) {
- g.select(".extent").attr("y", extent[0][1]);
- g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]);
- }
- function brushstart() {
- var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), center, origin = mouse(), offset;
- var w = d3.select(d3_window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup);
- if (dragging) {
- origin[0] = extent[0][0] - origin[0];
- origin[1] = extent[0][1] - origin[1];
- } else if (resizing) {
- var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
- offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];
- origin[0] = extent[ex][0];
- origin[1] = extent[ey][1];
- } else if (d3.event.altKey) center = origin.slice();
- g.style("pointer-events", "none").selectAll(".resize").style("display", null);
- d3.select("body").style("cursor", eventTarget.style("cursor"));
- event_({
- type: "brushstart"
+ voronoi.x = function(_) {
+ return arguments.length ? (x = _, voronoi) : x;
+ };
+ voronoi.y = function(_) {
+ return arguments.length ? (y = _, voronoi) : y;
+ };
+ voronoi.size = function(_) {
+ if (!arguments.length) return size;
+ if (_ == null) {
+ clip = null;
+ } else {
+ size = [ +_[0], +_[1] ];
+ clip = d3.geom.polygon([ [ 0, 0 ], [ 0, size[1] ], size, [ size[0], 0 ] ]).clip;
+ }
+ return voronoi;
+ };
+ voronoi.links = function(data) {
+ var points, graph = data.map(function() {
+ return [];
+ }), links = [], fx = d3_functor(x), fy = d3_functor(y), d, i, n = data.length;
+ if (fx === d3_svg_lineX && fy === d3_svg_lineY) points = data; else for (i = 0; i < n; ++i) {
+ points.push([ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ]);
+ }
+ d3_geom_voronoiTessellate(points, function(e) {
+ var l = e.region.l.index, r = e.region.r.index;
+ if (graph[l][r]) return;
+ graph[l][r] = graph[r][l] = true;
+ links.push({
+ source: data[l],
+ target: data[r]
+ });
});
- brushmove();
- d3_eventCancel();
- function mouse() {
- var touches = d3.event.changedTouches;
- return touches ? d3.touches(target, touches)[0] : d3.mouse(target);
+ return links;
+ };
+ voronoi.triangles = function(data) {
+ if (x === d3_svg_lineX && y === d3_svg_lineY) return d3.geom.delaunay(data);
+ var points, point, fx = d3_functor(x), fy = d3_functor(y), d, i, n;
+ for (i = 0, points = [], n = data.length; i < n; ++i) {
+ point = [ +fx.call(this, d = data[i], i), +fy.call(this, d, i) ];
+ point.data = d;
+ points.push(point);
+ }
+ return d3.geom.delaunay(points).map(function(triangle) {
+ return triangle.map(function(point) {
+ return point.data;
+ });
+ });
+ };
+ return voronoi;
+ };
+ var d3_geom_voronoiOpposite = {
+ l: "r",
+ r: "l"
+ };
+ function d3_geom_voronoiTessellate(points, callback) {
+ var Sites = {
+ list: points.map(function(v, i) {
+ return {
+ index: i,
+ x: v[0],
+ y: v[1]
+ };
+ }).sort(function(a, b) {
+ return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;
+ }),
+ bottomSite: null
+ };
+ var EdgeList = {
+ list: [],
+ leftEnd: null,
+ rightEnd: null,
+ init: function() {
+ EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l");
+ EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l");
+ EdgeList.leftEnd.r = EdgeList.rightEnd;
+ EdgeList.rightEnd.l = EdgeList.leftEnd;
+ EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);
+ },
+ createHalfEdge: function(edge, side) {
+ return {
+ edge: edge,
+ side: side,
+ vertex: null,
+ l: null,
+ r: null
+ };
+ },
+ insert: function(lb, he) {
+ he.l = lb;
+ he.r = lb.r;
+ lb.r.l = he;
+ lb.r = he;
+ },
+ leftBound: function(p) {
+ var he = EdgeList.leftEnd;
+ do {
+ he = he.r;
+ } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));
+ he = he.l;
+ return he;
+ },
+ del: function(he) {
+ he.l.r = he.r;
+ he.r.l = he.l;
+ he.edge = null;
+ },
+ right: function(he) {
+ return he.r;
+ },
+ left: function(he) {
+ return he.l;
+ },
+ leftRegion: function(he) {
+ return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];
+ },
+ rightRegion: function(he) {
+ return he.edge == null ? Sites.bottomSite : he.edge.region[d3_geom_voronoiOpposite[he.side]];
}
- function keydown() {
- if (d3.event.keyCode == 32) {
- if (!dragging) {
- center = null;
- origin[0] -= extent[1][0];
- origin[1] -= extent[1][1];
- dragging = 2;
+ };
+ var Geom = {
+ bisect: function(s1, s2) {
+ var newEdge = {
+ region: {
+ l: s1,
+ r: s2
+ },
+ ep: {
+ l: null,
+ r: null
}
- d3_eventCancel();
- }
- }
- function keyup() {
- if (d3.event.keyCode == 32 && dragging == 2) {
- origin[0] += extent[1][0];
- origin[1] += extent[1][1];
- dragging = 0;
- d3_eventCancel();
+ };
+ var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;
+ newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;
+ if (adx > ady) {
+ newEdge.a = 1;
+ newEdge.b = dy / dx;
+ newEdge.c /= dx;
+ } else {
+ newEdge.b = 1;
+ newEdge.a = dx / dy;
+ newEdge.c /= dy;
}
- }
- function brushmove() {
- var point = mouse(), moved = false;
- if (offset) {
- point[0] += offset[0];
- point[1] += offset[1];
+ return newEdge;
+ },
+ intersect: function(el1, el2) {
+ var e1 = el1.edge, e2 = el2.edge;
+ if (!e1 || !e2 || e1.region.r == e2.region.r) {
+ return null;
}
- if (!dragging) {
- if (d3.event.altKey) {
- if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];
- origin[0] = extent[+(point[0] < center[0])][0];
- origin[1] = extent[+(point[1] < center[1])][1];
- } else center = null;
+ var d = e1.a * e2.b - e1.b * e2.a;
+ if (Math.abs(d) < 1e-10) {
+ return null;
}
- if (resizingX && move1(point, x, 0)) {
- redrawX(g);
- moved = true;
+ var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;
+ if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {
+ el = el1;
+ e = e1;
+ } else {
+ el = el2;
+ e = e2;
}
- if (resizingY && move1(point, y, 1)) {
- redrawY(g);
- moved = true;
+ var rightOfSite = xint >= e.region.r.x;
+ if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") {
+ return null;
}
- if (moved) {
- redraw(g);
- event_({
- type: "brush",
- mode: dragging ? "move" : "resize"
- });
+ return {
+ x: xint,
+ y: yint
+ };
+ },
+ rightOf: function(he, p) {
+ var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;
+ if (rightOfSite && he.side === "l") {
+ return 1;
}
- }
- function move1(point, scale, i) {
- var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;
- if (dragging) {
- r0 -= position;
- r1 -= size + position;
+ if (!rightOfSite && he.side === "r") {
+ return 0;
}
- min = Math.max(r0, Math.min(r1, point[i]));
- if (dragging) {
- max = (min += position) + size;
- } else {
- if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
- if (position < min) {
- max = min;
- min = position;
+ if (e.a === 1) {
+ var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;
+ if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {
+ above = fast = dyp >= e.b * dxp;
} else {
- max = position;
+ above = p.x + p.y * e.b > e.c;
+ if (e.b < 0) {
+ above = !above;
+ }
+ if (!above) {
+ fast = 1;
+ }
}
+ if (!fast) {
+ var dxs = topsite.x - e.region.l.x;
+ above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);
+ if (e.b < 0) {
+ above = !above;
+ }
+ }
+ } else {
+ var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;
+ above = t1 * t1 > t2 * t2 + t3 * t3;
}
- if (extent[0][i] !== min || extent[1][i] !== max) {
- extentDomain = null;
- extent[0][i] = min;
- extent[1][i] = max;
- return true;
- }
- }
- function brushend() {
- brushmove();
- g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
- d3.select("body").style("cursor", null);
- w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
- event_({
- type: "brushend"
- });
- d3_eventCancel();
+ return he.side === "l" ? above : !above;
+ },
+ endPoint: function(edge, side, site) {
+ edge.ep[side] = site;
+ if (!edge.ep[d3_geom_voronoiOpposite[side]]) return;
+ callback(edge);
+ },
+ distance: function(s, t) {
+ var dx = s.x - t.x, dy = s.y - t.y;
+ return Math.sqrt(dx * dx + dy * dy);
}
- }
- brush.x = function(z) {
- if (!arguments.length) return x;
- x = z;
- resizes = d3_svg_brushResizes[!x << 1 | !y];
- return brush;
- };
- brush.y = function(z) {
- if (!arguments.length) return y;
- y = z;
- resizes = d3_svg_brushResizes[!x << 1 | !y];
- return brush;
};
- brush.extent = function(z) {
- var x0, x1, y0, y1, t;
- if (!arguments.length) {
- z = extentDomain || extent;
- if (x) {
- x0 = z[0][0], x1 = z[1][0];
- if (!extentDomain) {
- x0 = extent[0][0], x1 = extent[1][0];
- if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
- if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ var EventQueue = {
+ list: [],
+ insert: function(he, site, offset) {
+ he.vertex = site;
+ he.ystar = site.y + offset;
+ for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {
+ var next = list[i];
+ if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {
+ continue;
+ } else {
+ break;
}
}
- if (y) {
- y0 = z[0][1], y1 = z[1][1];
- if (!extentDomain) {
- y0 = extent[0][1], y1 = extent[1][1];
- if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
- if (y1 < y0) t = y0, y0 = y1, y1 = t;
- }
+ list.splice(i, 0, he);
+ },
+ del: function(he) {
+ for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}
+ ls.splice(i, 1);
+ },
+ empty: function() {
+ return EventQueue.list.length === 0;
+ },
+ nextEvent: function(he) {
+ for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {
+ if (ls[i] == he) return ls[i + 1];
}
- return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
- }
- extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];
- if (x) {
- x0 = z[0], x1 = z[1];
- if (y) x0 = x0[0], x1 = x1[0];
- extentDomain[0][0] = x0, extentDomain[1][0] = x1;
- if (x.invert) x0 = x(x0), x1 = x(x1);
- if (x1 < x0) t = x0, x0 = x1, x1 = t;
- extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;
- }
- if (y) {
- y0 = z[0], y1 = z[1];
- if (x) y0 = y0[1], y1 = y1[1];
- extentDomain[0][1] = y0, extentDomain[1][1] = y1;
- if (y.invert) y0 = y(y0), y1 = y(y1);
- if (y1 < y0) t = y0, y0 = y1, y1 = t;
- extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;
+ return null;
+ },
+ min: function() {
+ var elem = EventQueue.list[0];
+ return {
+ x: elem.vertex.x,
+ y: elem.ystar
+ };
+ },
+ extractMin: function() {
+ return EventQueue.list.shift();
}
- return brush;
- };
- brush.clear = function() {
- extentDomain = null;
- extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;
- return brush;
- };
- brush.empty = function() {
- return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];
};
- return d3.rebind(brush, event, "on");
- };
- var d3_svg_brushCursor = {
- n: "ns-resize",
- e: "ew-resize",
- s: "ns-resize",
- w: "ew-resize",
- nw: "nwse-resize",
- ne: "nesw-resize",
- se: "nwse-resize",
- sw: "nesw-resize"
- };
- var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
- d3.behavior = {};
- d3.behavior.drag = function() {
- var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null;
- function drag() {
- this.on("mousedown.drag", mousedown).on("touchstart.drag", mousedown);
- }
- function mousedown() {
- var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null, offset, origin_ = point(), moved = 0;
- var w = d3.select(d3_window).on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", dragmove).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", dragend, true);
- if (origin) {
- offset = origin.apply(target, arguments);
- offset = [ offset.x - origin_[0], offset.y - origin_[1] ];
+ EdgeList.init();
+ Sites.bottomSite = Sites.list.shift();
+ var newSite = Sites.list.shift(), newIntStar;
+ var lbnd, rbnd, llbnd, rrbnd, bisector;
+ var bot, top, temp, p, v;
+ var e, pm;
+ while (true) {
+ if (!EventQueue.empty()) {
+ newIntStar = EventQueue.min();
+ }
+ if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {
+ lbnd = EdgeList.leftBound(newSite);
+ rbnd = EdgeList.right(lbnd);
+ bot = EdgeList.rightRegion(lbnd);
+ e = Geom.bisect(bot, newSite);
+ bisector = EdgeList.createHalfEdge(e, "l");
+ EdgeList.insert(lbnd, bisector);
+ p = Geom.intersect(lbnd, bisector);
+ if (p) {
+ EventQueue.del(lbnd);
+ EventQueue.insert(lbnd, p, Geom.distance(p, newSite));
+ }
+ lbnd = bisector;
+ bisector = EdgeList.createHalfEdge(e, "r");
+ EdgeList.insert(lbnd, bisector);
+ p = Geom.intersect(bisector, rbnd);
+ if (p) {
+ EventQueue.insert(bisector, p, Geom.distance(p, newSite));
+ }
+ newSite = Sites.list.shift();
+ } else if (!EventQueue.empty()) {
+ lbnd = EventQueue.extractMin();
+ llbnd = EdgeList.left(lbnd);
+ rbnd = EdgeList.right(lbnd);
+ rrbnd = EdgeList.right(rbnd);
+ bot = EdgeList.leftRegion(lbnd);
+ top = EdgeList.rightRegion(rbnd);
+ v = lbnd.vertex;
+ Geom.endPoint(lbnd.edge, lbnd.side, v);
+ Geom.endPoint(rbnd.edge, rbnd.side, v);
+ EdgeList.del(lbnd);
+ EventQueue.del(rbnd);
+ EdgeList.del(rbnd);
+ pm = "l";
+ if (bot.y > top.y) {
+ temp = bot;
+ bot = top;
+ top = temp;
+ pm = "r";
+ }
+ e = Geom.bisect(bot, top);
+ bisector = EdgeList.createHalfEdge(e, pm);
+ EdgeList.insert(llbnd, bisector);
+ Geom.endPoint(e, d3_geom_voronoiOpposite[pm], v);
+ p = Geom.intersect(llbnd, bisector);
+ if (p) {
+ EventQueue.del(llbnd);
+ EventQueue.insert(llbnd, p, Geom.distance(p, bot));
+ }
+ p = Geom.intersect(bisector, rrbnd);
+ if (p) {
+ EventQueue.insert(bisector, p, Geom.distance(p, bot));
+ }
} else {
- offset = [ 0, 0 ];
- }
- if (touchId == null) d3_eventCancel();
- event_({
- type: "dragstart"
- });
- function point() {
- var p = target.parentNode;
- return touchId != null ? d3.touches(p).filter(function(p) {
- return p.identifier === touchId;
- })[0] : d3.mouse(p);
+ break;
}
- function dragmove() {
- if (!target.parentNode) return dragend();
- var p = point(), dx = p[0] - origin_[0], dy = p[1] - origin_[1];
- moved |= dx | dy;
- origin_ = p;
- d3_eventCancel();
- event_({
- type: "drag",
- x: p[0] + offset[0],
- y: p[1] + offset[1],
- dx: dx,
- dy: dy
- });
+ }
+ for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {
+ callback(lbnd.edge);
+ }
+ }
+ d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+ var x = d3_svg_lineX, y = d3_svg_lineY, compat;
+ if (compat = arguments.length) {
+ x = d3_geom_quadtreeCompatX;
+ y = d3_geom_quadtreeCompatY;
+ if (compat === 3) {
+ y2 = y1;
+ x2 = x1;
+ y1 = x1 = 0;
}
- function dragend() {
- event_({
- type: "dragend"
- });
- if (moved) {
- d3_eventCancel();
- if (d3.event.target === eventTarget) w.on("click.drag", click, true);
+ return quadtree(points);
+ }
+ function quadtree(data) {
+ var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
+ if (x1 != null) {
+ x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
+ } else {
+ x2_ = y2_ = -(x1_ = y1_ = Infinity);
+ xs = [], ys = [];
+ n = data.length;
+ if (compat) for (i = 0; i < n; ++i) {
+ d = data[i];
+ if (d.x < x1_) x1_ = d.x;
+ if (d.y < y1_) y1_ = d.y;
+ if (d.x > x2_) x2_ = d.x;
+ if (d.y > y2_) y2_ = d.y;
+ xs.push(d.x);
+ ys.push(d.y);
+ } else for (i = 0; i < n; ++i) {
+ var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
+ if (x_ < x1_) x1_ = x_;
+ if (y_ < y1_) y1_ = y_;
+ if (x_ > x2_) x2_ = x_;
+ if (y_ > y2_) y2_ = y_;
+ xs.push(x_);
+ ys.push(y_);
}
- w.on(touchId != null ? "touchmove.drag-" + touchId : "mousemove.drag", null).on(touchId != null ? "touchend.drag-" + touchId : "mouseup.drag", null);
}
- function click() {
- d3_eventCancel();
- w.on("click.drag", null);
+ var dx = x2_ - x1_, dy = y2_ - y1_;
+ if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
+ function insert(n, d, x, y, x1, y1, x2, y2) {
+ if (isNaN(x) || isNaN(y)) return;
+ if (n.leaf) {
+ var nx = n.x, ny = n.y;
+ if (nx != null) {
+ if (Math.abs(nx - x) + Math.abs(ny - y) < .01) {
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ } else {
+ var nPoint = n.point;
+ n.x = n.y = n.point = null;
+ insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ }
+ } else {
+ n.x = x, n.y = y, n.point = d;
+ }
+ } else {
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ }
}
+ function insertChild(n, d, x, y, x1, y1, x2, y2) {
+ var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;
+ n.leaf = false;
+ n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+ if (right) x1 = sx; else x2 = sx;
+ if (bottom) y1 = sy; else y2 = sy;
+ insert(n, d, x, y, x1, y1, x2, y2);
+ }
+ var root = d3_geom_quadtreeNode();
+ root.add = function(d) {
+ insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
+ };
+ root.visit = function(f) {
+ d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
+ };
+ i = -1;
+ if (x1 == null) {
+ while (++i < n) {
+ insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
+ }
+ --i;
+ } else data.forEach(root.add);
+ xs = ys = data = d = null;
+ return root;
}
- drag.origin = function(x) {
- if (!arguments.length) return origin;
- origin = x;
- return drag;
- };
- return d3.rebind(drag, event, "on");
- };
- d3.behavior.zoom = function() {
- var translate = [ 0, 0 ], translate0, scale = 1, scale0, scaleExtent = d3_behavior_zoomInfinity, event = d3_eventDispatch(zoom, "zoom"), x0, x1, y0, y1, touchtime;
- function zoom() {
- this.on("mousedown.zoom", mousedown).on("mousemove.zoom", mousemove).on(d3_behavior_zoomWheel + ".zoom", mousewheel).on("dblclick.zoom", dblclick).on("touchstart.zoom", touchstart).on("touchmove.zoom", touchmove).on("touchend.zoom", touchstart);
- }
- zoom.translate = function(x) {
- if (!arguments.length) return translate;
- translate = x.map(Number);
- rescale();
- return zoom;
- };
- zoom.scale = function(x) {
- if (!arguments.length) return scale;
- scale = +x;
- rescale();
- return zoom;
+ quadtree.x = function(_) {
+ return arguments.length ? (x = _, quadtree) : x;
};
- zoom.scaleExtent = function(x) {
- if (!arguments.length) return scaleExtent;
- scaleExtent = x == null ? d3_behavior_zoomInfinity : x.map(Number);
- return zoom;
+ quadtree.y = function(_) {
+ return arguments.length ? (y = _, quadtree) : y;
};
- zoom.x = function(z) {
- if (!arguments.length) return x1;
- x1 = z;
- x0 = z.copy();
- translate = [ 0, 0 ];
- scale = 1;
- return zoom;
+ quadtree.size = function(_) {
+ if (!arguments.length) return x1 == null ? null : [ x2, y2 ];
+ if (_ == null) {
+ x1 = y1 = x2 = y2 = null;
+ } else {
+ x1 = y1 = 0;
+ x2 = +_[0], y2 = +_[1];
+ }
+ return quadtree;
};
- zoom.y = function(z) {
- if (!arguments.length) return y1;
- y1 = z;
- y0 = z.copy();
- translate = [ 0, 0 ];
- scale = 1;
- return zoom;
+ return quadtree;
+ };
+ function d3_geom_quadtreeCompatX(d) {
+ return d.x;
+ }
+ function d3_geom_quadtreeCompatY(d) {
+ return d.y;
+ }
+ function d3_geom_quadtreeNode() {
+ return {
+ leaf: true,
+ nodes: [],
+ point: null,
+ x: null,
+ y: null
};
- function location(p) {
- return [ (p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale ];
- }
- function point(l) {
- return [ l[0] * scale + translate[0], l[1] * scale + translate[1] ];
+ }
+ function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
+ if (!f(node, x1, y1, x2, y2)) {
+ var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
+ if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
+ if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
+ if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
+ if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
}
- function scaleTo(s) {
- scale = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+ }
+ d3.interpolateRgb = d3_interpolateRgb;
+ function d3_interpolateRgb(a, b) {
+ a = d3.rgb(a);
+ b = d3.rgb(b);
+ var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
+ return function(t) {
+ return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
+ };
+ }
+ d3.transform = function(string) {
+ var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
+ return (d3.transform = function(string) {
+ if (string != null) {
+ g.setAttribute("transform", string);
+ var t = g.transform.baseVal.consolidate();
+ }
+ return new d3_transform(t ? t.matrix : d3_transformIdentity);
+ })(string);
+ };
+ function d3_transform(m) {
+ var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
+ if (r0[0] * r1[1] < r1[0] * r0[1]) {
+ r0[0] *= -1;
+ r0[1] *= -1;
+ kx *= -1;
+ kz *= -1;
}
- function translateTo(p, l) {
- l = point(l);
- translate[0] += p[0] - l[0];
- translate[1] += p[1] - l[1];
+ this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
+ this.translate = [ m.e, m.f ];
+ this.scale = [ kx, ky ];
+ this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
+ }
+ d3_transform.prototype.toString = function() {
+ return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
+ };
+ function d3_transformDot(a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+ }
+ function d3_transformNormalize(a) {
+ var k = Math.sqrt(d3_transformDot(a, a));
+ if (k) {
+ a[0] /= k;
+ a[1] /= k;
}
- function rescale() {
- if (x1) x1.domain(x0.range().map(function(x) {
- return (x - translate[0]) / scale;
- }).map(x0.invert));
- if (y1) y1.domain(y0.range().map(function(y) {
- return (y - translate[1]) / scale;
- }).map(y0.invert));
+ return k;
+ }
+ function d3_transformCombine(a, b, k) {
+ a[0] += k * b[0];
+ a[1] += k * b[1];
+ return a;
+ }
+ var d3_transformIdentity = {
+ a: 1,
+ b: 0,
+ c: 0,
+ d: 1,
+ e: 0,
+ f: 0
+ };
+ d3.interpolateNumber = d3_interpolateNumber;
+ function d3_interpolateNumber(a, b) {
+ b -= a = +a;
+ return function(t) {
+ return a + b * t;
+ };
+ }
+ d3.interpolateTransform = d3_interpolateTransform;
+ function d3_interpolateTransform(a, b) {
+ var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
+ if (ta[0] != tb[0] || ta[1] != tb[1]) {
+ s.push("translate(", null, ",", null, ")");
+ q.push({
+ i: 1,
+ x: d3_interpolateNumber(ta[0], tb[0])
+ }, {
+ i: 3,
+ x: d3_interpolateNumber(ta[1], tb[1])
+ });
+ } else if (tb[0] || tb[1]) {
+ s.push("translate(" + tb + ")");
+ } else {
+ s.push("");
}
- function dispatch(event) {
- rescale();
- d3.event.preventDefault();
- event({
- type: "zoom",
- scale: scale,
- translate: translate
+ if (ra != rb) {
+ if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
+ q.push({
+ i: s.push(s.pop() + "rotate(", null, ")") - 2,
+ x: d3_interpolateNumber(ra, rb)
});
+ } else if (rb) {
+ s.push(s.pop() + "rotate(" + rb + ")");
}
- function mousedown() {
- var target = this, event_ = event.of(target, arguments), eventTarget = d3.event.target, moved = 0, w = d3.select(d3_window).on("mousemove.zoom", mousemove).on("mouseup.zoom", mouseup), l = location(d3.mouse(target));
- d3_window.focus();
- d3_eventCancel();
- function mousemove() {
- moved = 1;
- translateTo(d3.mouse(target), l);
- dispatch(event_);
- }
- function mouseup() {
- if (moved) d3_eventCancel();
- w.on("mousemove.zoom", null).on("mouseup.zoom", null);
- if (moved && d3.event.target === eventTarget) w.on("click.zoom", click, true);
- }
- function click() {
- d3_eventCancel();
- w.on("click.zoom", null);
- }
+ if (wa != wb) {
+ q.push({
+ i: s.push(s.pop() + "skewX(", null, ")") - 2,
+ x: d3_interpolateNumber(wa, wb)
+ });
+ } else if (wb) {
+ s.push(s.pop() + "skewX(" + wb + ")");
}
- function mousewheel() {
- if (!translate0) translate0 = location(d3.mouse(this));
- scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * scale);
- translateTo(d3.mouse(this), translate0);
- dispatch(event.of(this, arguments));
+ if (ka[0] != kb[0] || ka[1] != kb[1]) {
+ n = s.push(s.pop() + "scale(", null, ",", null, ")");
+ q.push({
+ i: n - 4,
+ x: d3_interpolateNumber(ka[0], kb[0])
+ }, {
+ i: n - 2,
+ x: d3_interpolateNumber(ka[1], kb[1])
+ });
+ } else if (kb[0] != 1 || kb[1] != 1) {
+ s.push(s.pop() + "scale(" + kb + ")");
}
- function mousemove() {
- translate0 = null;
+ n = q.length;
+ return function(t) {
+ var i = -1, o;
+ while (++i < n) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ };
+ }
+ d3.interpolateObject = d3_interpolateObject;
+ function d3_interpolateObject(a, b) {
+ var i = {}, c = {}, k;
+ for (k in a) {
+ if (k in b) {
+ i[k] = d3_interpolateByName(k)(a[k], b[k]);
+ } else {
+ c[k] = a[k];
+ }
}
- function dblclick() {
- var p = d3.mouse(this), l = location(p), k = Math.log(scale) / Math.LN2;
- scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
- translateTo(p, l);
- dispatch(event.of(this, arguments));
+ for (k in b) {
+ if (!(k in a)) {
+ c[k] = b[k];
+ }
}
- function touchstart() {
- var touches = d3.touches(this), now = Date.now();
- scale0 = scale;
- translate0 = {};
- touches.forEach(function(t) {
- translate0[t.identifier] = location(t);
+ return function(t) {
+ for (k in i) c[k] = i[k](t);
+ return c;
+ };
+ }
+ d3.interpolateString = d3_interpolateString;
+ function d3_interpolateString(a, b) {
+ var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
+ a = a + "", b = b + "";
+ d3_interpolate_number.lastIndex = 0;
+ for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
+ if (m.index) s.push(b.substring(s0, s1 = m.index));
+ q.push({
+ i: s.length,
+ x: m[0]
});
- d3_eventCancel();
- if (touches.length === 1) {
- if (now - touchtime < 500) {
- var p = touches[0], l = location(touches[0]);
- scaleTo(scale * 2);
- translateTo(p, l);
- dispatch(event.of(this, arguments));
+ s.push(null);
+ s0 = d3_interpolate_number.lastIndex;
+ }
+ if (s0 < b.length) s.push(b.substring(s0));
+ for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
+ o = q[i];
+ if (o.x == m[0]) {
+ if (o.i) {
+ if (s[o.i + 1] == null) {
+ s[o.i - 1] += o.x;
+ s.splice(o.i, 1);
+ for (j = i + 1; j < n; ++j) q[j].i--;
+ } else {
+ s[o.i - 1] += o.x + s[o.i + 1];
+ s.splice(o.i, 2);
+ for (j = i + 1; j < n; ++j) q[j].i -= 2;
+ }
+ } else {
+ if (s[o.i + 1] == null) {
+ s[o.i] = o.x;
+ } else {
+ s[o.i] = o.x + s[o.i + 1];
+ s.splice(o.i + 1, 1);
+ for (j = i + 1; j < n; ++j) q[j].i--;
+ }
}
- touchtime = now;
+ q.splice(i, 1);
+ n--;
+ i--;
+ } else {
+ o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
}
}
- function touchmove() {
- var touches = d3.touches(this), p0 = touches[0], l0 = translate0[p0.identifier];
- if (p1 = touches[1]) {
- var p1, l1 = translate0[p1.identifier];
- p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
- l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
- scaleTo(d3.event.scale * scale0);
+ while (i < n) {
+ o = q.pop();
+ if (s[o.i + 1] == null) {
+ s[o.i] = o.x;
+ } else {
+ s[o.i] = o.x + s[o.i + 1];
+ s.splice(o.i + 1, 1);
}
- translateTo(p0, l0);
- touchtime = null;
- dispatch(event.of(this, arguments));
+ n--;
}
- return d3.rebind(zoom, event, "on");
+ if (s.length === 1) {
+ return s[0] == null ? (o = q[0].x, function(t) {
+ return o(t) + "";
+ }) : function() {
+ return b;
+ };
+ }
+ return function(t) {
+ for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ };
+ }
+ var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
+ d3.interpolate = d3_interpolate;
+ function d3_interpolate(a, b) {
+ var i = d3.interpolators.length, f;
+ while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
+ return f;
+ }
+ function d3_interpolateByName(name) {
+ return name == "transform" ? d3_interpolateTransform : d3_interpolate;
+ }
+ d3.interpolators = [ function(a, b) {
+ var t = typeof b;
+ return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_Color ? d3_interpolateRgb : t === "object" ? Array.isArray(b) ? d3_interpolateArray : d3_interpolateObject : d3_interpolateNumber)(a, b);
+ } ];
+ d3.interpolateArray = d3_interpolateArray;
+ function d3_interpolateArray(a, b) {
+ var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
+ for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
+ for (;i < na; ++i) c[i] = a[i];
+ for (;i < nb; ++i) c[i] = b[i];
+ return function(t) {
+ for (i = 0; i < n0; ++i) c[i] = x[i](t);
+ return c;
+ };
+ }
+ var d3_ease_default = function() {
+ return d3_identity;
};
- var d3_behavior_zoomInfinity = [ 0, Infinity ];
- var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in document ? (d3_behavior_zoomDelta = function() {
- return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
- }, "wheel") : "onmousewheel" in document ? (d3_behavior_zoomDelta = function() {
- return d3.event.wheelDelta;
- }, "mousewheel") : (d3_behavior_zoomDelta = function() {
- return -d3.event.detail;
- }, "MozMousePixelScroll");
+ var d3_ease = d3.map({
+ linear: d3_ease_default,
+ poly: d3_ease_poly,
+ quad: function() {
+ return d3_ease_quad;
+ },
+ cubic: function() {
+ return d3_ease_cubic;
+ },
+ sin: function() {
+ return d3_ease_sin;
+ },
+ exp: function() {
+ return d3_ease_exp;
+ },
+ circle: function() {
+ return d3_ease_circle;
+ },
+ elastic: d3_ease_elastic,
+ back: d3_ease_back,
+ bounce: function() {
+ return d3_ease_bounce;
+ }
+ });
+ var d3_ease_mode = d3.map({
+ "in": d3_identity,
+ out: d3_ease_reverse,
+ "in-out": d3_ease_reflect,
+ "out-in": function(f) {
+ return d3_ease_reflect(d3_ease_reverse(f));
+ }
+ });
+ d3.ease = function(name) {
+ var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in";
+ t = d3_ease.get(t) || d3_ease_default;
+ m = d3_ease_mode.get(m) || d3_identity;
+ return d3_ease_clamp(m(t.apply(null, Array.prototype.slice.call(arguments, 1))));
+ };
+ function d3_ease_clamp(f) {
+ return function(t) {
+ return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
+ };
+ }
+ function d3_ease_reverse(f) {
+ return function(t) {
+ return 1 - f(1 - t);
+ };
+ }
+ function d3_ease_reflect(f) {
+ return function(t) {
+ return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
+ };
+ }
+ function d3_ease_quad(t) {
+ return t * t;
+ }
+ function d3_ease_cubic(t) {
+ return t * t * t;
+ }
+ function d3_ease_cubicInOut(t) {
+ if (t <= 0) return 0;
+ if (t >= 1) return 1;
+ var t2 = t * t, t3 = t2 * t;
+ return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
+ }
+ function d3_ease_poly(e) {
+ return function(t) {
+ return Math.pow(t, e);
+ };
+ }
+ function d3_ease_sin(t) {
+ return 1 - Math.cos(t * π / 2);
+ }
+ function d3_ease_exp(t) {
+ return Math.pow(2, 10 * (t - 1));
+ }
+ function d3_ease_circle(t) {
+ return 1 - Math.sqrt(1 - t * t);
+ }
+ function d3_ease_elastic(a, p) {
+ var s;
+ if (arguments.length < 2) p = .45;
+ if (arguments.length) s = p / (2 * π) * Math.asin(1 / a); else a = 1, s = p / 4;
+ return function(t) {
+ return 1 + a * Math.pow(2, 10 * -t) * Math.sin((t - s) * 2 * π / p);
+ };
+ }
+ function d3_ease_back(s) {
+ if (!s) s = 1.70158;
+ return function(t) {
+ return t * t * ((s + 1) * t - s);
+ };
+ }
+ function d3_ease_bounce(t) {
+ return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+ }
+ d3.interpolateHcl = d3_interpolateHcl;
+ function d3_interpolateHcl(a, b) {
+ a = d3.hcl(a);
+ b = d3.hcl(b);
+ var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
+ if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
+ if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+ return function(t) {
+ return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
+ };
+ }
+ d3.interpolateHsl = d3_interpolateHsl;
+ function d3_interpolateHsl(a, b) {
+ a = d3.hsl(a);
+ b = d3.hsl(b);
+ var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
+ if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
+ if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+ return function(t) {
+ return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
+ };
+ }
+ d3.interpolateLab = d3_interpolateLab;
+ function d3_interpolateLab(a, b) {
+ a = d3.lab(a);
+ b = d3.lab(b);
+ var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
+ return function(t) {
+ return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
+ };
+ }
+ d3.interpolateRound = d3_interpolateRound;
+ function d3_interpolateRound(a, b) {
+ b -= a;
+ return function(t) {
+ return Math.round(a + b * t);
+ };
+ }
+ function d3_uninterpolateNumber(a, b) {
+ b = b - (a = +a) ? 1 / (b - a) : 0;
+ return function(x) {
+ return (x - a) * b;
+ };
+ }
+ function d3_uninterpolateClamp(a, b) {
+ b = b - (a = +a) ? 1 / (b - a) : 0;
+ return function(x) {
+ return Math.max(0, Math.min(1, (x - a) * b));
+ };
+ }
d3.layout = {};
d3.layout.bundle = function() {
return function(links) {
@@ -4145,465 +5387,169 @@ d3 = function() {
};
force.nodes = function(x) {
if (!arguments.length) return nodes;
- nodes = x;
- return force;
- };
- force.links = function(x) {
- if (!arguments.length) return links;
- links = x;
- return force;
- };
- force.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return force;
- };
- force.linkDistance = function(x) {
- if (!arguments.length) return linkDistance;
- linkDistance = typeof x === "function" ? x : +x;
- return force;
- };
- force.distance = force.linkDistance;
- force.linkStrength = function(x) {
- if (!arguments.length) return linkStrength;
- linkStrength = typeof x === "function" ? x : +x;
- return force;
- };
- force.friction = function(x) {
- if (!arguments.length) return friction;
- friction = +x;
- return force;
- };
- force.charge = function(x) {
- if (!arguments.length) return charge;
- charge = typeof x === "function" ? x : +x;
- return force;
- };
- force.gravity = function(x) {
- if (!arguments.length) return gravity;
- gravity = +x;
- return force;
- };
- force.theta = function(x) {
- if (!arguments.length) return theta;
- theta = +x;
- return force;
- };
- force.alpha = function(x) {
- if (!arguments.length) return alpha;
- x = +x;
- if (alpha) {
- if (x > 0) alpha = x; else alpha = 0;
- } else if (x > 0) {
- event.start({
- type: "start",
- alpha: alpha = x
- });
- d3.timer(force.tick);
- }
- return force;
- };
- force.start = function() {
- var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
- for (i = 0; i < n; ++i) {
- (o = nodes[i]).index = i;
- o.weight = 0;
- }
- for (i = 0; i < m; ++i) {
- o = links[i];
- if (typeof o.source == "number") o.source = nodes[o.source];
- if (typeof o.target == "number") o.target = nodes[o.target];
- ++o.source.weight;
- ++o.target.weight;
- }
- for (i = 0; i < n; ++i) {
- o = nodes[i];
- if (isNaN(o.x)) o.x = position("x", w);
- if (isNaN(o.y)) o.y = position("y", h);
- if (isNaN(o.px)) o.px = o.x;
- if (isNaN(o.py)) o.py = o.y;
- }
- distances = [];
- if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
- strengths = [];
- if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
- charges = [];
- if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
- function position(dimension, size) {
- var neighbors = neighbor(i), j = -1, m = neighbors.length, x;
- while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
- return Math.random() * size;
- }
- function neighbor() {
- if (!neighbors) {
- neighbors = [];
- for (j = 0; j < n; ++j) {
- neighbors[j] = [];
- }
- for (j = 0; j < m; ++j) {
- var o = links[j];
- neighbors[o.source.index].push(o.target);
- neighbors[o.target.index].push(o.source);
- }
- }
- return neighbors[i];
- }
- return force.resume();
- };
- force.resume = function() {
- return force.alpha(.1);
- };
- force.stop = function() {
- return force.alpha(0);
- };
- force.drag = function() {
- if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
- if (!arguments.length) return drag;
- this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
- };
- function dragmove(d) {
- d.px = d3.event.x, d.py = d3.event.y;
- force.resume();
- }
- return d3.rebind(force, event, "on");
- };
- function d3_layout_forceDragstart(d) {
- d.fixed |= 2;
- }
- function d3_layout_forceDragend(d) {
- d.fixed &= ~6;
- }
- function d3_layout_forceMouseover(d) {
- d.fixed |= 4;
- d.px = d.x, d.py = d.y;
- }
- function d3_layout_forceMouseout(d) {
- d.fixed &= ~4;
- }
- function d3_layout_forceAccumulate(quad, alpha, charges) {
- var cx = 0, cy = 0;
- quad.charge = 0;
- if (!quad.leaf) {
- var nodes = quad.nodes, n = nodes.length, i = -1, c;
- while (++i < n) {
- c = nodes[i];
- if (c == null) continue;
- d3_layout_forceAccumulate(c, alpha, charges);
- quad.charge += c.charge;
- cx += c.charge * c.cx;
- cy += c.charge * c.cy;
- }
- }
- if (quad.point) {
- if (!quad.leaf) {
- quad.point.x += Math.random() - .5;
- quad.point.y += Math.random() - .5;
- }
- var k = alpha * charges[quad.point.index];
- quad.charge += quad.pointCharge = k;
- cx += k * quad.point.x;
- cy += k * quad.point.y;
- }
- quad.cx = cx / quad.charge;
- quad.cy = cy / quad.charge;
- }
- var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1;
- d3.layout.partition = function() {
- var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
- function position(node, x, dx, dy) {
- var children = node.children;
- node.x = x;
- node.y = node.depth * dy;
- node.dx = dx;
- node.dy = dy;
- if (children && (n = children.length)) {
- var i = -1, n, c, d;
- dx = node.value ? dx / node.value : 0;
- while (++i < n) {
- position(c = children[i], x, d = c.value * dx, dy);
- x += d;
- }
- }
- }
- function depth(node) {
- var children = node.children, d = 0;
- if (children && (n = children.length)) {
- var i = -1, n;
- while (++i < n) d = Math.max(d, depth(children[i]));
- }
- return 1 + d;
- }
- function partition(d, i) {
- var nodes = hierarchy.call(this, d, i);
- position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
- return nodes;
- }
- partition.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return partition;
- };
- return d3_layout_hierarchyRebind(partition, hierarchy);
- };
- d3.layout.pie = function() {
- var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * π;
- function pie(data) {
- var values = data.map(function(d, i) {
- return +value.call(pie, d, i);
- });
- var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
- var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - startAngle) / d3.sum(values);
- var index = d3.range(data.length);
- if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
- return values[j] - values[i];
- } : function(i, j) {
- return sort(data[i], data[j]);
- });
- var arcs = [];
- index.forEach(function(i) {
- var d;
- arcs[i] = {
- data: data[i],
- value: d = values[i],
- startAngle: a,
- endAngle: a += d * k
- };
- });
- return arcs;
- }
- pie.value = function(x) {
- if (!arguments.length) return value;
- value = x;
- return pie;
+ nodes = x;
+ return force;
};
- pie.sort = function(x) {
- if (!arguments.length) return sort;
- sort = x;
- return pie;
+ force.links = function(x) {
+ if (!arguments.length) return links;
+ links = x;
+ return force;
};
- pie.startAngle = function(x) {
- if (!arguments.length) return startAngle;
- startAngle = x;
- return pie;
+ force.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return force;
};
- pie.endAngle = function(x) {
- if (!arguments.length) return endAngle;
- endAngle = x;
- return pie;
+ force.linkDistance = function(x) {
+ if (!arguments.length) return linkDistance;
+ linkDistance = typeof x === "function" ? x : +x;
+ return force;
};
- return pie;
- };
- var d3_layout_pieSortByValue = {};
- d3.layout.stack = function() {
- var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
- function stack(data, index) {
- var series = data.map(function(d, i) {
- return values.call(stack, d, i);
- });
- var points = series.map(function(d) {
- return d.map(function(v, i) {
- return [ x.call(stack, v, i), y.call(stack, v, i) ];
- });
- });
- var orders = order.call(stack, points, index);
- series = d3.permute(series, orders);
- points = d3.permute(points, orders);
- var offsets = offset.call(stack, points, index);
- var n = series.length, m = series[0].length, i, j, o;
- for (j = 0; j < m; ++j) {
- out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
- for (i = 1; i < n; ++i) {
- out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
- }
- }
- return data;
- }
- stack.values = function(x) {
- if (!arguments.length) return values;
- values = x;
- return stack;
+ force.distance = force.linkDistance;
+ force.linkStrength = function(x) {
+ if (!arguments.length) return linkStrength;
+ linkStrength = typeof x === "function" ? x : +x;
+ return force;
};
- stack.order = function(x) {
- if (!arguments.length) return order;
- order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
- return stack;
+ force.friction = function(x) {
+ if (!arguments.length) return friction;
+ friction = +x;
+ return force;
};
- stack.offset = function(x) {
- if (!arguments.length) return offset;
- offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
- return stack;
+ force.charge = function(x) {
+ if (!arguments.length) return charge;
+ charge = typeof x === "function" ? x : +x;
+ return force;
};
- stack.x = function(z) {
- if (!arguments.length) return x;
- x = z;
- return stack;
+ force.gravity = function(x) {
+ if (!arguments.length) return gravity;
+ gravity = +x;
+ return force;
};
- stack.y = function(z) {
- if (!arguments.length) return y;
- y = z;
- return stack;
+ force.theta = function(x) {
+ if (!arguments.length) return theta;
+ theta = +x;
+ return force;
};
- stack.out = function(z) {
- if (!arguments.length) return out;
- out = z;
- return stack;
+ force.alpha = function(x) {
+ if (!arguments.length) return alpha;
+ x = +x;
+ if (alpha) {
+ if (x > 0) alpha = x; else alpha = 0;
+ } else if (x > 0) {
+ event.start({
+ type: "start",
+ alpha: alpha = x
+ });
+ d3.timer(force.tick);
+ }
+ return force;
};
- return stack;
- };
- function d3_layout_stackX(d) {
- return d.x;
- }
- function d3_layout_stackY(d) {
- return d.y;
- }
- function d3_layout_stackOut(d, y0, y) {
- d.y0 = y0;
- d.y = y;
- }
- var d3_layout_stackOrders = d3.map({
- "inside-out": function(data) {
- var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
- return max[a] - max[b];
- }), top = 0, bottom = 0, tops = [], bottoms = [];
+ force.start = function() {
+ var i, j, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
for (i = 0; i < n; ++i) {
- j = index[i];
- if (top < bottom) {
- top += sums[j];
- tops.push(j);
- } else {
- bottom += sums[j];
- bottoms.push(j);
- }
- }
- return bottoms.reverse().concat(tops);
- },
- reverse: function(data) {
- return d3.range(data.length).reverse();
- },
- "default": d3_layout_stackOrderDefault
- });
- var d3_layout_stackOffsets = d3.map({
- silhouette: function(data) {
- var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
- for (j = 0; j < m; ++j) {
- for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
- if (o > max) max = o;
- sums.push(o);
- }
- for (j = 0; j < m; ++j) {
- y0[j] = (max - sums[j]) / 2;
- }
- return y0;
- },
- wiggle: function(data) {
- var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
- y0[0] = o = o0 = 0;
- for (j = 1; j < m; ++j) {
- for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
- for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
- for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
- s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
- }
- s2 += s3 * data[i][j][1];
- }
- y0[j] = o -= s1 ? s2 / s1 * dx : 0;
- if (o < o0) o0 = o;
+ (o = nodes[i]).index = i;
+ o.weight = 0;
}
- for (j = 0; j < m; ++j) y0[j] -= o0;
- return y0;
- },
- expand: function(data) {
- var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
- for (j = 0; j < m; ++j) {
- for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
- if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
+ for (i = 0; i < m; ++i) {
+ o = links[i];
+ if (typeof o.source == "number") o.source = nodes[o.source];
+ if (typeof o.target == "number") o.target = nodes[o.target];
+ ++o.source.weight;
+ ++o.target.weight;
}
- for (j = 0; j < m; ++j) y0[j] = 0;
- return y0;
- },
- zero: d3_layout_stackOffsetZero
- });
- function d3_layout_stackOrderDefault(data) {
- return d3.range(data.length);
- }
- function d3_layout_stackOffsetZero(data) {
- var j = -1, m = data[0].length, y0 = [];
- while (++j < m) y0[j] = 0;
- return y0;
- }
- function d3_layout_stackMaxIndex(array) {
- var i = 1, j = 0, v = array[0][1], k, n = array.length;
- for (;i < n; ++i) {
- if ((k = array[i][1]) > v) {
- j = i;
- v = k;
+ for (i = 0; i < n; ++i) {
+ o = nodes[i];
+ if (isNaN(o.x)) o.x = position("x", w);
+ if (isNaN(o.y)) o.y = position("y", h);
+ if (isNaN(o.px)) o.px = o.x;
+ if (isNaN(o.py)) o.py = o.y;
}
- }
- return j;
- }
- function d3_layout_stackReduceSum(d) {
- return d.reduce(d3_layout_stackSum, 0);
- }
- function d3_layout_stackSum(p, d) {
- return p + d[1];
- }
- d3.layout.histogram = function() {
- var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
- function histogram(data, i) {
- var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
- while (++i < m) {
- bin = bins[i] = [];
- bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
- bin.y = 0;
+ distances = [];
+ if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
+ strengths = [];
+ if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
+ charges = [];
+ if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
+ function position(dimension, size) {
+ var neighbors = neighbor(i), j = -1, m = neighbors.length, x;
+ while (++j < m) if (!isNaN(x = neighbors[j][dimension])) return x;
+ return Math.random() * size;
}
- if (m > 0) {
- i = -1;
- while (++i < n) {
- x = values[i];
- if (x >= range[0] && x <= range[1]) {
- bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
- bin.y += k;
- bin.push(data[i]);
+ function neighbor() {
+ if (!neighbors) {
+ neighbors = [];
+ for (j = 0; j < n; ++j) {
+ neighbors[j] = [];
+ }
+ for (j = 0; j < m; ++j) {
+ var o = links[j];
+ neighbors[o.source.index].push(o.target);
+ neighbors[o.target.index].push(o.source);
}
}
+ return neighbors[i];
}
- return bins;
- }
- histogram.value = function(x) {
- if (!arguments.length) return valuer;
- valuer = x;
- return histogram;
+ return force.resume();
};
- histogram.range = function(x) {
- if (!arguments.length) return ranger;
- ranger = d3_functor(x);
- return histogram;
+ force.resume = function() {
+ return force.alpha(.1);
};
- histogram.bins = function(x) {
- if (!arguments.length) return binner;
- binner = typeof x === "number" ? function(range) {
- return d3_layout_histogramBinFixed(range, x);
- } : d3_functor(x);
- return histogram;
+ force.stop = function() {
+ return force.alpha(0);
};
- histogram.frequency = function(x) {
- if (!arguments.length) return frequency;
- frequency = !!x;
- return histogram;
+ force.drag = function() {
+ if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
+ if (!arguments.length) return drag;
+ this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
};
- return histogram;
+ function dragmove(d) {
+ d.px = d3.event.x, d.py = d3.event.y;
+ force.resume();
+ }
+ return d3.rebind(force, event, "on");
};
- function d3_layout_histogramBinSturges(range, values) {
- return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+ function d3_layout_forceDragstart(d) {
+ d.fixed |= 2;
}
- function d3_layout_histogramBinFixed(range, n) {
- var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
- while (++x <= n) f[x] = m * x + b;
- return f;
+ function d3_layout_forceDragend(d) {
+ d.fixed &= ~6;
}
- function d3_layout_histogramRange(values) {
- return [ d3.min(values), d3.max(values) ];
+ function d3_layout_forceMouseover(d) {
+ d.fixed |= 4;
+ d.px = d.x, d.py = d.y;
+ }
+ function d3_layout_forceMouseout(d) {
+ d.fixed &= ~4;
+ }
+ function d3_layout_forceAccumulate(quad, alpha, charges) {
+ var cx = 0, cy = 0;
+ quad.charge = 0;
+ if (!quad.leaf) {
+ var nodes = quad.nodes, n = nodes.length, i = -1, c;
+ while (++i < n) {
+ c = nodes[i];
+ if (c == null) continue;
+ d3_layout_forceAccumulate(c, alpha, charges);
+ quad.charge += c.charge;
+ cx += c.charge * c.cx;
+ cy += c.charge * c.cy;
+ }
+ }
+ if (quad.point) {
+ if (!quad.leaf) {
+ quad.point.x += Math.random() - .5;
+ quad.point.y += Math.random() - .5;
+ }
+ var k = alpha * charges[quad.point.index];
+ quad.charge += quad.pointCharge = k;
+ cx += k * quad.point.x;
+ cy += k * quad.point.y;
+ }
+ quad.cx = cx / quad.charge;
+ quad.cy = cy / quad.charge;
}
+ var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1;
d3.layout.hierarchy = function() {
var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
function recurse(node, depth, nodes) {
@@ -4687,2492 +5633,2325 @@ d3 = function() {
});
}));
}
- d3.layout.pack = function() {
- var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];
- function pack(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0];
- root.x = 0;
- root.y = 0;
- d3_layout_treeVisitAfter(root, function(d) {
- d.r = Math.sqrt(d.value);
- });
- d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
- var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);
- if (padding > 0) {
- var dr = padding * k / 2;
- d3_layout_treeVisitAfter(root, function(d) {
- d.r += dr;
- });
- d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
- d3_layout_treeVisitAfter(root, function(d) {
- d.r -= dr;
- });
- k = Math.max(2 * root.r / w, 2 * root.r / h);
- }
- d3_layout_packTransform(root, w / 2, h / 2, 1 / k);
- return nodes;
- }
- pack.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return pack;
- };
- pack.padding = function(_) {
- if (!arguments.length) return padding;
- padding = +_;
- return pack;
- };
- return d3_layout_hierarchyRebind(pack, hierarchy);
- };
- function d3_layout_packSort(a, b) {
- return a.value - b.value;
- }
- function d3_layout_packInsert(a, b) {
- var c = a._pack_next;
- a._pack_next = b;
- b._pack_prev = a;
- b._pack_next = c;
- c._pack_prev = b;
- }
- function d3_layout_packSplice(a, b) {
- a._pack_next = b;
- b._pack_prev = a;
- }
- function d3_layout_packIntersects(a, b) {
- var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
- return dr * dr - dx * dx - dy * dy > .001;
- }
- function d3_layout_packSiblings(node) {
- if (!(nodes = node.children) || !(n = nodes.length)) return;
- var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
- function bound(node) {
- xMin = Math.min(node.x - node.r, xMin);
- xMax = Math.max(node.x + node.r, xMax);
- yMin = Math.min(node.y - node.r, yMin);
- yMax = Math.max(node.y + node.r, yMax);
- }
- nodes.forEach(d3_layout_packLink);
- a = nodes[0];
- a.x = -a.r;
- a.y = 0;
- bound(a);
- if (n > 1) {
- b = nodes[1];
- b.x = b.r;
- b.y = 0;
- bound(b);
- if (n > 2) {
- c = nodes[2];
- d3_layout_packPlace(a, b, c);
- bound(c);
- d3_layout_packInsert(a, c);
- a._pack_prev = c;
- d3_layout_packInsert(c, b);
- b = a._pack_next;
- for (i = 3; i < n; i++) {
- d3_layout_packPlace(a, b, c = nodes[i]);
- var isect = 0, s1 = 1, s2 = 1;
- for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
- if (d3_layout_packIntersects(j, c)) {
- isect = 1;
- break;
- }
- }
- if (isect == 1) {
- for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
- if (d3_layout_packIntersects(k, c)) {
- break;
- }
- }
- }
- if (isect) {
- if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
- i--;
- } else {
- d3_layout_packInsert(a, c);
- b = c;
- bound(c);
- }
- }
- }
- }
- var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
- for (i = 0; i < n; i++) {
- c = nodes[i];
- c.x -= cx;
- c.y -= cy;
- cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
- }
- node.r = cr;
- nodes.forEach(d3_layout_packUnlink);
- }
- function d3_layout_packLink(node) {
- node._pack_next = node._pack_prev = node;
- }
- function d3_layout_packUnlink(node) {
- delete node._pack_next;
- delete node._pack_prev;
- }
- function d3_layout_packTransform(node, x, y, k) {
- var children = node.children;
- node.x = x += k * node.x;
- node.y = y += k * node.y;
- node.r *= k;
- if (children) {
- var i = -1, n = children.length;
- while (++i < n) d3_layout_packTransform(children[i], x, y, k);
- }
- }
- function d3_layout_packPlace(a, b, c) {
- var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
- if (db && (dx || dy)) {
- var da = b.r + c.r, dc = dx * dx + dy * dy;
- da *= da;
- db *= db;
- var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
- c.x = a.x + x * dx + y * dy;
- c.y = a.y + x * dy - y * dx;
- } else {
- c.x = a.x + db;
- c.y = a.y;
- }
- }
- d3.layout.cluster = function() {
- var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
- function cluster(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
- d3_layout_treeVisitAfter(root, function(node) {
- var children = node.children;
- if (children && children.length) {
- node.x = d3_layout_clusterX(children);
- node.y = d3_layout_clusterY(children);
- } else {
- node.x = previousNode ? x += separation(node, previousNode) : 0;
- node.y = 0;
- previousNode = node;
+ d3.layout.partition = function() {
+ var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
+ function position(node, x, dx, dy) {
+ var children = node.children;
+ node.x = x;
+ node.y = node.depth * dy;
+ node.dx = dx;
+ node.dy = dy;
+ if (children && (n = children.length)) {
+ var i = -1, n, c, d;
+ dx = node.value ? dx / node.value : 0;
+ while (++i < n) {
+ position(c = children[i], x, d = c.value * dx, dy);
+ x += d;
}
- });
- var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
- d3_layout_treeVisitAfter(root, function(node) {
- node.x = (node.x - x0) / (x1 - x0) * size[0];
- node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
- });
+ }
+ }
+ function depth(node) {
+ var children = node.children, d = 0;
+ if (children && (n = children.length)) {
+ var i = -1, n;
+ while (++i < n) d = Math.max(d, depth(children[i]));
+ }
+ return 1 + d;
+ }
+ function partition(d, i) {
+ var nodes = hierarchy.call(this, d, i);
+ position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
return nodes;
}
- cluster.separation = function(x) {
- if (!arguments.length) return separation;
- separation = x;
- return cluster;
- };
- cluster.size = function(x) {
+ partition.size = function(x) {
if (!arguments.length) return size;
size = x;
- return cluster;
+ return partition;
};
- return d3_layout_hierarchyRebind(cluster, hierarchy);
+ return d3_layout_hierarchyRebind(partition, hierarchy);
};
- function d3_layout_clusterY(children) {
- return 1 + d3.max(children, function(child) {
- return child.y;
- });
- }
- function d3_layout_clusterX(children) {
- return children.reduce(function(x, child) {
- return x + child.x;
- }, 0) / children.length;
- }
- function d3_layout_clusterLeft(node) {
- var children = node.children;
- return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
- }
- function d3_layout_clusterRight(node) {
- var children = node.children, n;
- return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
- }
- d3.layout.tree = function() {
- var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
- function tree(d, i) {
- var nodes = hierarchy.call(this, d, i), root = nodes[0];
- function firstWalk(node, previousSibling) {
- var children = node.children, layout = node._tree;
- if (children && (n = children.length)) {
- var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
- while (++i < n) {
- child = children[i];
- firstWalk(child, previousChild);
- ancestor = apportion(child, previousChild, ancestor);
- previousChild = child;
- }
- d3_layout_treeShift(node);
- var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
- if (previousSibling) {
- layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
- layout.mod = layout.prelim - midpoint;
- } else {
- layout.prelim = midpoint;
- }
- } else {
- if (previousSibling) {
- layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
- }
- }
- }
- function secondWalk(node, x) {
- node.x = node._tree.prelim + x;
- var children = node.children;
- if (children && (n = children.length)) {
- var i = -1, n;
- x += node._tree.mod;
- while (++i < n) {
- secondWalk(children[i], x);
- }
- }
- }
- function apportion(node, previousSibling, ancestor) {
- if (previousSibling) {
- var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
- while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
- vom = d3_layout_treeLeft(vom);
- vop = d3_layout_treeRight(vop);
- vop._tree.ancestor = node;
- shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
- if (shift > 0) {
- d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
- sip += shift;
- sop += shift;
- }
- sim += vim._tree.mod;
- sip += vip._tree.mod;
- som += vom._tree.mod;
- sop += vop._tree.mod;
- }
- if (vim && !d3_layout_treeRight(vop)) {
- vop._tree.thread = vim;
- vop._tree.mod += sim - sop;
- }
- if (vip && !d3_layout_treeLeft(vom)) {
- vom._tree.thread = vip;
- vom._tree.mod += sip - som;
- ancestor = node;
- }
- }
- return ancestor;
- }
- d3_layout_treeVisitAfter(root, function(node, previousSibling) {
- node._tree = {
- ancestor: node,
- prelim: 0,
- mod: 0,
- change: 0,
- shift: 0,
- number: previousSibling ? previousSibling._tree.number + 1 : 0
- };
+ d3.layout.pie = function() {
+ var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = 2 * π;
+ function pie(data) {
+ var values = data.map(function(d, i) {
+ return +value.call(pie, d, i);
});
- firstWalk(root);
- secondWalk(root, -root._tree.prelim);
- var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
- d3_layout_treeVisitAfter(root, function(node) {
- node.x = (node.x - x0) / (x1 - x0) * size[0];
- node.y = node.depth / y1 * size[1];
- delete node._tree;
+ var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
+ var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
+ var index = d3.range(data.length);
+ if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
+ return values[j] - values[i];
+ } : function(i, j) {
+ return sort(data[i], data[j]);
});
- return nodes;
+ var arcs = [];
+ index.forEach(function(i) {
+ var d;
+ arcs[i] = {
+ data: data[i],
+ value: d = values[i],
+ startAngle: a,
+ endAngle: a += d * k
+ };
+ });
+ return arcs;
}
- tree.separation = function(x) {
- if (!arguments.length) return separation;
- separation = x;
- return tree;
+ pie.value = function(x) {
+ if (!arguments.length) return value;
+ value = x;
+ return pie;
};
- tree.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return tree;
+ pie.sort = function(x) {
+ if (!arguments.length) return sort;
+ sort = x;
+ return pie;
};
- return d3_layout_hierarchyRebind(tree, hierarchy);
+ pie.startAngle = function(x) {
+ if (!arguments.length) return startAngle;
+ startAngle = x;
+ return pie;
+ };
+ pie.endAngle = function(x) {
+ if (!arguments.length) return endAngle;
+ endAngle = x;
+ return pie;
+ };
+ return pie;
};
- function d3_layout_treeSeparation(a, b) {
- return a.parent == b.parent ? 1 : 2;
- }
- function d3_layout_treeLeft(node) {
- var children = node.children;
- return children && children.length ? children[0] : node._tree.thread;
- }
- function d3_layout_treeRight(node) {
- var children = node.children, n;
- return children && (n = children.length) ? children[n - 1] : node._tree.thread;
- }
- function d3_layout_treeSearch(node, compare) {
- var children = node.children;
- if (children && (n = children.length)) {
- var child, n, i = -1;
- while (++i < n) {
- if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
- node = child;
+ var d3_layout_pieSortByValue = {};
+ d3.layout.stack = function() {
+ var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
+ function stack(data, index) {
+ var series = data.map(function(d, i) {
+ return values.call(stack, d, i);
+ });
+ var points = series.map(function(d) {
+ return d.map(function(v, i) {
+ return [ x.call(stack, v, i), y.call(stack, v, i) ];
+ });
+ });
+ var orders = order.call(stack, points, index);
+ series = d3.permute(series, orders);
+ points = d3.permute(points, orders);
+ var offsets = offset.call(stack, points, index);
+ var n = series.length, m = series[0].length, i, j, o;
+ for (j = 0; j < m; ++j) {
+ out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
+ for (i = 1; i < n; ++i) {
+ out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
}
}
+ return data;
}
- return node;
- }
- function d3_layout_treeRightmost(a, b) {
- return a.x - b.x;
+ stack.values = function(x) {
+ if (!arguments.length) return values;
+ values = x;
+ return stack;
+ };
+ stack.order = function(x) {
+ if (!arguments.length) return order;
+ order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
+ return stack;
+ };
+ stack.offset = function(x) {
+ if (!arguments.length) return offset;
+ offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
+ return stack;
+ };
+ stack.x = function(z) {
+ if (!arguments.length) return x;
+ x = z;
+ return stack;
+ };
+ stack.y = function(z) {
+ if (!arguments.length) return y;
+ y = z;
+ return stack;
+ };
+ stack.out = function(z) {
+ if (!arguments.length) return out;
+ out = z;
+ return stack;
+ };
+ return stack;
+ };
+ function d3_layout_stackX(d) {
+ return d.x;
}
- function d3_layout_treeLeftmost(a, b) {
- return b.x - a.x;
+ function d3_layout_stackY(d) {
+ return d.y;
}
- function d3_layout_treeDeepest(a, b) {
- return a.depth - b.depth;
+ function d3_layout_stackOut(d, y0, y) {
+ d.y0 = y0;
+ d.y = y;
}
- function d3_layout_treeVisitAfter(node, callback) {
- function visit(node, previousSibling) {
- var children = node.children;
- if (children && (n = children.length)) {
- var child, previousChild = null, i = -1, n;
- while (++i < n) {
- child = children[i];
- visit(child, previousChild);
- previousChild = child;
+ var d3_layout_stackOrders = d3.map({
+ "inside-out": function(data) {
+ var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
+ return max[a] - max[b];
+ }), top = 0, bottom = 0, tops = [], bottoms = [];
+ for (i = 0; i < n; ++i) {
+ j = index[i];
+ if (top < bottom) {
+ top += sums[j];
+ tops.push(j);
+ } else {
+ bottom += sums[j];
+ bottoms.push(j);
}
}
- callback(node, previousSibling);
- }
- visit(node, null);
- }
- function d3_layout_treeShift(node) {
- var shift = 0, change = 0, children = node.children, i = children.length, child;
- while (--i >= 0) {
- child = children[i]._tree;
- child.prelim += shift;
- child.mod += shift;
- shift += child.shift + (change += child.change);
- }
- }
- function d3_layout_treeMove(ancestor, node, shift) {
- ancestor = ancestor._tree;
- node = node._tree;
- var change = shift / (node.number - ancestor.number);
- ancestor.change += change;
- node.change -= change;
- node.shift += shift;
- node.prelim += shift;
- node.mod += shift;
- }
- function d3_layout_treeAncestor(vim, node, ancestor) {
- return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
- }
- d3.layout.treemap = function() {
- var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
- function scale(children, k) {
- var i = -1, n = children.length, child, area;
- while (++i < n) {
- area = (child = children[i]).value * (k < 0 ? 0 : k);
- child.area = isNaN(area) || area <= 0 ? 0 : area;
+ return bottoms.reverse().concat(tops);
+ },
+ reverse: function(data) {
+ return d3.range(data.length).reverse();
+ },
+ "default": d3_layout_stackOrderDefault
+ });
+ var d3_layout_stackOffsets = d3.map({
+ silhouette: function(data) {
+ var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
+ for (j = 0; j < m; ++j) {
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+ if (o > max) max = o;
+ sums.push(o);
}
- }
- function squarify(node) {
- var children = node.children;
- if (children && children.length) {
- var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
- scale(remaining, rect.dx * rect.dy / node.value);
- row.area = 0;
- while ((n = remaining.length) > 0) {
- row.push(child = remaining[n - 1]);
- row.area += child.area;
- if (mode !== "squarify" || (score = worst(row, u)) <= best) {
- remaining.pop();
- best = score;
- } else {
- row.area -= row.pop().area;
- position(row, u, rect, false);
- u = Math.min(rect.dx, rect.dy);
- row.length = row.area = 0;
- best = Infinity;
- }
- }
- if (row.length) {
- position(row, u, rect, true);
- row.length = row.area = 0;
- }
- children.forEach(squarify);
+ for (j = 0; j < m; ++j) {
+ y0[j] = (max - sums[j]) / 2;
}
- }
- function stickify(node) {
- var children = node.children;
- if (children && children.length) {
- var rect = pad(node), remaining = children.slice(), child, row = [];
- scale(remaining, rect.dx * rect.dy / node.value);
- row.area = 0;
- while (child = remaining.pop()) {
- row.push(child);
- row.area += child.area;
- if (child.z != null) {
- position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
- row.length = row.area = 0;
+ return y0;
+ },
+ wiggle: function(data) {
+ var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
+ y0[0] = o = o0 = 0;
+ for (j = 1; j < m; ++j) {
+ for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
+ for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
+ for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
+ s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
}
+ s2 += s3 * data[i][j][1];
}
- children.forEach(stickify);
+ y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+ if (o < o0) o0 = o;
}
- }
- function worst(row, u) {
- var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
- while (++i < n) {
- if (!(r = row[i].area)) continue;
- if (r < rmin) rmin = r;
- if (r > rmax) rmax = r;
+ for (j = 0; j < m; ++j) y0[j] -= o0;
+ return y0;
+ },
+ expand: function(data) {
+ var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
+ for (j = 0; j < m; ++j) {
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+ if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
}
- s *= s;
- u *= u;
- return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
- }
- function position(row, u, rect, flush) {
- var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
- if (u == rect.dx) {
- if (flush || v > rect.dy) v = rect.dy;
- while (++i < n) {
- o = row[i];
- o.x = x;
- o.y = y;
- o.dy = v;
- x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
- }
- o.z = true;
- o.dx += rect.x + rect.dx - x;
- rect.y += v;
- rect.dy -= v;
- } else {
- if (flush || v > rect.dx) v = rect.dx;
- while (++i < n) {
- o = row[i];
- o.x = x;
- o.y = y;
- o.dx = v;
- y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
- }
- o.z = false;
- o.dy += rect.y + rect.dy - y;
- rect.x += v;
- rect.dx -= v;
+ for (j = 0; j < m; ++j) y0[j] = 0;
+ return y0;
+ },
+ zero: d3_layout_stackOffsetZero
+ });
+ function d3_layout_stackOrderDefault(data) {
+ return d3.range(data.length);
+ }
+ function d3_layout_stackOffsetZero(data) {
+ var j = -1, m = data[0].length, y0 = [];
+ while (++j < m) y0[j] = 0;
+ return y0;
+ }
+ function d3_layout_stackMaxIndex(array) {
+ var i = 1, j = 0, v = array[0][1], k, n = array.length;
+ for (;i < n; ++i) {
+ if ((k = array[i][1]) > v) {
+ j = i;
+ v = k;
}
}
- function treemap(d) {
- var nodes = stickies || hierarchy(d), root = nodes[0];
- root.x = 0;
- root.y = 0;
- root.dx = size[0];
- root.dy = size[1];
- if (stickies) hierarchy.revalue(root);
- scale([ root ], root.dx * root.dy / root.value);
- (stickies ? stickify : squarify)(root);
- if (sticky) stickies = nodes;
- return nodes;
- }
- treemap.size = function(x) {
- if (!arguments.length) return size;
- size = x;
- return treemap;
- };
- treemap.padding = function(x) {
- if (!arguments.length) return padding;
- function padFunction(node) {
- var p = x.call(treemap, node, node.depth);
- return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
+ return j;
+ }
+ function d3_layout_stackReduceSum(d) {
+ return d.reduce(d3_layout_stackSum, 0);
+ }
+ function d3_layout_stackSum(p, d) {
+ return p + d[1];
+ }
+ d3.layout.histogram = function() {
+ var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
+ function histogram(data, i) {
+ var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
+ while (++i < m) {
+ bin = bins[i] = [];
+ bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
+ bin.y = 0;
}
- function padConstant(node) {
- return d3_layout_treemapPad(node, x);
+ if (m > 0) {
+ i = -1;
+ while (++i < n) {
+ x = values[i];
+ if (x >= range[0] && x <= range[1]) {
+ bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
+ bin.y += k;
+ bin.push(data[i]);
+ }
+ }
}
- var type;
- pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ],
- padConstant) : padConstant;
- return treemap;
- };
- treemap.round = function(x) {
- if (!arguments.length) return round != Number;
- round = x ? Math.round : Number;
- return treemap;
+ return bins;
+ }
+ histogram.value = function(x) {
+ if (!arguments.length) return valuer;
+ valuer = x;
+ return histogram;
};
- treemap.sticky = function(x) {
- if (!arguments.length) return sticky;
- sticky = x;
- stickies = null;
- return treemap;
+ histogram.range = function(x) {
+ if (!arguments.length) return ranger;
+ ranger = d3_functor(x);
+ return histogram;
};
- treemap.ratio = function(x) {
- if (!arguments.length) return ratio;
- ratio = x;
- return treemap;
+ histogram.bins = function(x) {
+ if (!arguments.length) return binner;
+ binner = typeof x === "number" ? function(range) {
+ return d3_layout_histogramBinFixed(range, x);
+ } : d3_functor(x);
+ return histogram;
};
- treemap.mode = function(x) {
- if (!arguments.length) return mode;
- mode = x + "";
- return treemap;
+ histogram.frequency = function(x) {
+ if (!arguments.length) return frequency;
+ frequency = !!x;
+ return histogram;
};
- return d3_layout_hierarchyRebind(treemap, hierarchy);
+ return histogram;
};
- function d3_layout_treemapPadNull(node) {
- return {
- x: node.x,
- y: node.y,
- dx: node.dx,
- dy: node.dy
- };
+ function d3_layout_histogramBinSturges(range, values) {
+ return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
}
- function d3_layout_treemapPad(node, padding) {
- var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
- if (dx < 0) {
- x += dx / 2;
- dx = 0;
- }
- if (dy < 0) {
- y += dy / 2;
- dy = 0;
- }
- return {
- x: x,
- y: y,
- dx: dx,
- dy: dy
- };
+ function d3_layout_histogramBinFixed(range, n) {
+ var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
+ while (++x <= n) f[x] = m * x + b;
+ return f;
}
- function d3_dsv(delimiter, mimeType) {
- var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
- function dsv(url, callback) {
- return d3.xhr(url, mimeType, callback).response(response);
- }
- function response(request) {
- return dsv.parse(request.responseText);
- }
- dsv.parse = function(text) {
- var o;
- return dsv.parseRows(text, function(row) {
- if (o) return o(row);
- o = new Function("d", "return {" + row.map(function(name, i) {
- return JSON.stringify(name) + ": d[" + i + "]";
- }).join(",") + "}");
- });
- };
- dsv.parseRows = function(text, f) {
- var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
- function token() {
- if (I >= N) return EOF;
- if (eol) return eol = false, EOL;
- var j = I;
- if (text.charCodeAt(j) === 34) {
- var i = j;
- while (i++ < N) {
- if (text.charCodeAt(i) === 34) {
- if (text.charCodeAt(i + 1) !== 34) break;
- ++i;
- }
+ function d3_layout_histogramRange(values) {
+ return [ d3.min(values), d3.max(values) ];
+ }
+ d3.layout.tree = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
+ function tree(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0];
+ function firstWalk(node, previousSibling) {
+ var children = node.children, layout = node._tree;
+ if (children && (n = children.length)) {
+ var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
+ while (++i < n) {
+ child = children[i];
+ firstWalk(child, previousChild);
+ ancestor = apportion(child, previousChild, ancestor);
+ previousChild = child;
}
- I = i + 2;
- var c = text.charCodeAt(i + 1);
- if (c === 13) {
- eol = true;
- if (text.charCodeAt(i + 2) === 10) ++I;
- } else if (c === 10) {
- eol = true;
+ d3_layout_treeShift(node);
+ var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
+ if (previousSibling) {
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+ layout.mod = layout.prelim - midpoint;
+ } else {
+ layout.prelim = midpoint;
+ }
+ } else {
+ if (previousSibling) {
+ layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
}
- return text.substring(j + 1, i).replace(/""/g, '"');
}
- while (I < N) {
- var c = text.charCodeAt(I++), k = 1;
- if (c === 10) eol = true; else if (c === 13) {
- eol = true;
- if (text.charCodeAt(I) === 10) ++I, ++k;
- } else if (c !== delimiterCode) continue;
- return text.substring(j, I - k);
+ }
+ function secondWalk(node, x) {
+ node.x = node._tree.prelim + x;
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var i = -1, n;
+ x += node._tree.mod;
+ while (++i < n) {
+ secondWalk(children[i], x);
+ }
}
- return text.substring(j);
}
- while ((t = token()) !== EOF) {
- var a = [];
- while (t !== EOL && t !== EOF) {
- a.push(t);
- t = token();
+ function apportion(node, previousSibling, ancestor) {
+ if (previousSibling) {
+ var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
+ while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
+ vom = d3_layout_treeLeft(vom);
+ vop = d3_layout_treeRight(vop);
+ vop._tree.ancestor = node;
+ shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
+ if (shift > 0) {
+ d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
+ sip += shift;
+ sop += shift;
+ }
+ sim += vim._tree.mod;
+ sip += vip._tree.mod;
+ som += vom._tree.mod;
+ sop += vop._tree.mod;
+ }
+ if (vim && !d3_layout_treeRight(vop)) {
+ vop._tree.thread = vim;
+ vop._tree.mod += sim - sop;
+ }
+ if (vip && !d3_layout_treeLeft(vom)) {
+ vom._tree.thread = vip;
+ vom._tree.mod += sip - som;
+ ancestor = node;
+ }
}
- if (f && !(a = f(a, n++))) continue;
- rows.push(a);
+ return ancestor;
}
- return rows;
- };
- dsv.format = function(rows) {
- return rows.map(formatRow).join("\n");
- };
- function formatRow(row) {
- return row.map(formatValue).join(delimiter);
- }
- function formatValue(text) {
- return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
- }
- return dsv;
- }
- d3.csv = d3_dsv(",", "text/csv");
- d3.tsv = d3_dsv(" ", "text/tab-separated-values");
- d3.geo = {};
- d3.geo.stream = function(object, listener) {
- if (d3_geo_streamObjectType.hasOwnProperty(object.type)) {
- d3_geo_streamObjectType[object.type](object, listener);
- } else {
- d3_geo_streamGeometry(object, listener);
- }
- };
- function d3_geo_streamGeometry(geometry, listener) {
- if (d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
- d3_geo_streamGeometryType[geometry.type](geometry, listener);
- }
- }
- var d3_geo_streamObjectType = {
- Feature: function(feature, listener) {
- d3_geo_streamGeometry(feature.geometry, listener);
- },
- FeatureCollection: function(object, listener) {
- var features = object.features, i = -1, n = features.length;
- while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
- }
- };
- var d3_geo_streamGeometryType = {
- Sphere: function(object, listener) {
- listener.sphere();
- },
- Point: function(object, listener) {
- var coordinate = object.coordinates;
- listener.point(coordinate[0], coordinate[1]);
- },
- MultiPoint: function(object, listener) {
- var coordinates = object.coordinates, i = -1, n = coordinates.length, coordinate;
- while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
- },
- LineString: function(object, listener) {
- d3_geo_streamLine(object.coordinates, listener, 0);
- },
- MultiLineString: function(object, listener) {
- var coordinates = object.coordinates, i = -1, n = coordinates.length;
- while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
- },
- Polygon: function(object, listener) {
- d3_geo_streamPolygon(object.coordinates, listener);
- },
- MultiPolygon: function(object, listener) {
- var coordinates = object.coordinates, i = -1, n = coordinates.length;
- while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
- },
- GeometryCollection: function(object, listener) {
- var geometries = object.geometries, i = -1, n = geometries.length;
- while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
+ d3_layout_treeVisitAfter(root, function(node, previousSibling) {
+ node._tree = {
+ ancestor: node,
+ prelim: 0,
+ mod: 0,
+ change: 0,
+ shift: 0,
+ number: previousSibling ? previousSibling._tree.number + 1 : 0
+ };
+ });
+ firstWalk(root);
+ secondWalk(root, -root._tree.prelim);
+ var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
+ d3_layout_treeVisitAfter(root, function(node) {
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
+ node.y = node.depth / y1 * size[1];
+ delete node._tree;
+ });
+ return nodes;
}
+ tree.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return tree;
+ };
+ tree.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return tree;
+ };
+ return d3_layout_hierarchyRebind(tree, hierarchy);
};
- function d3_geo_streamLine(coordinates, listener, closed) {
- var i = -1, n = coordinates.length - closed, coordinate;
- listener.lineStart();
- while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1]);
- listener.lineEnd();
- }
- function d3_geo_streamPolygon(coordinates, listener) {
- var i = -1, n = coordinates.length;
- listener.polygonStart();
- while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
- listener.polygonEnd();
- }
- function d3_geo_spherical(cartesian) {
- return [ Math.atan2(cartesian[1], cartesian[0]), Math.asin(Math.max(-1, Math.min(1, cartesian[2]))) ];
- }
- function d3_geo_sphericalEqual(a, b) {
- return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
+ function d3_layout_treeSeparation(a, b) {
+ return a.parent == b.parent ? 1 : 2;
}
- function d3_geo_cartesian(spherical) {
- var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
- return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+ function d3_layout_treeLeft(node) {
+ var children = node.children;
+ return children && children.length ? children[0] : node._tree.thread;
}
- function d3_geo_cartesianDot(a, b) {
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ function d3_layout_treeRight(node) {
+ var children = node.children, n;
+ return children && (n = children.length) ? children[n - 1] : node._tree.thread;
}
- function d3_geo_cartesianCross(a, b) {
- return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+ function d3_layout_treeSearch(node, compare) {
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var child, n, i = -1;
+ while (++i < n) {
+ if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
+ node = child;
+ }
+ }
+ }
+ return node;
}
- function d3_geo_cartesianAdd(a, b) {
- a[0] += b[0];
- a[1] += b[1];
- a[2] += b[2];
+ function d3_layout_treeRightmost(a, b) {
+ return a.x - b.x;
}
- function d3_geo_cartesianScale(vector, k) {
- return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+ function d3_layout_treeLeftmost(a, b) {
+ return b.x - a.x;
}
- function d3_geo_cartesianNormalize(d) {
- var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
- d[0] /= l;
- d[1] /= l;
- d[2] /= l;
+ function d3_layout_treeDeepest(a, b) {
+ return a.depth - b.depth;
}
- function d3_geo_resample(project) {
- var δ2 = .5, maxDepth = 16;
- function resample(stream) {
- var λ0, x0, y0, a0, b0, c0;
- var resample = {
- point: point,
- lineStart: lineStart,
- lineEnd: lineEnd,
- polygonStart: function() {
- stream.polygonStart();
- resample.lineStart = polygonLineStart;
- },
- polygonEnd: function() {
- stream.polygonEnd();
- resample.lineStart = lineStart;
- }
- };
- function point(x, y) {
- x = project(x, y);
- stream.point(x[0], x[1]);
- }
- function lineStart() {
- x0 = NaN;
- resample.point = linePoint;
- stream.lineStart();
- }
- function linePoint(λ, φ) {
- var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
- resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
- stream.point(x0, y0);
- }
- function lineEnd() {
- resample.point = point;
- stream.lineEnd();
- }
- function polygonLineStart() {
- var λ00, φ00, x00, y00, a00, b00, c00;
- lineStart();
- resample.point = function(λ, φ) {
- linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
- resample.point = linePoint;
- };
- resample.lineEnd = function() {
- resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
- resample.lineEnd = lineEnd;
- lineEnd();
- };
- }
- return resample;
- }
- function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
- var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
- if (d2 > 4 * δ2 && depth--) {
- var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = Math.abs(Math.abs(c) - 1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
- if (dz * dz / d2 > δ2 || Math.abs((dx * dx2 + dy * dy2) / d2 - .5) > .3) {
- resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
- stream.point(x2, y2);
- resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+ function d3_layout_treeVisitAfter(node, callback) {
+ function visit(node, previousSibling) {
+ var children = node.children;
+ if (children && (n = children.length)) {
+ var child, previousChild = null, i = -1, n;
+ while (++i < n) {
+ child = children[i];
+ visit(child, previousChild);
+ previousChild = child;
}
}
+ callback(node, previousSibling);
}
- resample.precision = function(_) {
- if (!arguments.length) return Math.sqrt(δ2);
- maxDepth = (δ2 = _ * _) > 0 && 16;
- return resample;
- };
- return resample;
+ visit(node, null);
}
- d3.geo.albersUsa = function() {
- var lower48 = d3.geo.albers();
- var alaska = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 60 ]).parallels([ 55, 65 ]);
- var hawaii = d3.geo.albers().rotate([ 160, 0 ]).center([ 0, 20 ]).parallels([ 8, 18 ]);
- var puertoRico = d3.geo.albers().rotate([ 60, 0 ]).center([ 0, 10 ]).parallels([ 8, 18 ]);
- function albersUsa(coordinates) {
- return projection(coordinates)(coordinates);
- }
- function projection(point) {
- var lon = point[0], lat = point[1];
- return lat > 50 ? alaska : lon < -140 ? hawaii : lat < 21 ? puertoRico : lower48;
- }
- albersUsa.scale = function(x) {
- if (!arguments.length) return lower48.scale();
- lower48.scale(x);
- alaska.scale(x * .6);
- hawaii.scale(x);
- puertoRico.scale(x * 1.5);
- return albersUsa.translate(lower48.translate());
- };
- albersUsa.translate = function(x) {
- if (!arguments.length) return lower48.translate();
- var dz = lower48.scale(), dx = x[0], dy = x[1];
- lower48.translate(x);
- alaska.translate([ dx - .4 * dz, dy + .17 * dz ]);
- hawaii.translate([ dx - .19 * dz, dy + .2 * dz ]);
- puertoRico.translate([ dx + .58 * dz, dy + .43 * dz ]);
- return albersUsa;
- };
- return albersUsa.scale(lower48.scale());
- };
- function d3_geo_albers(φ0, φ1) {
- var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
- function albers(λ, φ) {
- var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
- return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+ function d3_layout_treeShift(node) {
+ var shift = 0, change = 0, children = node.children, i = children.length, child;
+ while (--i >= 0) {
+ child = children[i]._tree;
+ child.prelim += shift;
+ child.mod += shift;
+ shift += child.shift + (change += child.change);
}
- albers.invert = function(x, y) {
- var ρ0_y = ρ0 - y;
- return [ Math.atan2(x, ρ0_y) / n, Math.asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
- };
- return albers;
}
- (d3.geo.albers = function() {
- var φ0 = 29.5 * d3_radians, φ1 = 45.5 * d3_radians, m = d3_geo_projectionMutator(d3_geo_albers), p = m(φ0, φ1);
- p.parallels = function(_) {
- if (!arguments.length) return [ φ0 * d3_degrees, φ1 * d3_degrees ];
- return m(φ0 = _[0] * d3_radians, φ1 = _[1] * d3_radians);
- };
- return p.rotate([ 98, 0 ]).center([ 0, 38 ]).scale(1e3);
- }).raw = d3_geo_albers;
- var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
- return Math.sqrt(2 / (1 + cosλcosφ));
- }, function(ρ) {
- return 2 * Math.asin(ρ / 2);
- });
- (d3.geo.azimuthalEqualArea = function() {
- return d3_geo_projection(d3_geo_azimuthalEqualArea);
- }).raw = d3_geo_azimuthalEqualArea;
- var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
- var c = Math.acos(cosλcosφ);
- return c && c / Math.sin(c);
- }, d3_identity);
- (d3.geo.azimuthalEquidistant = function() {
- return d3_geo_projection(d3_geo_azimuthalEquidistant);
- }).raw = d3_geo_azimuthalEquidistant;
- d3.geo.bounds = d3_geo_bounds(d3_identity);
- function d3_geo_bounds(projectStream) {
- var x0, y0, x1, y1;
- var bound = {
- point: boundPoint,
- lineStart: d3_noop,
- lineEnd: d3_noop,
- polygonStart: function() {
- bound.lineEnd = boundPolygonLineEnd;
- },
- polygonEnd: function() {
- bound.point = boundPoint;
+ function d3_layout_treeMove(ancestor, node, shift) {
+ ancestor = ancestor._tree;
+ node = node._tree;
+ var change = shift / (node.number - ancestor.number);
+ ancestor.change += change;
+ node.change -= change;
+ node.shift += shift;
+ node.prelim += shift;
+ node.mod += shift;
+ }
+ function d3_layout_treeAncestor(vim, node, ancestor) {
+ return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
+ }
+ d3.layout.pack = function() {
+ var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ];
+ function pack(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0];
+ root.x = 0;
+ root.y = 0;
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r = Math.sqrt(d.value);
+ });
+ d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+ var w = size[0], h = size[1], k = Math.max(2 * root.r / w, 2 * root.r / h);
+ if (padding > 0) {
+ var dr = padding * k / 2;
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r += dr;
+ });
+ d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+ d3_layout_treeVisitAfter(root, function(d) {
+ d.r -= dr;
+ });
+ k = Math.max(2 * root.r / w, 2 * root.r / h);
}
- };
- function boundPoint(x, y) {
- if (x < x0) x0 = x;
- if (x > x1) x1 = x;
- if (y < y0) y0 = y;
- if (y > y1) y1 = y;
- }
- function boundPolygonLineEnd() {
- bound.point = bound.lineEnd = d3_noop;
+ d3_layout_packTransform(root, w / 2, h / 2, 1 / k);
+ return nodes;
}
- return function(feature) {
- y1 = x1 = -(x0 = y0 = Infinity);
- d3.geo.stream(feature, projectStream(bound));
- return [ [ x0, y0 ], [ x1, y1 ] ];
+ pack.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return pack;
+ };
+ pack.padding = function(_) {
+ if (!arguments.length) return padding;
+ padding = +_;
+ return pack;
};
+ return d3_layout_hierarchyRebind(pack, hierarchy);
+ };
+ function d3_layout_packSort(a, b) {
+ return a.value - b.value;
}
- d3.geo.centroid = function(object) {
- d3_geo_centroidDimension = d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- d3.geo.stream(object, d3_geo_centroid);
- var m;
- if (d3_geo_centroidW && Math.abs(m = Math.sqrt(d3_geo_centroidX * d3_geo_centroidX + d3_geo_centroidY * d3_geo_centroidY + d3_geo_centroidZ * d3_geo_centroidZ)) > ε) {
- return [ Math.atan2(d3_geo_centroidY, d3_geo_centroidX) * d3_degrees, Math.asin(Math.max(-1, Math.min(1, d3_geo_centroidZ / m))) * d3_degrees ];
+ function d3_layout_packInsert(a, b) {
+ var c = a._pack_next;
+ a._pack_next = b;
+ b._pack_prev = a;
+ b._pack_next = c;
+ c._pack_prev = b;
+ }
+ function d3_layout_packSplice(a, b) {
+ a._pack_next = b;
+ b._pack_prev = a;
+ }
+ function d3_layout_packIntersects(a, b) {
+ var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
+ return dr * dr - dx * dx - dy * dy > .001;
+ }
+ function d3_layout_packSiblings(node) {
+ if (!(nodes = node.children) || !(n = nodes.length)) return;
+ var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
+ function bound(node) {
+ xMin = Math.min(node.x - node.r, xMin);
+ xMax = Math.max(node.x + node.r, xMax);
+ yMin = Math.min(node.y - node.r, yMin);
+ yMax = Math.max(node.y + node.r, yMax);
}
- };
- var d3_geo_centroidDimension, d3_geo_centroidW, d3_geo_centroidX, d3_geo_centroidY, d3_geo_centroidZ;
- var d3_geo_centroid = {
- sphere: function() {
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- }
- },
- point: d3_geo_centroidPoint,
- lineStart: d3_geo_centroidLineStart,
- lineEnd: d3_geo_centroidLineEnd,
- polygonStart: function() {
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ nodes.forEach(d3_layout_packLink);
+ a = nodes[0];
+ a.x = -a.r;
+ a.y = 0;
+ bound(a);
+ if (n > 1) {
+ b = nodes[1];
+ b.x = b.r;
+ b.y = 0;
+ bound(b);
+ if (n > 2) {
+ c = nodes[2];
+ d3_layout_packPlace(a, b, c);
+ bound(c);
+ d3_layout_packInsert(a, c);
+ a._pack_prev = c;
+ d3_layout_packInsert(c, b);
+ b = a._pack_next;
+ for (i = 3; i < n; i++) {
+ d3_layout_packPlace(a, b, c = nodes[i]);
+ var isect = 0, s1 = 1, s2 = 1;
+ for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
+ if (d3_layout_packIntersects(j, c)) {
+ isect = 1;
+ break;
+ }
+ }
+ if (isect == 1) {
+ for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
+ if (d3_layout_packIntersects(k, c)) {
+ break;
+ }
+ }
+ }
+ if (isect) {
+ if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
+ i--;
+ } else {
+ d3_layout_packInsert(a, c);
+ b = c;
+ bound(c);
+ }
+ }
}
- d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
- },
- polygonEnd: function() {
- d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
}
- };
- function d3_geo_centroidPoint(λ, φ) {
- if (d3_geo_centroidDimension) return;
- ++d3_geo_centroidW;
- λ *= d3_radians;
- var cosφ = Math.cos(φ *= d3_radians);
- d3_geo_centroidX += (cosφ * Math.cos(λ) - d3_geo_centroidX) / d3_geo_centroidW;
- d3_geo_centroidY += (cosφ * Math.sin(λ) - d3_geo_centroidY) / d3_geo_centroidW;
- d3_geo_centroidZ += (Math.sin(φ) - d3_geo_centroidZ) / d3_geo_centroidW;
+ var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
+ for (i = 0; i < n; i++) {
+ c = nodes[i];
+ c.x -= cx;
+ c.y -= cy;
+ cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
+ }
+ node.r = cr;
+ nodes.forEach(d3_layout_packUnlink);
}
- function d3_geo_centroidRingStart() {
- var λ00, φ00;
- d3_geo_centroidDimension = 1;
- d3_geo_centroidLineStart();
- d3_geo_centroidDimension = 2;
- var linePoint = d3_geo_centroid.point;
- d3_geo_centroid.point = function(λ, φ) {
- linePoint(λ00 = λ, φ00 = φ);
- };
- d3_geo_centroid.lineEnd = function() {
- d3_geo_centroid.point(λ00, φ00);
- d3_geo_centroidLineEnd();
- d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
- };
+ function d3_layout_packLink(node) {
+ node._pack_next = node._pack_prev = node;
}
- function d3_geo_centroidLineStart() {
- var x0, y0, z0;
- if (d3_geo_centroidDimension > 1) return;
- if (d3_geo_centroidDimension < 1) {
- d3_geo_centroidDimension = 1;
- d3_geo_centroidW = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- }
- d3_geo_centroid.point = function(λ, φ) {
- λ *= d3_radians;
- var cosφ = Math.cos(φ *= d3_radians);
- x0 = cosφ * Math.cos(λ);
- y0 = cosφ * Math.sin(λ);
- z0 = Math.sin(φ);
- d3_geo_centroid.point = nextPoint;
- };
- function nextPoint(λ, φ) {
- λ *= d3_radians;
- var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
- d3_geo_centroidW += w;
- d3_geo_centroidX += w * (x0 + (x0 = x));
- d3_geo_centroidY += w * (y0 + (y0 = y));
- d3_geo_centroidZ += w * (z0 + (z0 = z));
+ function d3_layout_packUnlink(node) {
+ delete node._pack_next;
+ delete node._pack_prev;
+ }
+ function d3_layout_packTransform(node, x, y, k) {
+ var children = node.children;
+ node.x = x += k * node.x;
+ node.y = y += k * node.y;
+ node.r *= k;
+ if (children) {
+ var i = -1, n = children.length;
+ while (++i < n) d3_layout_packTransform(children[i], x, y, k);
}
}
- function d3_geo_centroidLineEnd() {
- d3_geo_centroid.point = d3_geo_centroidPoint;
+ function d3_layout_packPlace(a, b, c) {
+ var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
+ if (db && (dx || dy)) {
+ var da = b.r + c.r, dc = dx * dx + dy * dy;
+ da *= da;
+ db *= db;
+ var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
+ c.x = a.x + x * dx + y * dy;
+ c.y = a.y + x * dy - y * dx;
+ } else {
+ c.x = a.x + db;
+ c.y = a.y;
+ }
}
- d3.geo.circle = function() {
- var origin = [ 0, 0 ], angle, precision = 6, interpolate;
- function circle() {
- var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
- interpolate(null, null, 1, {
- point: function(x, y) {
- ring.push(x = rotate(x, y));
- x[0] *= d3_degrees, x[1] *= d3_degrees;
+ d3.layout.cluster = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ];
+ function cluster(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+ d3_layout_treeVisitAfter(root, function(node) {
+ var children = node.children;
+ if (children && children.length) {
+ node.x = d3_layout_clusterX(children);
+ node.y = d3_layout_clusterY(children);
+ } else {
+ node.x = previousNode ? x += separation(node, previousNode) : 0;
+ node.y = 0;
+ previousNode = node;
}
});
- return {
- type: "Polygon",
- coordinates: [ ring ]
- };
+ var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
+ d3_layout_treeVisitAfter(root, function(node) {
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
+ node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
+ });
+ return nodes;
}
- circle.origin = function(x) {
- if (!arguments.length) return origin;
- origin = x;
- return circle;
- };
- circle.angle = function(x) {
- if (!arguments.length) return angle;
- interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
- return circle;
+ cluster.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return cluster;
};
- circle.precision = function(_) {
- if (!arguments.length) return precision;
- interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
- return circle;
+ cluster.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return cluster;
};
- return circle.angle(90);
+ return d3_layout_hierarchyRebind(cluster, hierarchy);
};
- function d3_geo_circleInterpolate(radians, precision) {
- var cr = Math.cos(radians), sr = Math.sin(radians);
- return function(from, to, direction, listener) {
- if (from != null) {
- from = d3_geo_circleAngle(cr, from);
- to = d3_geo_circleAngle(cr, to);
- if (direction > 0 ? from < to : from > to) from += direction * 2 * π;
- } else {
- from = radians + direction * 2 * π;
- to = radians;
- }
- var point;
- for (var step = direction * precision, t = from; direction > 0 ? t > to : t < to; t -= step) {
- listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
- }
- };
+ function d3_layout_clusterY(children) {
+ return 1 + d3.max(children, function(child) {
+ return child.y;
+ });
+ }
+ function d3_layout_clusterX(children) {
+ return children.reduce(function(x, child) {
+ return x + child.x;
+ }, 0) / children.length;
+ }
+ function d3_layout_clusterLeft(node) {
+ var children = node.children;
+ return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
}
- function d3_geo_circleAngle(cr, point) {
- var a = d3_geo_cartesian(point);
- a[0] -= cr;
- d3_geo_cartesianNormalize(a);
- var angle = Math.acos(Math.max(-1, Math.min(1, -a[1])));
- return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+ function d3_layout_clusterRight(node) {
+ var children = node.children, n;
+ return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
}
- function d3_geo_clip(pointVisible, clipLine, interpolate) {
- return function(listener) {
- var line = clipLine(listener);
- var clip = {
- point: point,
- lineStart: lineStart,
- lineEnd: lineEnd,
- polygonStart: function() {
- clip.point = pointRing;
- clip.lineStart = ringStart;
- clip.lineEnd = ringEnd;
- invisible = false;
- invisibleArea = visibleArea = 0;
- segments = [];
- listener.polygonStart();
- },
- polygonEnd: function() {
- clip.point = point;
- clip.lineStart = lineStart;
- clip.lineEnd = lineEnd;
- segments = d3.merge(segments);
- if (segments.length) {
- d3_geo_clipPolygon(segments, interpolate, listener);
- } else if (visibleArea < -ε || invisible && invisibleArea < -ε) {
- listener.lineStart();
- interpolate(null, null, 1, listener);
- listener.lineEnd();
+ d3.layout.treemap = function() {
+ var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
+ function scale(children, k) {
+ var i = -1, n = children.length, child, area;
+ while (++i < n) {
+ area = (child = children[i]).value * (k < 0 ? 0 : k);
+ child.area = isNaN(area) || area <= 0 ? 0 : area;
+ }
+ }
+ function squarify(node) {
+ var children = node.children;
+ if (children && children.length) {
+ var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
+ scale(remaining, rect.dx * rect.dy / node.value);
+ row.area = 0;
+ while ((n = remaining.length) > 0) {
+ row.push(child = remaining[n - 1]);
+ row.area += child.area;
+ if (mode !== "squarify" || (score = worst(row, u)) <= best) {
+ remaining.pop();
+ best = score;
+ } else {
+ row.area -= row.pop().area;
+ position(row, u, rect, false);
+ u = Math.min(rect.dx, rect.dy);
+ row.length = row.area = 0;
+ best = Infinity;
}
- listener.polygonEnd();
- segments = null;
- },
- sphere: function() {
- listener.polygonStart();
- listener.lineStart();
- interpolate(null, null, 1, listener);
- listener.lineEnd();
- listener.polygonEnd();
}
- };
- function point(λ, φ) {
- if (pointVisible(λ, φ)) listener.point(λ, φ);
- }
- function pointLine(λ, φ) {
- line.point(λ, φ);
- }
- function lineStart() {
- clip.point = pointLine;
- line.lineStart();
- }
- function lineEnd() {
- clip.point = point;
- line.lineEnd();
+ if (row.length) {
+ position(row, u, rect, true);
+ row.length = row.area = 0;
+ }
+ children.forEach(squarify);
}
- var segments, visibleArea, invisibleArea, invisible;
- var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), ring;
- function pointRing(λ, φ) {
- ringListener.point(λ, φ);
- ring.push([ λ, φ ]);
+ }
+ function stickify(node) {
+ var children = node.children;
+ if (children && children.length) {
+ var rect = pad(node), remaining = children.slice(), child, row = [];
+ scale(remaining, rect.dx * rect.dy / node.value);
+ row.area = 0;
+ while (child = remaining.pop()) {
+ row.push(child);
+ row.area += child.area;
+ if (child.z != null) {
+ position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
+ row.length = row.area = 0;
+ }
+ }
+ children.forEach(stickify);
}
- function ringStart() {
- ringListener.lineStart();
- ring = [];
+ }
+ function worst(row, u) {
+ var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
+ while (++i < n) {
+ if (!(r = row[i].area)) continue;
+ if (r < rmin) rmin = r;
+ if (r > rmax) rmax = r;
}
- function ringEnd() {
- pointRing(ring[0][0], ring[0][1]);
- ringListener.lineEnd();
- var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
- if (!n) {
- invisible = true;
- invisibleArea += d3_geo_clipAreaRing(ring, -1);
- ring = null;
- return;
+ s *= s;
+ u *= u;
+ return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
+ }
+ function position(row, u, rect, flush) {
+ var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
+ if (u == rect.dx) {
+ if (flush || v > rect.dy) v = rect.dy;
+ while (++i < n) {
+ o = row[i];
+ o.x = x;
+ o.y = y;
+ o.dy = v;
+ x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
}
- ring = null;
- if (clean & 1) {
- segment = ringSegments[0];
- visibleArea += d3_geo_clipAreaRing(segment, 1);
- var n = segment.length - 1, i = -1, point;
- listener.lineStart();
- while (++i < n) listener.point((point = segment[i])[0], point[1]);
- listener.lineEnd();
- return;
+ o.z = true;
+ o.dx += rect.x + rect.dx - x;
+ rect.y += v;
+ rect.dy -= v;
+ } else {
+ if (flush || v > rect.dx) v = rect.dx;
+ while (++i < n) {
+ o = row[i];
+ o.x = x;
+ o.y = y;
+ o.dx = v;
+ y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
}
- if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
- segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+ o.z = false;
+ o.dy += rect.y + rect.dy - y;
+ rect.x += v;
+ rect.dx -= v;
}
- return clip;
+ }
+ function treemap(d) {
+ var nodes = stickies || hierarchy(d), root = nodes[0];
+ root.x = 0;
+ root.y = 0;
+ root.dx = size[0];
+ root.dy = size[1];
+ if (stickies) hierarchy.revalue(root);
+ scale([ root ], root.dx * root.dy / root.value);
+ (stickies ? stickify : squarify)(root);
+ if (sticky) stickies = nodes;
+ return nodes;
+ }
+ treemap.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return treemap;
+ };
+ treemap.padding = function(x) {
+ if (!arguments.length) return padding;
+ function padFunction(node) {
+ var p = x.call(treemap, node, node.depth);
+ return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
+ }
+ function padConstant(node) {
+ return d3_layout_treemapPad(node, x);
+ }
+ var type;
+ pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ],
+ padConstant) : padConstant;
+ return treemap;
+ };
+ treemap.round = function(x) {
+ if (!arguments.length) return round != Number;
+ round = x ? Math.round : Number;
+ return treemap;
+ };
+ treemap.sticky = function(x) {
+ if (!arguments.length) return sticky;
+ sticky = x;
+ stickies = null;
+ return treemap;
+ };
+ treemap.ratio = function(x) {
+ if (!arguments.length) return ratio;
+ ratio = x;
+ return treemap;
+ };
+ treemap.mode = function(x) {
+ if (!arguments.length) return mode;
+ mode = x + "";
+ return treemap;
+ };
+ return d3_layout_hierarchyRebind(treemap, hierarchy);
+ };
+ function d3_layout_treemapPadNull(node) {
+ return {
+ x: node.x,
+ y: node.y,
+ dx: node.dx,
+ dy: node.dy
};
}
- function d3_geo_clipPolygon(segments, interpolate, listener) {
- var subject = [], clip = [];
- segments.forEach(function(segment) {
- var n = segment.length;
- if (n <= 1) return;
- var p0 = segment[0], p1 = segment[n - 1], a = {
- point: p0,
- points: segment,
- other: null,
- visited: false,
- entry: true,
- subject: true
- }, b = {
- point: p0,
- points: [ p0 ],
- other: a,
- visited: false,
- entry: false,
- subject: false
+ function d3_layout_treemapPad(node, padding) {
+ var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
+ if (dx < 0) {
+ x += dx / 2;
+ dx = 0;
+ }
+ if (dy < 0) {
+ y += dy / 2;
+ dy = 0;
+ }
+ return {
+ x: x,
+ y: y,
+ dx: dx,
+ dy: dy
+ };
+ }
+ d3.random = {
+ normal: function(µ, σ) {
+ var n = arguments.length;
+ if (n < 2) σ = 1;
+ if (n < 1) µ = 0;
+ return function() {
+ var x, y, r;
+ do {
+ x = Math.random() * 2 - 1;
+ y = Math.random() * 2 - 1;
+ r = x * x + y * y;
+ } while (!r || r > 1);
+ return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
};
- a.other = b;
- subject.push(a);
- clip.push(b);
- a = {
- point: p1,
- points: [ p1 ],
- other: null,
- visited: false,
- entry: false,
- subject: true
+ },
+ logNormal: function() {
+ var random = d3.random.normal.apply(d3, arguments);
+ return function() {
+ return Math.exp(random());
};
- b = {
- point: p1,
- points: [ p1 ],
- other: a,
- visited: false,
- entry: true,
- subject: false
+ },
+ irwinHall: function(m) {
+ return function() {
+ for (var s = 0, j = 0; j < m; j++) s += Math.random();
+ return s / m;
};
- a.other = b;
- subject.push(a);
- clip.push(b);
- });
- clip.sort(d3_geo_clipSort);
- d3_geo_clipLinkCircular(subject);
- d3_geo_clipLinkCircular(clip);
- if (!subject.length) return;
- var start = subject[0], current, points, point;
- while (1) {
- current = start;
- while (current.visited) if ((current = current.next) === start) return;
- points = current.points;
- listener.lineStart();
- do {
- current.visited = current.other.visited = true;
- if (current.entry) {
- if (current.subject) {
- for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
- } else {
- interpolate(current.point, current.next.point, 1, listener);
- }
- current = current.next;
- } else {
- if (current.subject) {
- points = current.prev.points;
- for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);
- } else {
- interpolate(current.point, current.prev.point, -1, listener);
- }
- current = current.prev;
- }
- current = current.other;
- points = current.points;
- } while (!current.visited);
- listener.lineEnd();
}
+ };
+ d3.scale = {};
+ function d3_scaleExtent(domain) {
+ var start = domain[0], stop = domain[domain.length - 1];
+ return start < stop ? [ start, stop ] : [ stop, start ];
}
- function d3_geo_clipLinkCircular(array) {
- if (!(n = array.length)) return;
- var n, i = 0, a = array[0], b;
- while (++i < n) {
- a.next = b = array[i];
- b.prev = a;
- a = b;
- }
- a.next = b = array[0];
- b.prev = a;
+ function d3_scaleRange(scale) {
+ return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
}
- function d3_geo_clipSort(a, b) {
- return ((a = a.point)[0] < 0 ? a[1] - π / 2 - ε : π / 2 - a[1]) - ((b = b.point)[0] < 0 ? b[1] - π / 2 - ε : π / 2 - b[1]);
+ function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
+ var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
+ return function(x) {
+ return i(u(x));
+ };
}
- function d3_geo_clipSegmentLength1(segment) {
- return segment.length > 1;
+ function d3_scale_nice(domain, nice) {
+ var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
+ if (x1 < x0) {
+ dx = i0, i0 = i1, i1 = dx;
+ dx = x0, x0 = x1, x1 = dx;
+ }
+ if (nice = nice(x1 - x0)) {
+ domain[i0] = nice.floor(x0);
+ domain[i1] = nice.ceil(x1);
+ }
+ return domain;
}
- function d3_geo_clipBufferListener() {
- var lines = [], line;
- return {
- lineStart: function() {
- lines.push(line = []);
- },
- point: function(λ, φ) {
- line.push([ λ, φ ]);
- },
- lineEnd: d3_noop,
- buffer: function() {
- var buffer = lines;
- lines = [];
- line = null;
- return buffer;
- }
+ function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
+ var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
+ if (domain[k] < domain[0]) {
+ domain = domain.slice().reverse();
+ range = range.slice().reverse();
+ }
+ while (++j <= k) {
+ u.push(uninterpolate(domain[j - 1], domain[j]));
+ i.push(interpolate(range[j - 1], range[j]));
+ }
+ return function(x) {
+ var j = d3.bisect(domain, x, 1, k) - 1;
+ return i[j](u[j](x));
};
}
- function d3_geo_clipAreaRing(ring, invisible) {
- if (!(n = ring.length)) return 0;
- var n, i = 0, area = 0, p = ring[0], λ = p[0], φ = p[1], cosφ = Math.cos(φ), x0 = Math.atan2(invisible * Math.sin(λ) * cosφ, Math.sin(φ)), y0 = 1 - invisible * Math.cos(λ) * cosφ, x1 = x0, x, y;
- while (++i < n) {
- p = ring[i];
- cosφ = Math.cos(φ = p[1]);
- x = Math.atan2(invisible * Math.sin(λ = p[0]) * cosφ, Math.sin(φ));
- y = 1 - invisible * Math.cos(λ) * cosφ;
- if (Math.abs(y0 - 2) < ε && Math.abs(y - 2) < ε) continue;
- if (Math.abs(y) < ε || Math.abs(y0) < ε) {} else if (Math.abs(Math.abs(x - x0) - π) < ε) {
- if (y + y0 > 2) area += 4 * (x - x0);
- } else if (Math.abs(y0 - 2) < ε) area += 4 * (x - x1); else area += ((3 * π + x - x0) % (2 * π) - π) * (y0 + y);
- x1 = x0, x0 = x, y0 = y;
+ d3.scale.linear = function() {
+ return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
+ };
+ function d3_scale_linear(domain, range, interpolate, clamp) {
+ var output, input;
+ function rescale() {
+ var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
+ output = linear(domain, range, uninterpolate, interpolate);
+ input = linear(range, domain, uninterpolate, d3_interpolate);
+ return scale;
}
- return area;
+ function scale(x) {
+ return output(x);
+ }
+ scale.invert = function(y) {
+ return input(y);
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(Number);
+ return rescale();
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.rangeRound = function(x) {
+ return scale.range(x).interpolate(d3_interpolateRound);
+ };
+ scale.clamp = function(x) {
+ if (!arguments.length) return clamp;
+ clamp = x;
+ return rescale();
+ };
+ scale.interpolate = function(x) {
+ if (!arguments.length) return interpolate;
+ interpolate = x;
+ return rescale();
+ };
+ scale.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
+ };
+ scale.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
+ };
+ scale.nice = function() {
+ d3_scale_nice(domain, d3_scale_linearNice);
+ return rescale();
+ };
+ scale.copy = function() {
+ return d3_scale_linear(domain, range, interpolate, clamp);
+ };
+ return rescale();
}
- var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate);
- function d3_geo_clipAntimeridianLine(listener) {
- var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
- return {
- lineStart: function() {
- listener.lineStart();
- clean = 1;
- },
- point: function(λ1, φ1) {
- var sλ1 = λ1 > 0 ? π : -π, dλ = Math.abs(λ1 - λ0);
- if (Math.abs(dλ - π) < ε) {
- listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? π / 2 : -π / 2);
- listener.point(sλ0, φ0);
- listener.lineEnd();
- listener.lineStart();
- listener.point(sλ1, φ0);
- listener.point(λ1, φ0);
- clean = 0;
- } else if (sλ0 !== sλ1 && dλ >= π) {
- if (Math.abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
- if (Math.abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
- φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
- listener.point(sλ0, φ0);
- listener.lineEnd();
- listener.lineStart();
- listener.point(sλ1, φ0);
- clean = 0;
- }
- listener.point(λ0 = λ1, φ0 = φ1);
- sλ0 = sλ1;
- },
- lineEnd: function() {
- listener.lineEnd();
- λ0 = φ0 = NaN;
+ function d3_scale_linearRebind(scale, linear) {
+ return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+ }
+ function d3_scale_linearNice(dx) {
+ dx = Math.pow(10, Math.round(Math.log(dx) / Math.LN10) - 1);
+ return dx && {
+ floor: function(x) {
+ return Math.floor(x / dx) * dx;
},
- clean: function() {
- return 2 - clean;
+ ceil: function(x) {
+ return Math.ceil(x / dx) * dx;
}
};
}
- function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
- var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
- return Math.abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
+ function d3_scale_linearTickRange(domain, m) {
+ var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+ extent[0] = Math.ceil(extent[0] / step) * step;
+ extent[1] = Math.floor(extent[1] / step) * step + step * .5;
+ extent[2] = step;
+ return extent;
}
- function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
- var φ;
- if (from == null) {
- φ = direction * π / 2;
- listener.point(-π, φ);
- listener.point(0, φ);
- listener.point(π, φ);
- listener.point(π, 0);
- listener.point(π, -φ);
- listener.point(0, -φ);
- listener.point(-π, -φ);
- listener.point(-π, 0);
- listener.point(-π, φ);
- } else if (Math.abs(from[0] - to[0]) > ε) {
- var s = (from[0] < to[0] ? 1 : -1) * π;
- φ = direction * s / 2;
- listener.point(-s, φ);
- listener.point(0, φ);
- listener.point(s, φ);
- } else {
- listener.point(to[0], to[1]);
- }
+ function d3_scale_linearTicks(domain, m) {
+ return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
}
- function d3_geo_clipCircle(degrees) {
- var radians = degrees * d3_radians, cr = Math.cos(radians), interpolate = d3_geo_circleInterpolate(radians, 6 * d3_radians);
- return d3_geo_clip(visible, clipLine, interpolate);
- function visible(λ, φ) {
- return Math.cos(λ) * Math.cos(φ) > cr;
+ function d3_scale_linearTickFormat(domain, m, format) {
+ var precision = -Math.floor(Math.log(d3_scale_linearTickRange(domain, m)[2]) / Math.LN10 + .01);
+ return d3.format(format ? format.replace(d3_format_re, function(a, b, c, d, e, f, g, h, i, j) {
+ return [ b, c, d, e, f, g, h, i || "." + (precision - (j === "%") * 2), j ].join("");
+ }) : ",." + precision + "f");
+ }
+ d3.scale.log = function() {
+ return d3_scale_log(d3.scale.linear().domain([ 0, Math.LN10 ]), 10, d3_scale_logp, d3_scale_powp, [ 1, 10 ]);
+ };
+ function d3_scale_log(linear, base, log, pow, domain) {
+ function scale(x) {
+ return linear(log(x));
}
- function clipLine(listener) {
- var point0, v0, v00, clean;
- return {
- lineStart: function() {
- v00 = v0 = false;
- clean = 1;
- },
- point: function(λ, φ) {
- var point1 = [ λ, φ ], point2, v = visible(λ, φ);
- if (!point0 && (v00 = v0 = v)) listener.lineStart();
- if (v !== v0) {
- point2 = intersect(point0, point1);
- if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
- point1[0] += ε;
- point1[1] += ε;
- v = visible(point1[0], point1[1]);
- }
- }
- if (v !== v0) {
- clean = 0;
- if (v0 = v) {
- listener.lineStart();
- point2 = intersect(point1, point0);
- listener.point(point2[0], point2[1]);
- } else {
- point2 = intersect(point0, point1);
- listener.point(point2[0], point2[1]);
- listener.lineEnd();
- }
- point0 = point2;
- }
- if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) listener.point(point1[0], point1[1]);
- point0 = point1;
- },
- lineEnd: function() {
- if (v0) listener.lineEnd();
- point0 = null;
+ scale.invert = function(x) {
+ return pow(linear.invert(x));
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ if (x[0] < 0) log = d3_scale_logn, pow = d3_scale_pown; else log = d3_scale_logp,
+ pow = d3_scale_powp;
+ linear.domain((domain = x.map(Number)).map(log));
+ return scale;
+ };
+ scale.base = function(_) {
+ if (!arguments.length) return base;
+ base = +_;
+ return scale;
+ };
+ scale.nice = function() {
+ linear.domain(d3_scale_nice(domain, nice).map(log));
+ return scale;
+ };
+ scale.ticks = function() {
+ var extent = d3_scaleExtent(linear.domain()), ticks = [];
+ if (extent.every(isFinite)) {
+ var b = Math.log(base), i = Math.floor(extent[0] / b), j = Math.ceil(extent[1] / b), u = pow(extent[0]), v = pow(extent[1]), n = base % 1 ? 2 : base;
+ if (log === d3_scale_logn) {
+ ticks.push(-Math.pow(base, -i));
+ for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(-Math.pow(base, -i) * k);
+ } else {
+ for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(Math.pow(base, i) * k);
+ ticks.push(Math.pow(base, i));
+ }
+ for (i = 0; ticks[i] < u; i++) {}
+ for (j = ticks.length; ticks[j - 1] > v; j--) {}
+ ticks = ticks.slice(i, j);
+ }
+ return ticks;
+ };
+ scale.tickFormat = function(n, format) {
+ if (arguments.length < 2) format = d3_scale_logFormat;
+ if (!arguments.length) return format;
+ var b = Math.log(base), k = Math.max(.1, n / scale.ticks().length), f = log === d3_scale_logn ? (e = -1e-12,
+ Math.floor) : (e = 1e-12, Math.ceil), e;
+ return function(d) {
+ return d / pow(b * f(log(d) / b + e)) <= k ? format(d) : "";
+ };
+ };
+ scale.copy = function() {
+ return d3_scale_log(linear.copy(), base, log, pow, domain);
+ };
+ function nice() {
+ return log === d3_scale_logp ? {
+ floor: floor,
+ ceil: ceil
+ } : {
+ floor: function(x) {
+ return -ceil(-x);
},
- clean: function() {
- return clean | (v00 && v0) << 1;
+ ceil: function(x) {
+ return -floor(-x);
}
};
}
- function intersect(a, b) {
- var pa = d3_geo_cartesian(a, 0), pb = d3_geo_cartesian(b, 0);
- var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
- if (!determinant) return a;
- var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
- d3_geo_cartesianAdd(A, B);
- var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t = Math.sqrt(w * w - uu * (d3_geo_cartesianDot(A, A) - 1)), q = d3_geo_cartesianScale(u, (-w - t) / uu);
- d3_geo_cartesianAdd(q, A);
- return d3_geo_spherical(q);
+ function floor(x) {
+ return Math.pow(base, Math.floor(Math.log(x) / Math.log(base)));
}
- }
- function d3_geo_compose(a, b) {
- function compose(x, y) {
- return x = a(x, y), b(x[0], x[1]);
+ function ceil(x) {
+ return Math.pow(base, Math.ceil(Math.log(x) / Math.log(base)));
}
- if (a.invert && b.invert) compose.invert = function(x, y) {
- return x = b.invert(x, y), x && a.invert(x[0], x[1]);
- };
- return compose;
+ return d3_scale_linearRebind(scale, linear);
}
- function d3_geo_equirectangular(λ, φ) {
- return [ λ, φ ];
+ var d3_scale_logFormat = d3.format(".0e");
+ function d3_scale_logp(x) {
+ return Math.log(x < 0 ? 0 : x);
}
- (d3.geo.equirectangular = function() {
- return d3_geo_projection(d3_geo_equirectangular).scale(250 / π);
- }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
- var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
- return 1 / cosλcosφ;
- }, Math.atan);
- (d3.geo.gnomonic = function() {
- return d3_geo_projection(d3_geo_gnomonic);
- }).raw = d3_geo_gnomonic;
- d3.geo.graticule = function() {
- var x1, x0, y1, y0, dx = 22.5, dy = dx, x, y, precision = 2.5;
- function graticule() {
- return {
- type: "MultiLineString",
- coordinates: lines()
- };
- }
- function lines() {
- return d3.range(Math.ceil(x0 / dx) * dx, x1, dx).map(x).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).map(y));
+ function d3_scale_powp(x) {
+ return Math.exp(x);
+ }
+ function d3_scale_logn(x) {
+ return -Math.log(x > 0 ? 0 : -x);
+ }
+ function d3_scale_pown(x) {
+ return -Math.exp(-x);
+ }
+ d3.scale.pow = function() {
+ return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
+ };
+ function d3_scale_pow(linear, exponent, domain) {
+ var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
+ function scale(x) {
+ return linear(powp(x));
}
- graticule.lines = function() {
- return lines().map(function(coordinates) {
- return {
- type: "LineString",
- coordinates: coordinates
- };
- });
+ scale.invert = function(x) {
+ return powb(linear.invert(x));
};
- graticule.outline = function() {
- return {
- type: "Polygon",
- coordinates: [ x(x0).concat(y(y1).slice(1), x(x1).reverse().slice(1), y(y0).reverse().slice(1)) ]
- };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ linear.domain((domain = x.map(Number)).map(powp));
+ return scale;
};
- graticule.extent = function(_) {
- if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
- x0 = +_[0][0], x1 = +_[1][0];
- y0 = +_[0][1], y1 = +_[1][1];
- if (x0 > x1) _ = x0, x0 = x1, x1 = _;
- if (y0 > y1) _ = y0, y0 = y1, y1 = _;
- return graticule.precision(precision);
+ scale.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
};
- graticule.step = function(_) {
- if (!arguments.length) return [ dx, dy ];
- dx = +_[0], dy = +_[1];
- return graticule;
+ scale.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
};
- graticule.precision = function(_) {
- if (!arguments.length) return precision;
- precision = +_;
- x = d3_geo_graticuleX(y0, y1, precision);
- y = d3_geo_graticuleY(x0, x1, precision);
- return graticule;
+ scale.nice = function() {
+ return scale.domain(d3_scale_nice(domain, d3_scale_linearNice));
};
- return graticule.extent([ [ -180 + ε, -90 + ε ], [ 180 - ε, 90 - ε ] ]);
- };
- function d3_geo_graticuleX(y0, y1, dy) {
- var y = d3.range(y0, y1 - ε, dy).concat(y1);
+ scale.exponent = function(x) {
+ if (!arguments.length) return exponent;
+ powp = d3_scale_powPow(exponent = x);
+ powb = d3_scale_powPow(1 / exponent);
+ linear.domain(domain.map(powp));
+ return scale;
+ };
+ scale.copy = function() {
+ return d3_scale_pow(linear.copy(), exponent, domain);
+ };
+ return d3_scale_linearRebind(scale, linear);
+ }
+ function d3_scale_powPow(e) {
return function(x) {
- return y.map(function(y) {
- return [ x, y ];
- });
+ return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
};
}
- function d3_geo_graticuleY(x0, x1, dx) {
- var x = d3.range(x0, x1 - ε, dx).concat(x1);
- return function(y) {
- return x.map(function(x) {
- return [ x, y ];
+ d3.scale.sqrt = function() {
+ return d3.scale.pow().exponent(.5);
+ };
+ d3.scale.ordinal = function() {
+ return d3_scale_ordinal([], {
+ t: "range",
+ a: [ [] ]
+ });
+ };
+ function d3_scale_ordinal(domain, ranger) {
+ var index, range, rangeBand;
+ function scale(x) {
+ return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];
+ }
+ function steps(start, step) {
+ return d3.range(domain.length).map(function(i) {
+ return start + step * i;
});
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = [];
+ index = new d3_Map();
+ var i = -1, n = x.length, xi;
+ while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
+ return scale[ranger.t].apply(scale, ranger.a);
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ rangeBand = 0;
+ ranger = {
+ t: "range",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangePoints = function(x, padding) {
+ if (arguments.length < 2) padding = 0;
+ var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
+ range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
+ rangeBand = 0;
+ ranger = {
+ t: "rangePoints",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangeBands = function(x, padding, outerPadding) {
+ if (arguments.length < 2) padding = 0;
+ if (arguments.length < 3) outerPadding = padding;
+ var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
+ range = steps(start + step * outerPadding, step);
+ if (reverse) range.reverse();
+ rangeBand = step * (1 - padding);
+ ranger = {
+ t: "rangeBands",
+ a: arguments
+ };
+ return scale;
};
- }
- d3.geo.interpolate = function(source, target) {
- return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
- };
- function d3_geo_interpolate(x0, y0, x1, y1) {
- var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))), k = 1 / Math.sin(d);
- function interpolate(t) {
- var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
- return [ Math.atan2(y, x) / d3_radians, Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians ];
- }
- interpolate.distance = d;
- return interpolate;
- }
- d3.geo.greatArc = function() {
- var source = d3_source, source_, target = d3_target, target_, precision = 6 * d3_radians, interpolate;
- function greatArc() {
- var p0 = source_ || source.apply(this, arguments), p1 = target_ || target.apply(this, arguments), i = interpolate || d3.geo.interpolate(p0, p1), t = 0, dt = precision / i.distance, coordinates = [ p0 ];
- while ((t += dt) < 1) coordinates.push(i(t));
- coordinates.push(p1);
- return {
- type: "LineString",
- coordinates: coordinates
+ scale.rangeRoundBands = function(x, padding, outerPadding) {
+ if (arguments.length < 2) padding = 0;
+ if (arguments.length < 3) outerPadding = padding;
+ var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
+ range = steps(start + Math.round(error / 2), step);
+ if (reverse) range.reverse();
+ rangeBand = Math.round(step * (1 - padding));
+ ranger = {
+ t: "rangeRoundBands",
+ a: arguments
};
- }
- greatArc.distance = function() {
- return (interpolate || d3.geo.interpolate(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments))).distance;
+ return scale;
};
- greatArc.source = function(_) {
- if (!arguments.length) return source;
- source = _, source_ = typeof _ === "function" ? null : _;
- interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null;
- return greatArc;
+ scale.rangeBand = function() {
+ return rangeBand;
};
- greatArc.target = function(_) {
- if (!arguments.length) return target;
- target = _, target_ = typeof _ === "function" ? null : _;
- interpolate = source_ && target_ ? d3.geo.interpolate(source_, target_) : null;
- return greatArc;
+ scale.rangeExtent = function() {
+ return d3_scaleExtent(ranger.a[0]);
};
- greatArc.precision = function(_) {
- if (!arguments.length) return precision / d3_radians;
- precision = _ * d3_radians;
- return greatArc;
+ scale.copy = function() {
+ return d3_scale_ordinal(domain, ranger);
};
- return greatArc;
- };
- function d3_geo_mercator(λ, φ) {
- return [ λ / (2 * π), Math.max(-.5, Math.min(+.5, Math.log(Math.tan(π / 4 + φ / 2)) / (2 * π))) ];
+ return scale.domain(domain);
}
- d3_geo_mercator.invert = function(x, y) {
- return [ 2 * π * x, 2 * Math.atan(Math.exp(2 * π * y)) - π / 2 ];
+ d3.scale.category10 = function() {
+ return d3.scale.ordinal().range(d3_category10);
};
- (d3.geo.mercator = function() {
- return d3_geo_projection(d3_geo_mercator).scale(500);
- }).raw = d3_geo_mercator;
- var d3_geo_orthographic = d3_geo_azimuthal(function() {
- return 1;
- }, Math.asin);
- (d3.geo.orthographic = function() {
- return d3_geo_projection(d3_geo_orthographic);
- }).raw = d3_geo_orthographic;
- d3.geo.path = function() {
- var pointRadius = 4.5, projection, context, projectStream, contextStream;
- function path(object) {
- if (object) d3.geo.stream(object, projectStream(contextStream.pointRadius(typeof pointRadius === "function" ? +pointRadius.apply(this, arguments) : pointRadius)));
- return contextStream.result();
+ d3.scale.category20 = function() {
+ return d3.scale.ordinal().range(d3_category20);
+ };
+ d3.scale.category20b = function() {
+ return d3.scale.ordinal().range(d3_category20b);
+ };
+ d3.scale.category20c = function() {
+ return d3.scale.ordinal().range(d3_category20c);
+ };
+ var d3_category10 = [ "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf" ];
+ var d3_category20 = [ "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5" ];
+ var d3_category20b = [ "#393b79", "#5254a3", "#6b6ecf", "#9c9ede", "#637939", "#8ca252", "#b5cf6b", "#cedb9c", "#8c6d31", "#bd9e39", "#e7ba52", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#e7969c", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6" ];
+ var d3_category20c = [ "#3182bd", "#6baed6", "#9ecae1", "#c6dbef", "#e6550d", "#fd8d3c", "#fdae6b", "#fdd0a2", "#31a354", "#74c476", "#a1d99b", "#c7e9c0", "#756bb1", "#9e9ac8", "#bcbddc", "#dadaeb", "#636363", "#969696", "#bdbdbd", "#d9d9d9" ];
+ d3.scale.quantile = function() {
+ return d3_scale_quantile([], []);
+ };
+ function d3_scale_quantile(domain, range) {
+ var thresholds;
+ function rescale() {
+ var k = 0, q = range.length;
+ thresholds = [];
+ while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
+ return scale;
}
- path.area = function(object) {
- d3_geo_pathAreaSum = 0;
- d3.geo.stream(object, projectStream(d3_geo_pathArea));
- return d3_geo_pathAreaSum;
- };
- path.centroid = function(object) {
- d3_geo_centroidDimension = d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
- return d3_geo_centroidZ ? [ d3_geo_centroidX / d3_geo_centroidZ, d3_geo_centroidY / d3_geo_centroidZ ] : undefined;
- };
- path.bounds = function(object) {
- return d3_geo_bounds(projectStream)(object);
- };
- path.projection = function(_) {
- if (!arguments.length) return projection;
- projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
- return path;
- };
- path.context = function(_) {
- if (!arguments.length) return context;
- contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
- return path;
+ function scale(x) {
+ if (isNaN(x = +x)) return NaN;
+ return range[d3.bisect(thresholds, x)];
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.filter(function(d) {
+ return !isNaN(d);
+ }).sort(d3.ascending);
+ return rescale();
};
- path.pointRadius = function(_) {
- if (!arguments.length) return pointRadius;
- pointRadius = typeof _ === "function" ? _ : +_;
- return path;
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
};
- return path.projection(d3.geo.albersUsa()).context(null);
- };
- function d3_geo_pathCircle(radius) {
- return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + +2 * radius + "z";
- }
- function d3_geo_pathProjectStream(project) {
- var resample = d3_geo_resample(function(λ, φ) {
- return project([ λ * d3_degrees, φ * d3_degrees ]);
- });
- return function(stream) {
- stream = resample(stream);
- return {
- point: function(λ, φ) {
- stream.point(λ * d3_radians, φ * d3_radians);
- },
- sphere: function() {
- stream.sphere();
- },
- lineStart: function() {
- stream.lineStart();
- },
- lineEnd: function() {
- stream.lineEnd();
- },
- polygonStart: function() {
- stream.polygonStart();
- },
- polygonEnd: function() {
- stream.polygonEnd();
- }
- };
+ scale.quantiles = function() {
+ return thresholds;
};
- }
- function d3_geo_pathBuffer() {
- var pointCircle = d3_geo_pathCircle(4.5), buffer = [];
- var stream = {
- point: point,
- lineStart: function() {
- stream.point = pointLineStart;
- },
- lineEnd: lineEnd,
- polygonStart: function() {
- stream.lineEnd = lineEndPolygon;
- },
- polygonEnd: function() {
- stream.lineEnd = lineEnd;
- stream.point = point;
- },
- pointRadius: function(_) {
- pointCircle = d3_geo_pathCircle(_);
- return stream;
- },
- result: function() {
- if (buffer.length) {
- var result = buffer.join("");
- buffer = [];
- return result;
- }
- }
+ scale.copy = function() {
+ return d3_scale_quantile(domain, range);
};
- function point(x, y) {
- buffer.push("M", x, ",", y, pointCircle);
- }
- function pointLineStart(x, y) {
- buffer.push("M", x, ",", y);
- stream.point = pointLine;
- }
- function pointLine(x, y) {
- buffer.push("L", x, ",", y);
- }
- function lineEnd() {
- stream.point = point;
- }
- function lineEndPolygon() {
- buffer.push("Z");
- }
- return stream;
+ return rescale();
}
- function d3_geo_pathContext(context) {
- var pointRadius = 4.5;
- var stream = {
- point: point,
- lineStart: function() {
- stream.point = pointLineStart;
- },
- lineEnd: lineEnd,
- polygonStart: function() {
- stream.lineEnd = lineEndPolygon;
- },
- polygonEnd: function() {
- stream.lineEnd = lineEnd;
- stream.point = point;
- },
- pointRadius: function(_) {
- pointRadius = _;
- return stream;
- },
- result: d3_noop
- };
- function point(x, y) {
- context.moveTo(x, y);
- context.arc(x, y, pointRadius, 0, 2 * π);
- }
- function pointLineStart(x, y) {
- context.moveTo(x, y);
- stream.point = pointLine;
- }
- function pointLine(x, y) {
- context.lineTo(x, y);
- }
- function lineEnd() {
- stream.point = point;
- }
- function lineEndPolygon() {
- context.closePath();
+ d3.scale.quantize = function() {
+ return d3_scale_quantize(0, 1, [ 0, 1 ]);
+ };
+ function d3_scale_quantize(x0, x1, range) {
+ var kx, i;
+ function scale(x) {
+ return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
}
- return stream;
- }
- var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
- point: d3_noop,
- lineStart: d3_noop,
- lineEnd: d3_noop,
- polygonStart: function() {
- d3_geo_pathAreaPolygon = 0;
- d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
- },
- polygonEnd: function() {
- d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
- d3_geo_pathAreaSum += Math.abs(d3_geo_pathAreaPolygon / 2);
+ function rescale() {
+ kx = range.length / (x1 - x0);
+ i = range.length - 1;
+ return scale;
}
- };
- function d3_geo_pathAreaRingStart() {
- var x00, y00, x0, y0;
- d3_geo_pathArea.point = function(x, y) {
- d3_geo_pathArea.point = nextPoint;
- x00 = x0 = x, y00 = y0 = y;
+ scale.domain = function(x) {
+ if (!arguments.length) return [ x0, x1 ];
+ x0 = +x[0];
+ x1 = +x[x.length - 1];
+ return rescale();
};
- function nextPoint(x, y) {
- d3_geo_pathAreaPolygon += y0 * x - x0 * y;
- x0 = x, y0 = y;
- }
- d3_geo_pathArea.lineEnd = function() {
- nextPoint(x00, y00);
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.copy = function() {
+ return d3_scale_quantize(x0, x1, range);
};
+ return rescale();
}
- var d3_geo_pathCentroid = {
- point: d3_geo_pathCentroidPoint,
- lineStart: d3_geo_pathCentroidLineStart,
- lineEnd: d3_geo_pathCentroidLineEnd,
- polygonStart: function() {
- d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
- },
- polygonEnd: function() {
- d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
- d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
- d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
- }
+ d3.scale.threshold = function() {
+ return d3_scale_threshold([ .5 ], [ 0, 1 ]);
};
- function d3_geo_pathCentroidPoint(x, y) {
- if (d3_geo_centroidDimension) return;
- d3_geo_centroidX += x;
- d3_geo_centroidY += y;
- ++d3_geo_centroidZ;
+ function d3_scale_threshold(domain, range) {
+ function scale(x) {
+ return range[d3.bisect(domain, x)];
+ }
+ scale.domain = function(_) {
+ if (!arguments.length) return domain;
+ domain = _;
+ return scale;
+ };
+ scale.range = function(_) {
+ if (!arguments.length) return range;
+ range = _;
+ return scale;
+ };
+ scale.copy = function() {
+ return d3_scale_threshold(domain, range);
+ };
+ return scale;
}
- function d3_geo_pathCentroidLineStart() {
- var x0, y0;
- if (d3_geo_centroidDimension !== 1) {
- if (d3_geo_centroidDimension < 1) {
- d3_geo_centroidDimension = 1;
- d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
- } else return;
+ d3.scale.identity = function() {
+ return d3_scale_identity([ 0, 1 ]);
+ };
+ function d3_scale_identity(domain) {
+ function identity(x) {
+ return +x;
}
- d3_geo_pathCentroid.point = function(x, y) {
- d3_geo_pathCentroid.point = nextPoint;
- x0 = x, y0 = y;
+ identity.invert = identity;
+ identity.domain = identity.range = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(identity);
+ return identity;
};
- function nextPoint(x, y) {
- var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
- d3_geo_centroidX += z * (x0 + x) / 2;
- d3_geo_centroidY += z * (y0 + y) / 2;
- d3_geo_centroidZ += z;
- x0 = x, y0 = y;
+ identity.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
+ };
+ identity.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
+ };
+ identity.copy = function() {
+ return d3_scale_identity(domain);
+ };
+ return identity;
+ }
+ d3.svg.arc = function() {
+ var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+ function arc() {
+ var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0,
+ a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
+ return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
}
+ arc.innerRadius = function(v) {
+ if (!arguments.length) return innerRadius;
+ innerRadius = d3_functor(v);
+ return arc;
+ };
+ arc.outerRadius = function(v) {
+ if (!arguments.length) return outerRadius;
+ outerRadius = d3_functor(v);
+ return arc;
+ };
+ arc.startAngle = function(v) {
+ if (!arguments.length) return startAngle;
+ startAngle = d3_functor(v);
+ return arc;
+ };
+ arc.endAngle = function(v) {
+ if (!arguments.length) return endAngle;
+ endAngle = d3_functor(v);
+ return arc;
+ };
+ arc.centroid = function() {
+ var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
+ return [ Math.cos(a) * r, Math.sin(a) * r ];
+ };
+ return arc;
+ };
+ var d3_svg_arcOffset = -π / 2, d3_svg_arcMax = 2 * π - 1e-6;
+ function d3_svg_arcInnerRadius(d) {
+ return d.innerRadius;
}
- function d3_geo_pathCentroidLineEnd() {
- d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ function d3_svg_arcOuterRadius(d) {
+ return d.outerRadius;
}
- function d3_geo_pathCentroidRingStart() {
- var x00, y00, x0, y0;
- if (d3_geo_centroidDimension < 2) {
- d3_geo_centroidDimension = 2;
- d3_geo_centroidX = d3_geo_centroidY = d3_geo_centroidZ = 0;
+ function d3_svg_arcStartAngle(d) {
+ return d.startAngle;
+ }
+ function d3_svg_arcEndAngle(d) {
+ return d.endAngle;
+ }
+ d3.svg.line.radial = function() {
+ var line = d3_svg_line(d3_svg_lineRadial);
+ line.radius = line.x, delete line.x;
+ line.angle = line.y, delete line.y;
+ return line;
+ };
+ function d3_svg_lineRadial(points) {
+ var point, i = -1, n = points.length, r, a;
+ while (++i < n) {
+ point = points[i];
+ r = point[0];
+ a = point[1] + d3_svg_arcOffset;
+ point[0] = r * Math.cos(a);
+ point[1] = r * Math.sin(a);
}
- d3_geo_pathCentroid.point = function(x, y) {
- d3_geo_pathCentroid.point = nextPoint;
- x00 = x0 = x, y00 = y0 = y;
- };
- function nextPoint(x, y) {
- var z = y0 * x - x0 * y;
- d3_geo_centroidX += z * (x0 + x);
- d3_geo_centroidY += z * (y0 + y);
- d3_geo_centroidZ += z * 3;
- x0 = x, y0 = y;
+ return points;
+ }
+ function d3_svg_area(projection) {
+ var x0 = d3_svg_lineX, x1 = d3_svg_lineX, y0 = 0, y1 = d3_svg_lineY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
+ function area(data) {
+ var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
+ return x;
+ } : d3_functor(x1), fy1 = y0 === y1 ? function() {
+ return y;
+ } : d3_functor(y1), x, y;
+ function segment() {
+ segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+ }
+ while (++i < n) {
+ if (defined.call(this, d = data[i], i)) {
+ points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
+ points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
+ } else if (points0.length) {
+ segment();
+ points0 = [];
+ points1 = [];
+ }
+ }
+ if (points0.length) segment();
+ return segments.length ? segments.join("") : null;
}
- d3_geo_pathCentroid.lineEnd = function() {
- nextPoint(x00, y00);
+ area.x = function(_) {
+ if (!arguments.length) return x1;
+ x0 = x1 = _;
+ return area;
+ };
+ area.x0 = function(_) {
+ if (!arguments.length) return x0;
+ x0 = _;
+ return area;
+ };
+ area.x1 = function(_) {
+ if (!arguments.length) return x1;
+ x1 = _;
+ return area;
+ };
+ area.y = function(_) {
+ if (!arguments.length) return y1;
+ y0 = y1 = _;
+ return area;
+ };
+ area.y0 = function(_) {
+ if (!arguments.length) return y0;
+ y0 = _;
+ return area;
+ };
+ area.y1 = function(_) {
+ if (!arguments.length) return y1;
+ y1 = _;
+ return area;
+ };
+ area.defined = function(_) {
+ if (!arguments.length) return defined;
+ defined = _;
+ return area;
+ };
+ area.interpolate = function(_) {
+ if (!arguments.length) return interpolateKey;
+ if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+ interpolateReverse = interpolate.reverse || interpolate;
+ L = interpolate.closed ? "M" : "L";
+ return area;
+ };
+ area.tension = function(_) {
+ if (!arguments.length) return tension;
+ tension = _;
+ return area;
};
+ return area;
}
- d3.geo.area = function(object) {
- d3_geo_areaSum = 0;
- d3.geo.stream(object, d3_geo_area);
- return d3_geo_areaSum;
+ d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+ d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+ d3.svg.area = function() {
+ return d3_svg_area(d3_identity);
};
- var d3_geo_areaSum, d3_geo_areaRingU, d3_geo_areaRingV;
- var d3_geo_area = {
- sphere: function() {
- d3_geo_areaSum += 4 * π;
- },
- point: d3_noop,
- lineStart: d3_noop,
- lineEnd: d3_noop,
- polygonStart: function() {
- d3_geo_areaRingU = 1, d3_geo_areaRingV = 0;
- d3_geo_area.lineStart = d3_geo_areaRingStart;
- },
- polygonEnd: function() {
- var area = 2 * Math.atan2(d3_geo_areaRingV, d3_geo_areaRingU);
- d3_geo_areaSum += area < 0 ? 4 * π + area : area;
- d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
- }
+ d3.svg.area.radial = function() {
+ var area = d3_svg_area(d3_svg_lineRadial);
+ area.radius = area.x, delete area.x;
+ area.innerRadius = area.x0, delete area.x0;
+ area.outerRadius = area.x1, delete area.x1;
+ area.angle = area.y, delete area.y;
+ area.startAngle = area.y0, delete area.y0;
+ area.endAngle = area.y1, delete area.y1;
+ return area;
};
- function d3_geo_areaRingStart() {
- var λ00, φ00, λ0, cosφ0, sinφ0;
- d3_geo_area.point = function(λ, φ) {
- d3_geo_area.point = nextPoint;
- λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4),
- sinφ0 = Math.sin(φ);
- };
- function nextPoint(λ, φ) {
- λ *= d3_radians;
- φ = φ * d3_radians / 2 + π / 4;
- var dλ = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u0 = d3_geo_areaRingU, v0 = d3_geo_areaRingV, u = cosφ0 * cosφ + k * Math.cos(dλ), v = k * Math.sin(dλ);
- d3_geo_areaRingU = u0 * u - v0 * v;
- d3_geo_areaRingV = v0 * u + u0 * v;
- λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
+ d3.svg.chord = function() {
+ var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+ function chord(d, i) {
+ var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
+ return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
}
- d3_geo_area.lineEnd = function() {
- nextPoint(λ00, φ00);
- };
- }
- d3.geo.projection = d3_geo_projection;
- d3.geo.projectionMutator = d3_geo_projectionMutator;
- function d3_geo_projection(project) {
- return d3_geo_projectionMutator(function() {
- return project;
- })();
- }
- function d3_geo_projectionMutator(projectAt) {
- var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
- x = project(x, y);
- return [ x[0] * k + δx, δy - x[1] * k ];
- }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, clip = d3_geo_clipAntimeridian, clipAngle = null;
- function projection(point) {
- point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
- return [ point[0] * k + δx, δy - point[1] * k ];
+ function subgroup(self, f, d, i) {
+ var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
+ return {
+ r: r,
+ a0: a0,
+ a1: a1,
+ p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
+ p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
+ };
}
- function invert(point) {
- point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
- return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
+ function equals(a, b) {
+ return a.a0 == b.a0 && a.a1 == b.a1;
}
- projection.stream = function(stream) {
- return d3_geo_projectionRadiansRotate(rotate, clip(projectResample(stream)));
- };
- projection.clipAngle = function(_) {
- if (!arguments.length) return clipAngle;
- clip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle(clipAngle = +_);
- return projection;
+ function arc(r, p, a) {
+ return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
+ }
+ function curve(r0, p0, r1, p1) {
+ return "Q 0,0 " + p1;
+ }
+ chord.radius = function(v) {
+ if (!arguments.length) return radius;
+ radius = d3_functor(v);
+ return chord;
};
- projection.scale = function(_) {
- if (!arguments.length) return k;
- k = +_;
- return reset();
+ chord.source = function(v) {
+ if (!arguments.length) return source;
+ source = d3_functor(v);
+ return chord;
};
- projection.translate = function(_) {
- if (!arguments.length) return [ x, y ];
- x = +_[0];
- y = +_[1];
- return reset();
+ chord.target = function(v) {
+ if (!arguments.length) return target;
+ target = d3_functor(v);
+ return chord;
};
- projection.center = function(_) {
- if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
- λ = _[0] % 360 * d3_radians;
- φ = _[1] % 360 * d3_radians;
- return reset();
+ chord.startAngle = function(v) {
+ if (!arguments.length) return startAngle;
+ startAngle = d3_functor(v);
+ return chord;
};
- projection.rotate = function(_) {
- if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
- δλ = _[0] % 360 * d3_radians;
- δφ = _[1] % 360 * d3_radians;
- δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
- return reset();
+ chord.endAngle = function(v) {
+ if (!arguments.length) return endAngle;
+ endAngle = d3_functor(v);
+ return chord;
};
- d3.rebind(projection, projectResample, "precision");
- function reset() {
- projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
- var center = project(λ, φ);
- δx = x - center[0] * k;
- δy = y + center[1] * k;
- return projection;
+ return chord;
+ };
+ function d3_svg_chordRadius(d) {
+ return d.radius;
+ }
+ d3.svg.diagonal = function() {
+ var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
+ function diagonal(d, i) {
+ var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
+ x: p0.x,
+ y: m
+ }, {
+ x: p3.x,
+ y: m
+ }, p3 ];
+ p = p.map(projection);
+ return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
}
- return function() {
- project = projectAt.apply(this, arguments);
- projection.invert = project.invert && invert;
- return reset();
+ diagonal.source = function(x) {
+ if (!arguments.length) return source;
+ source = d3_functor(x);
+ return diagonal;
};
- }
- function d3_geo_projectionRadiansRotate(rotate, stream) {
- return {
- point: function(x, y) {
- y = rotate(x * d3_radians, y * d3_radians), x = y[0];
- stream.point(x > π ? x - 2 * π : x < -π ? x + 2 * π : x, y[1]);
- },
- sphere: function() {
- stream.sphere();
- },
- lineStart: function() {
- stream.lineStart();
- },
- lineEnd: function() {
- stream.lineEnd();
- },
- polygonStart: function() {
- stream.polygonStart();
- },
- polygonEnd: function() {
- stream.polygonEnd();
- }
+ diagonal.target = function(x) {
+ if (!arguments.length) return target;
+ target = d3_functor(x);
+ return diagonal;
};
- }
- function d3_geo_rotation(δλ, δφ, δγ) {
- return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_equirectangular;
- }
- function d3_geo_forwardRotationλ(δλ) {
- return function(λ, φ) {
- return λ += δλ, [ λ > π ? λ - 2 * π : λ < -π ? λ + 2 * π : λ, φ ];
+ diagonal.projection = function(x) {
+ if (!arguments.length) return projection;
+ projection = x;
+ return diagonal;
};
+ return diagonal;
+ };
+ function d3_svg_diagonalProjection(d) {
+ return [ d.x, d.y ];
}
- function d3_geo_rotationλ(δλ) {
- var rotation = d3_geo_forwardRotationλ(δλ);
- rotation.invert = d3_geo_forwardRotationλ(-δλ);
- return rotation;
- }
- function d3_geo_rotationφγ(δφ, δγ) {
- var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
- function rotation(λ, φ) {
- var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
- return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδγ + y * sinδγ))) ];
- }
- rotation.invert = function(λ, φ) {
- var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
- return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), Math.asin(Math.max(-1, Math.min(1, k * cosδφ - x * sinδφ))) ];
+ d3.svg.diagonal.radial = function() {
+ var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
+ diagonal.projection = function(x) {
+ return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
+ };
+ return diagonal;
+ };
+ function d3_svg_diagonalRadialProjection(projection) {
+ return function() {
+ var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
+ return [ r * Math.cos(a), r * Math.sin(a) ];
};
- return rotation;
}
- var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
- return 1 / (1 + cosλcosφ);
- }, function(ρ) {
- return 2 * Math.atan(ρ);
- });
- (d3.geo.stereographic = function() {
- return d3_geo_projection(d3_geo_stereographic);
- }).raw = d3_geo_stereographic;
- function d3_geo_azimuthal(scale, angle) {
- function azimuthal(λ, φ) {
- var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
- return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
+ d3.svg.symbol = function() {
+ var type = d3_svg_symbolType, size = d3_svg_symbolSize;
+ function symbol(d, i) {
+ return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
}
- azimuthal.invert = function(x, y) {
- var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
- return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
+ symbol.type = function(x) {
+ if (!arguments.length) return type;
+ type = d3_functor(x);
+ return symbol;
};
- return azimuthal;
+ symbol.size = function(x) {
+ if (!arguments.length) return size;
+ size = d3_functor(x);
+ return symbol;
+ };
+ return symbol;
+ };
+ function d3_svg_symbolSize() {
+ return 64;
}
- d3.geom = {};
- d3.geom.hull = function(vertices) {
- if (vertices.length < 3) return [];
- var len = vertices.length, plen = len - 1, points = [], stack = [], i, j, h = 0, x1, y1, x2, y2, u, v, a, sp;
- for (i = 1; i < len; ++i) {
- if (vertices[i][1] < vertices[h][1]) {
- h = i;
- } else if (vertices[i][1] == vertices[h][1]) {
- h = vertices[i][0] < vertices[h][0] ? i : h;
- }
- }
- for (i = 0; i < len; ++i) {
- if (i === h) continue;
- y1 = vertices[i][1] - vertices[h][1];
- x1 = vertices[i][0] - vertices[h][0];
- points.push({
- angle: Math.atan2(y1, x1),
- index: i
- });
+ function d3_svg_symbolType() {
+ return "circle";
+ }
+ function d3_svg_symbolCircle(size) {
+ var r = Math.sqrt(size / π);
+ return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
+ }
+ var d3_svg_symbols = d3.map({
+ circle: d3_svg_symbolCircle,
+ cross: function(size) {
+ var r = Math.sqrt(size / 5) / 2;
+ return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
+ },
+ diamond: function(size) {
+ var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
+ return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
+ },
+ square: function(size) {
+ var r = Math.sqrt(size) / 2;
+ return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
+ },
+ "triangle-down": function(size) {
+ var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+ return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
+ },
+ "triangle-up": function(size) {
+ var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+ return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
}
- points.sort(function(a, b) {
- return a.angle - b.angle;
- });
- a = points[0].angle;
- v = points[0].index;
- u = 0;
- for (i = 1; i < plen; ++i) {
- j = points[i].index;
- if (a == points[i].angle) {
- x1 = vertices[v][0] - vertices[h][0];
- y1 = vertices[v][1] - vertices[h][1];
- x2 = vertices[j][0] - vertices[h][0];
- y2 = vertices[j][1] - vertices[h][1];
- if (x1 * x1 + y1 * y1 >= x2 * x2 + y2 * y2) {
- points[i].index = -1;
+ });
+ d3.svg.symbolTypes = d3_svg_symbols.keys();
+ var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+ function d3_transition(groups, id) {
+ d3_arraySubclass(groups, d3_transitionPrototype);
+ groups.id = id;
+ return groups;
+ }
+ var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit = {
+ ease: d3_ease_cubicInOut,
+ delay: 0,
+ duration: 250
+ };
+ d3_transitionPrototype.call = d3_selectionPrototype.call;
+ d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+ d3_transitionPrototype.node = d3_selectionPrototype.node;
+ d3.transition = function(selection) {
+ return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+ };
+ d3.transition.prototype = d3_transitionPrototype;
+ d3_transitionPrototype.select = function(selector) {
+ var id = this.id, subgroups = [], subgroup, subnode, node;
+ if (typeof selector !== "function") selector = d3_selection_selector(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i))) {
+ if ("__data__" in node) subnode.__data__ = node.__data__;
+ d3_transitionNode(subnode, i, id, node.__transition__[id]);
+ subgroup.push(subnode);
} else {
- points[u].index = -1;
- a = points[i].angle;
- u = i;
- v = j;
+ subgroup.push(null);
}
- } else {
- a = points[i].angle;
- u = i;
- v = j;
}
}
- stack.push(h);
- for (i = 0, j = 0; i < 2; ++j) {
- if (points[j].index !== -1) {
- stack.push(points[j].index);
- i++;
+ return d3_transition(subgroups, id);
+ };
+ d3_transitionPrototype.selectAll = function(selector) {
+ var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
+ if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ transition = node.__transition__[id];
+ subnodes = selector.call(node, node.__data__, i);
+ subgroups.push(subgroup = []);
+ for (var k = -1, o = subnodes.length; ++k < o; ) {
+ d3_transitionNode(subnode = subnodes[k], k, id, transition);
+ subgroup.push(subnode);
+ }
+ }
}
}
- sp = stack.length;
- for (;j < plen; ++j) {
- if (points[j].index === -1) continue;
- while (!d3_geom_hullCCW(stack[sp - 2], stack[sp - 1], points[j].index, vertices)) {
- --sp;
+ return d3_transition(subgroups, id);
+ };
+ d3_transitionPrototype.filter = function(filter) {
+ var subgroups = [], subgroup, group, node;
+ if (typeof filter !== "function") filter = d3_selection_filter(filter);
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i)) {
+ subgroup.push(node);
+ }
}
- stack[sp++] = points[j].index;
- }
- var poly = [];
- for (i = 0; i < sp; ++i) {
- poly.push(vertices[stack[i]]);
}
- return poly;
+ return d3_transition(subgroups, this.id, this.time).ease(this.ease());
};
- function d3_geom_hullCCW(i1, i2, i3, v) {
- var t, a, b, c, d, e, f;
- t = v[i1];
- a = t[0];
- b = t[1];
- t = v[i2];
- c = t[0];
- d = t[1];
- t = v[i3];
- e = t[0];
- f = t[1];
- return (f - b) * (c - a) - (d - b) * (e - a) > 0;
+ d3_transitionPrototype.tween = function(name, tween) {
+ var id = this.id;
+ if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
+ return d3_selection_each(this, tween == null ? function(node) {
+ node.__transition__[id].tween.remove(name);
+ } : function(node) {
+ node.__transition__[id].tween.set(name, tween);
+ });
+ };
+ function d3_transition_tween(groups, name, value, tween) {
+ var id = groups.id;
+ return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+ } : (value = tween(value), function(node) {
+ node.__transition__[id].tween.set(name, value);
+ }));
}
- d3.geom.polygon = function(coordinates) {
- coordinates.area = function() {
- var i = 0, n = coordinates.length, area = coordinates[n - 1][1] * coordinates[0][0] - coordinates[n - 1][0] * coordinates[0][1];
- while (++i < n) {
- area += coordinates[i - 1][1] * coordinates[i][0] - coordinates[i - 1][0] * coordinates[i][1];
- }
- return area * .5;
- };
- coordinates.centroid = function(k) {
- var i = -1, n = coordinates.length, x = 0, y = 0, a, b = coordinates[n - 1], c;
- if (!arguments.length) k = -1 / (6 * coordinates.area());
- while (++i < n) {
- a = b;
- b = coordinates[i];
- c = a[0] * b[1] - b[0] * a[1];
- x += (a[0] + b[0]) * c;
- y += (a[1] + b[1]) * c;
- }
- return [ x * k, y * k ];
- };
- coordinates.clip = function(subject) {
- var input, i = -1, n = coordinates.length, j, m, a = coordinates[n - 1], b, c, d;
- while (++i < n) {
- input = subject.slice();
- subject.length = 0;
- b = coordinates[i];
- c = input[(m = input.length) - 1];
- j = -1;
- while (++j < m) {
- d = input[j];
- if (d3_geom_polygonInside(d, a, b)) {
- if (!d3_geom_polygonInside(c, a, b)) {
- subject.push(d3_geom_polygonIntersect(c, d, a, b));
- }
- subject.push(d);
- } else if (d3_geom_polygonInside(c, a, b)) {
- subject.push(d3_geom_polygonIntersect(c, d, a, b));
- }
- c = d;
- }
- a = b;
+ d3_transitionPrototype.attr = function(nameNS, value) {
+ if (arguments.length < 2) {
+ for (value in nameNS) this.attr(value, nameNS[value]);
+ return this;
+ }
+ var interpolate = d3_interpolateByName(nameNS), name = d3.ns.qualify(nameNS);
+ function attrNull() {
+ this.removeAttribute(name);
+ }
+ function attrNullNS() {
+ this.removeAttributeNS(name.space, name.local);
+ }
+ function attrTween(b) {
+ return b == null ? attrNull : (b += "", function() {
+ var a = this.getAttribute(name), i;
+ return a !== b && (i = interpolate(a, b), function(t) {
+ this.setAttribute(name, i(t));
+ });
+ });
+ }
+ function attrTweenNS(b) {
+ return b == null ? attrNullNS : (b += "", function() {
+ var a = this.getAttributeNS(name.space, name.local), i;
+ return a !== b && (i = interpolate(a, b), function(t) {
+ this.setAttributeNS(name.space, name.local, i(t));
+ });
+ });
+ }
+ return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
+ };
+ d3_transitionPrototype.attrTween = function(nameNS, tween) {
+ var name = d3.ns.qualify(nameNS);
+ function attrTween(d, i) {
+ var f = tween.call(this, d, i, this.getAttribute(name));
+ return f && function(t) {
+ this.setAttribute(name, f(t));
+ };
+ }
+ function attrTweenNS(d, i) {
+ var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
+ return f && function(t) {
+ this.setAttributeNS(name.space, name.local, f(t));
+ };
+ }
+ return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
+ };
+ d3_transitionPrototype.style = function(name, value, priority) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof name !== "string") {
+ if (n < 2) value = "";
+ for (priority in name) this.style(priority, name[priority], value);
+ return this;
}
- return subject;
- };
- return coordinates;
+ priority = "";
+ }
+ var interpolate = d3_interpolateByName(name);
+ function styleNull() {
+ this.style.removeProperty(name);
+ }
+ function styleString(b) {
+ return b == null ? styleNull : (b += "", function() {
+ var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
+ return a !== b && (i = interpolate(a, b), function(t) {
+ this.style.setProperty(name, i(t), priority);
+ });
+ });
+ }
+ return d3_transition_tween(this, "style." + name, value, styleString);
};
- function d3_geom_polygonInside(p, a, b) {
- return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
- }
- function d3_geom_polygonIntersect(c, d, a, b) {
- var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
- return [ x1 + ua * x21, y1 + ua * y21 ];
+ d3_transitionPrototype.styleTween = function(name, tween, priority) {
+ if (arguments.length < 3) priority = "";
+ function styleTween(d, i) {
+ var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
+ return f && function(t) {
+ this.style.setProperty(name, f(t), priority);
+ };
+ }
+ return this.tween("style." + name, styleTween);
+ };
+ d3_transitionPrototype.text = function(value) {
+ return d3_transition_tween(this, "text", value, d3_transition_text);
+ };
+ function d3_transition_text(b) {
+ if (b == null) b = "";
+ return function() {
+ this.textContent = b;
+ };
}
- d3.geom.voronoi = function(vertices) {
- var polygons = vertices.map(function() {
- return [];
- }), Z = 1e6;
- d3_voronoi_tessellate(vertices, function(e) {
- var s1, s2, x1, x2, y1, y2;
- if (e.a === 1 && e.b >= 0) {
- s1 = e.ep.r;
- s2 = e.ep.l;
- } else {
- s1 = e.ep.l;
- s2 = e.ep.r;
- }
- if (e.a === 1) {
- y1 = s1 ? s1.y : -Z;
- x1 = e.c - e.b * y1;
- y2 = s2 ? s2.y : Z;
- x2 = e.c - e.b * y2;
- } else {
- x1 = s1 ? s1.x : -Z;
- y1 = e.c - e.a * x1;
- x2 = s2 ? s2.x : Z;
- y2 = e.c - e.a * x2;
- }
- var v1 = [ x1, y1 ], v2 = [ x2, y2 ];
- polygons[e.region.l.index].push(v1, v2);
- polygons[e.region.r.index].push(v1, v2);
+ d3_transitionPrototype.remove = function() {
+ return this.each("end.transition", function() {
+ var p;
+ if (!this.__transition__ && (p = this.parentNode)) p.removeChild(this);
+ });
+ };
+ d3_transitionPrototype.ease = function(value) {
+ var id = this.id;
+ if (arguments.length < 1) return this.node().__transition__[id].ease;
+ if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
+ return d3_selection_each(this, function(node) {
+ node.__transition__[id].ease = value;
});
- polygons = polygons.map(function(polygon, i) {
- var cx = vertices[i][0], cy = vertices[i][1], angle = polygon.map(function(v) {
- return Math.atan2(v[0] - cx, v[1] - cy);
- }), order = d3.range(polygon.length).sort(function(a, b) {
- return angle[a] - angle[b];
+ };
+ d3_transitionPrototype.delay = function(value) {
+ var id = this.id;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].delay = value.call(node, node.__data__, i, j) | 0;
+ } : (value |= 0, function(node) {
+ node.__transition__[id].delay = value;
+ }));
+ };
+ d3_transitionPrototype.duration = function(value) {
+ var id = this.id;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j) | 0);
+ } : (value = Math.max(1, value | 0), function(node) {
+ node.__transition__[id].duration = value;
+ }));
+ };
+ d3_transitionPrototype.each = function(type, listener) {
+ var id = this.id;
+ if (arguments.length < 2) {
+ var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+ d3_transitionInheritId = id;
+ d3_selection_each(this, function(node, i, j) {
+ d3_transitionInherit = node.__transition__[id];
+ type.call(node, node.__data__, i, j);
});
- return order.filter(function(d, i) {
- return !i || angle[d] - angle[order[i - 1]] > ε;
- }).map(function(d) {
- return polygon[d];
+ d3_transitionInherit = inherit;
+ d3_transitionInheritId = inheritId;
+ } else {
+ d3_selection_each(this, function(node) {
+ node.__transition__[id].event.on(type, listener);
});
- });
- polygons.forEach(function(polygon, i) {
- var n = polygon.length;
- if (!n) return polygon.push([ -Z, -Z ], [ -Z, Z ], [ Z, Z ], [ Z, -Z ]);
- if (n > 2) return;
- var p0 = vertices[i], p1 = polygon[0], p2 = polygon[1], x0 = p0[0], y0 = p0[1], x1 = p1[0], y1 = p1[1], x2 = p2[0], y2 = p2[1], dx = Math.abs(x2 - x1), dy = y2 - y1;
- if (Math.abs(dy) < ε) {
- var y = y0 < y1 ? -Z : Z;
- polygon.push([ -Z, y ], [ Z, y ]);
- } else if (dx < ε) {
- var x = x0 < x1 ? -Z : Z;
- polygon.push([ x, -Z ], [ x, Z ]);
- } else {
- var y = (x2 - x1) * (y1 - y0) < (x1 - x0) * (y2 - y1) ? Z : -Z, z = Math.abs(dy) - dx;
- if (Math.abs(z) < ε) {
- polygon.push([ dy < 0 ? y : -y, y ]);
- } else {
- if (z > 0) y *= -1;
- polygon.push([ -Z, y ], [ Z, y ]);
+ }
+ return this;
+ };
+ d3_transitionPrototype.transition = function() {
+ var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ if (node = group[i]) {
+ transition = Object.create(node.__transition__[id0]);
+ transition.delay += transition.duration;
+ d3_transitionNode(node, i, id1, transition);
}
+ subgroup.push(node);
}
- });
- return polygons;
- };
- var d3_voronoi_opposite = {
- l: "r",
- r: "l"
+ }
+ return d3_transition(subgroups, id1);
};
- function d3_voronoi_tessellate(vertices, callback) {
- var Sites = {
- list: vertices.map(function(v, i) {
- return {
- index: i,
- x: v[0],
- y: v[1]
- };
- }).sort(function(a, b) {
- return a.y < b.y ? -1 : a.y > b.y ? 1 : a.x < b.x ? -1 : a.x > b.x ? 1 : 0;
- }),
- bottomSite: null
- };
- var EdgeList = {
- list: [],
- leftEnd: null,
- rightEnd: null,
- init: function() {
- EdgeList.leftEnd = EdgeList.createHalfEdge(null, "l");
- EdgeList.rightEnd = EdgeList.createHalfEdge(null, "l");
- EdgeList.leftEnd.r = EdgeList.rightEnd;
- EdgeList.rightEnd.l = EdgeList.leftEnd;
- EdgeList.list.unshift(EdgeList.leftEnd, EdgeList.rightEnd);
- },
- createHalfEdge: function(edge, side) {
- return {
- edge: edge,
- side: side,
- vertex: null,
- l: null,
- r: null
- };
- },
- insert: function(lb, he) {
- he.l = lb;
- he.r = lb.r;
- lb.r.l = he;
- lb.r = he;
- },
- leftBound: function(p) {
- var he = EdgeList.leftEnd;
- do {
- he = he.r;
- } while (he != EdgeList.rightEnd && Geom.rightOf(he, p));
- he = he.l;
- return he;
- },
- del: function(he) {
- he.l.r = he.r;
- he.r.l = he.l;
- he.edge = null;
- },
- right: function(he) {
- return he.r;
- },
- left: function(he) {
- return he.l;
- },
- leftRegion: function(he) {
- return he.edge == null ? Sites.bottomSite : he.edge.region[he.side];
- },
- rightRegion: function(he) {
- return he.edge == null ? Sites.bottomSite : he.edge.region[d3_voronoi_opposite[he.side]];
- }
- };
- var Geom = {
- bisect: function(s1, s2) {
- var newEdge = {
- region: {
- l: s1,
- r: s2
- },
- ep: {
- l: null,
- r: null
+ function d3_transitionNode(node, i, id, inherit) {
+ var lock = node.__transition__ || (node.__transition__ = {
+ active: 0,
+ count: 0
+ }), transition = lock[id];
+ if (!transition) {
+ var time = inherit.time;
+ transition = lock[id] = {
+ tween: new d3_Map(),
+ event: d3.dispatch("start", "end"),
+ time: time,
+ ease: inherit.ease,
+ delay: inherit.delay,
+ duration: inherit.duration
+ };
+ ++lock.count;
+ d3.timer(function(elapsed) {
+ var d = node.__data__, ease = transition.ease, event = transition.event, delay = transition.delay, duration = transition.duration, tweened = [];
+ return delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time), 1;
+ function start(elapsed) {
+ if (lock.active > id) return stop();
+ lock.active = id;
+ event.start.call(node, d, i);
+ transition.tween.forEach(function(key, value) {
+ if (value = value.call(node, d, i)) {
+ tweened.push(value);
+ }
+ });
+ if (!tick(elapsed)) d3.timer(tick, 0, time);
+ return 1;
+ }
+ function tick(elapsed) {
+ if (lock.active !== id) return stop();
+ var t = (elapsed - delay) / duration, e = ease(t), n = tweened.length;
+ while (n > 0) {
+ tweened[--n].call(node, e);
+ }
+ if (t >= 1) {
+ stop();
+ event.end.call(node, d, i);
+ return 1;
+ }
+ }
+ function stop() {
+ if (--lock.count) delete lock[id]; else delete node.__transition__;
+ return 1;
+ }
+ }, 0, time);
+ return transition;
+ }
+ }
+ d3.svg.axis = function() {
+ var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, tickMajorSize = 6, tickMinorSize = 6, tickEndSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_, tickSubdivide = 0;
+ function axis(g) {
+ g.each(function() {
+ var g = d3.select(this);
+ var ticks = tickValues == null ? scale.ticks ? scale.ticks.apply(scale, tickArguments_) : scale.domain() : tickValues, tickFormat = tickFormat_ == null ? scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments_) : String : tickFormat_;
+ var subticks = d3_svg_axisSubdivide(scale, ticks, tickSubdivide), subtick = g.selectAll(".tick.minor").data(subticks, String), subtickEnter = subtick.enter().insert("line", ".tick").attr("class", "tick minor").style("opacity", 1e-6), subtickExit = d3.transition(subtick.exit()).style("opacity", 1e-6).remove(), subtickUpdate = d3.transition(subtick).style("opacity", 1);
+ var tick = g.selectAll(".tick.major").data(ticks, String), tickEnter = tick.enter().insert("g", "path").attr("class", "tick major").style("opacity", 1e-6), tickExit = d3.transition(tick.exit()).style("opacity", 1e-6).remove(), tickUpdate = d3.transition(tick).style("opacity", 1), tickTransform;
+ var range = d3_scaleRange(scale), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
+ d3.transition(path));
+ var scale1 = scale.copy(), scale0 = this.__chart__ || scale1;
+ this.__chart__ = scale1;
+ tickEnter.append("line");
+ tickEnter.append("text");
+ var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
+ switch (orient) {
+ case "bottom":
+ {
+ tickTransform = d3_svg_axisX;
+ subtickEnter.attr("y2", tickMinorSize);
+ subtickUpdate.attr("x2", 0).attr("y2", tickMinorSize);
+ lineEnter.attr("y2", tickMajorSize);
+ textEnter.attr("y", Math.max(tickMajorSize, 0) + tickPadding);
+ lineUpdate.attr("x2", 0).attr("y2", tickMajorSize);
+ textUpdate.attr("x", 0).attr("y", Math.max(tickMajorSize, 0) + tickPadding);
+ text.attr("dy", ".71em").style("text-anchor", "middle");
+ pathUpdate.attr("d", "M" + range[0] + "," + tickEndSize + "V0H" + range[1] + "V" + tickEndSize);
+ break;
+ }
+
+ case "top":
+ {
+ tickTransform = d3_svg_axisX;
+ subtickEnter.attr("y2", -tickMinorSize);
+ subtickUpdate.attr("x2", 0).attr("y2", -tickMinorSize);
+ lineEnter.attr("y2", -tickMajorSize);
+ textEnter.attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
+ lineUpdate.attr("x2", 0).attr("y2", -tickMajorSize);
+ textUpdate.attr("x", 0).attr("y", -(Math.max(tickMajorSize, 0) + tickPadding));
+ text.attr("dy", "0em").style("text-anchor", "middle");
+ pathUpdate.attr("d", "M" + range[0] + "," + -tickEndSize + "V0H" + range[1] + "V" + -tickEndSize);
+ break;
+ }
+
+ case "left":
+ {
+ tickTransform = d3_svg_axisY;
+ subtickEnter.attr("x2", -tickMinorSize);
+ subtickUpdate.attr("x2", -tickMinorSize).attr("y2", 0);
+ lineEnter.attr("x2", -tickMajorSize);
+ textEnter.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding));
+ lineUpdate.attr("x2", -tickMajorSize).attr("y2", 0);
+ textUpdate.attr("x", -(Math.max(tickMajorSize, 0) + tickPadding)).attr("y", 0);
+ text.attr("dy", ".32em").style("text-anchor", "end");
+ pathUpdate.attr("d", "M" + -tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + -tickEndSize);
+ break;
+ }
+
+ case "right":
+ {
+ tickTransform = d3_svg_axisY;
+ subtickEnter.attr("x2", tickMinorSize);
+ subtickUpdate.attr("x2", tickMinorSize).attr("y2", 0);
+ lineEnter.attr("x2", tickMajorSize);
+ textEnter.attr("x", Math.max(tickMajorSize, 0) + tickPadding);
+ lineUpdate.attr("x2", tickMajorSize).attr("y2", 0);
+ textUpdate.attr("x", Math.max(tickMajorSize, 0) + tickPadding).attr("y", 0);
+ text.attr("dy", ".32em").style("text-anchor", "start");
+ pathUpdate.attr("d", "M" + tickEndSize + "," + range[0] + "H0V" + range[1] + "H" + tickEndSize);
+ break;
}
- };
- var dx = s2.x - s1.x, dy = s2.y - s1.y, adx = dx > 0 ? dx : -dx, ady = dy > 0 ? dy : -dy;
- newEdge.c = s1.x * dx + s1.y * dy + (dx * dx + dy * dy) * .5;
- if (adx > ady) {
- newEdge.a = 1;
- newEdge.b = dy / dx;
- newEdge.c /= dx;
- } else {
- newEdge.b = 1;
- newEdge.a = dx / dy;
- newEdge.c /= dy;
- }
- return newEdge;
- },
- intersect: function(el1, el2) {
- var e1 = el1.edge, e2 = el2.edge;
- if (!e1 || !e2 || e1.region.r == e2.region.r) {
- return null;
- }
- var d = e1.a * e2.b - e1.b * e2.a;
- if (Math.abs(d) < 1e-10) {
- return null;
}
- var xint = (e1.c * e2.b - e2.c * e1.b) / d, yint = (e2.c * e1.a - e1.c * e2.a) / d, e1r = e1.region.r, e2r = e2.region.r, el, e;
- if (e1r.y < e2r.y || e1r.y == e2r.y && e1r.x < e2r.x) {
- el = el1;
- e = e1;
+ if (scale.ticks) {
+ tickEnter.call(tickTransform, scale0);
+ tickUpdate.call(tickTransform, scale1);
+ tickExit.call(tickTransform, scale1);
+ subtickEnter.call(tickTransform, scale0);
+ subtickUpdate.call(tickTransform, scale1);
+ subtickExit.call(tickTransform, scale1);
} else {
- el = el2;
- e = e2;
- }
- var rightOfSite = xint >= e.region.r.x;
- if (rightOfSite && el.side === "l" || !rightOfSite && el.side === "r") {
- return null;
- }
- return {
- x: xint,
- y: yint
- };
- },
- rightOf: function(he, p) {
- var e = he.edge, topsite = e.region.r, rightOfSite = p.x > topsite.x;
- if (rightOfSite && he.side === "l") {
- return 1;
- }
- if (!rightOfSite && he.side === "r") {
- return 0;
+ var dx = scale1.rangeBand() / 2, x = function(d) {
+ return scale1(d) + dx;
+ };
+ tickEnter.call(tickTransform, x);
+ tickUpdate.call(tickTransform, x);
}
- if (e.a === 1) {
- var dyp = p.y - topsite.y, dxp = p.x - topsite.x, fast = 0, above = 0;
- if (!rightOfSite && e.b < 0 || rightOfSite && e.b >= 0) {
- above = fast = dyp >= e.b * dxp;
- } else {
- above = p.x + p.y * e.b > e.c;
- if (e.b < 0) {
- above = !above;
- }
- if (!above) {
- fast = 1;
- }
- }
- if (!fast) {
- var dxs = topsite.x - e.region.l.x;
- above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1 + 2 * dxp / dxs + e.b * e.b);
- if (e.b < 0) {
- above = !above;
- }
+ });
+ }
+ axis.scale = function(x) {
+ if (!arguments.length) return scale;
+ scale = x;
+ return axis;
+ };
+ axis.orient = function(x) {
+ if (!arguments.length) return orient;
+ orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
+ return axis;
+ };
+ axis.ticks = function() {
+ if (!arguments.length) return tickArguments_;
+ tickArguments_ = arguments;
+ return axis;
+ };
+ axis.tickValues = function(x) {
+ if (!arguments.length) return tickValues;
+ tickValues = x;
+ return axis;
+ };
+ axis.tickFormat = function(x) {
+ if (!arguments.length) return tickFormat_;
+ tickFormat_ = x;
+ return axis;
+ };
+ axis.tickSize = function(x, y) {
+ if (!arguments.length) return tickMajorSize;
+ var n = arguments.length - 1;
+ tickMajorSize = +x;
+ tickMinorSize = n > 1 ? +y : tickMajorSize;
+ tickEndSize = n > 0 ? +arguments[n] : tickMajorSize;
+ return axis;
+ };
+ axis.tickPadding = function(x) {
+ if (!arguments.length) return tickPadding;
+ tickPadding = +x;
+ return axis;
+ };
+ axis.tickSubdivide = function(x) {
+ if (!arguments.length) return tickSubdivide;
+ tickSubdivide = +x;
+ return axis;
+ };
+ return axis;
+ };
+ var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
+ top: 1,
+ right: 1,
+ bottom: 1,
+ left: 1
+ };
+ function d3_svg_axisX(selection, x) {
+ selection.attr("transform", function(d) {
+ return "translate(" + x(d) + ",0)";
+ });
+ }
+ function d3_svg_axisY(selection, y) {
+ selection.attr("transform", function(d) {
+ return "translate(0," + y(d) + ")";
+ });
+ }
+ function d3_svg_axisSubdivide(scale, ticks, m) {
+ subticks = [];
+ if (m && ticks.length > 1) {
+ var extent = d3_scaleExtent(scale.domain()), subticks, i = -1, n = ticks.length, d = (ticks[1] - ticks[0]) / ++m, j, v;
+ while (++i < n) {
+ for (j = m; --j > 0; ) {
+ if ((v = +ticks[i] - j * d) >= extent[0]) {
+ subticks.push(v);
}
- } else {
- var yl = e.c - e.a * p.x, t1 = p.y - yl, t2 = p.x - topsite.x, t3 = yl - topsite.y;
- above = t1 * t1 > t2 * t2 + t3 * t3;
}
- return he.side === "l" ? above : !above;
- },
- endPoint: function(edge, side, site) {
- edge.ep[side] = site;
- if (!edge.ep[d3_voronoi_opposite[side]]) return;
- callback(edge);
- },
- distance: function(s, t) {
- var dx = s.x - t.x, dy = s.y - t.y;
- return Math.sqrt(dx * dx + dy * dy);
}
- };
- var EventQueue = {
- list: [],
- insert: function(he, site, offset) {
- he.vertex = site;
- he.ystar = site.y + offset;
- for (var i = 0, list = EventQueue.list, l = list.length; i < l; i++) {
- var next = list[i];
- if (he.ystar > next.ystar || he.ystar == next.ystar && site.x > next.vertex.x) {
- continue;
- } else {
- break;
+ for (--i, j = 0; ++j < m && (v = +ticks[i] + j * d) < extent[1]; ) {
+ subticks.push(v);
+ }
+ }
+ return subticks;
+ }
+ d3.svg.brush = function() {
+ var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, resizes = d3_svg_brushResizes[0], extent = [ [ 0, 0 ], [ 0, 0 ] ], extentDomain;
+ function brush(g) {
+ g.each(function() {
+ var g = d3.select(this), bg = g.selectAll(".background").data([ 0 ]), fg = g.selectAll(".extent").data([ 0 ]), tz = g.selectAll(".resize").data(resizes, String), e;
+ g.style("pointer-events", "all").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
+ bg.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
+ fg.enter().append("rect").attr("class", "extent").style("cursor", "move");
+ tz.enter().append("g").attr("class", function(d) {
+ return "resize " + d;
+ }).style("cursor", function(d) {
+ return d3_svg_brushCursor[d];
+ }).append("rect").attr("x", function(d) {
+ return /[ew]$/.test(d) ? -3 : null;
+ }).attr("y", function(d) {
+ return /^[ns]/.test(d) ? -3 : null;
+ }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
+ tz.style("display", brush.empty() ? "none" : null);
+ tz.exit().remove();
+ if (x) {
+ e = d3_scaleRange(x);
+ bg.attr("x", e[0]).attr("width", e[1] - e[0]);
+ redrawX(g);
+ }
+ if (y) {
+ e = d3_scaleRange(y);
+ bg.attr("y", e[0]).attr("height", e[1] - e[0]);
+ redrawY(g);
+ }
+ redraw(g);
+ });
+ }
+ function redraw(g) {
+ g.selectAll(".resize").attr("transform", function(d) {
+ return "translate(" + extent[+/e$/.test(d)][0] + "," + extent[+/^s/.test(d)][1] + ")";
+ });
+ }
+ function redrawX(g) {
+ g.select(".extent").attr("x", extent[0][0]);
+ g.selectAll(".extent,.n>rect,.s>rect").attr("width", extent[1][0] - extent[0][0]);
+ }
+ function redrawY(g) {
+ g.select(".extent").attr("y", extent[0][1]);
+ g.selectAll(".extent,.e>rect,.w>rect").attr("height", extent[1][1] - extent[0][1]);
+ }
+ function brushstart() {
+ var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), center, origin = mouse(), offset;
+ var w = d3.select(d3_window).on("mousemove.brush", brushmove).on("mouseup.brush", brushend).on("touchmove.brush", brushmove).on("touchend.brush", brushend).on("keydown.brush", keydown).on("keyup.brush", keyup);
+ if (dragging) {
+ origin[0] = extent[0][0] - origin[0];
+ origin[1] = extent[0][1] - origin[1];
+ } else if (resizing) {
+ var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+ offset = [ extent[1 - ex][0] - origin[0], extent[1 - ey][1] - origin[1] ];
+ origin[0] = extent[ex][0];
+ origin[1] = extent[ey][1];
+ } else if (d3.event.altKey) center = origin.slice();
+ g.style("pointer-events", "none").selectAll(".resize").style("display", null);
+ d3.select("body").style("cursor", eventTarget.style("cursor"));
+ event_({
+ type: "brushstart"
+ });
+ brushmove();
+ d3_eventCancel();
+ function mouse() {
+ var touches = d3.event.changedTouches;
+ return touches ? d3.touches(target, touches)[0] : d3.mouse(target);
+ }
+ function keydown() {
+ if (d3.event.keyCode == 32) {
+ if (!dragging) {
+ center = null;
+ origin[0] -= extent[1][0];
+ origin[1] -= extent[1][1];
+ dragging = 2;
}
+ d3_eventCancel();
}
- list.splice(i, 0, he);
- },
- del: function(he) {
- for (var i = 0, ls = EventQueue.list, l = ls.length; i < l && ls[i] != he; ++i) {}
- ls.splice(i, 1);
- },
- empty: function() {
- return EventQueue.list.length === 0;
- },
- nextEvent: function(he) {
- for (var i = 0, ls = EventQueue.list, l = ls.length; i < l; ++i) {
- if (ls[i] == he) return ls[i + 1];
- }
- return null;
- },
- min: function() {
- var elem = EventQueue.list[0];
- return {
- x: elem.vertex.x,
- y: elem.ystar
- };
- },
- extractMin: function() {
- return EventQueue.list.shift();
}
- };
- EdgeList.init();
- Sites.bottomSite = Sites.list.shift();
- var newSite = Sites.list.shift(), newIntStar;
- var lbnd, rbnd, llbnd, rrbnd, bisector;
- var bot, top, temp, p, v;
- var e, pm;
- while (true) {
- if (!EventQueue.empty()) {
- newIntStar = EventQueue.min();
+ function keyup() {
+ if (d3.event.keyCode == 32 && dragging == 2) {
+ origin[0] += extent[1][0];
+ origin[1] += extent[1][1];
+ dragging = 0;
+ d3_eventCancel();
+ }
}
- if (newSite && (EventQueue.empty() || newSite.y < newIntStar.y || newSite.y == newIntStar.y && newSite.x < newIntStar.x)) {
- lbnd = EdgeList.leftBound(newSite);
- rbnd = EdgeList.right(lbnd);
- bot = EdgeList.rightRegion(lbnd);
- e = Geom.bisect(bot, newSite);
- bisector = EdgeList.createHalfEdge(e, "l");
- EdgeList.insert(lbnd, bisector);
- p = Geom.intersect(lbnd, bisector);
- if (p) {
- EventQueue.del(lbnd);
- EventQueue.insert(lbnd, p, Geom.distance(p, newSite));
+ function brushmove() {
+ var point = mouse(), moved = false;
+ if (offset) {
+ point[0] += offset[0];
+ point[1] += offset[1];
}
- lbnd = bisector;
- bisector = EdgeList.createHalfEdge(e, "r");
- EdgeList.insert(lbnd, bisector);
- p = Geom.intersect(bisector, rbnd);
- if (p) {
- EventQueue.insert(bisector, p, Geom.distance(p, newSite));
+ if (!dragging) {
+ if (d3.event.altKey) {
+ if (!center) center = [ (extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2 ];
+ origin[0] = extent[+(point[0] < center[0])][0];
+ origin[1] = extent[+(point[1] < center[1])][1];
+ } else center = null;
}
- newSite = Sites.list.shift();
- } else if (!EventQueue.empty()) {
- lbnd = EventQueue.extractMin();
- llbnd = EdgeList.left(lbnd);
- rbnd = EdgeList.right(lbnd);
- rrbnd = EdgeList.right(rbnd);
- bot = EdgeList.leftRegion(lbnd);
- top = EdgeList.rightRegion(rbnd);
- v = lbnd.vertex;
- Geom.endPoint(lbnd.edge, lbnd.side, v);
- Geom.endPoint(rbnd.edge, rbnd.side, v);
- EdgeList.del(lbnd);
- EventQueue.del(rbnd);
- EdgeList.del(rbnd);
- pm = "l";
- if (bot.y > top.y) {
- temp = bot;
- bot = top;
- top = temp;
- pm = "r";
+ if (resizingX && move1(point, x, 0)) {
+ redrawX(g);
+ moved = true;
}
- e = Geom.bisect(bot, top);
- bisector = EdgeList.createHalfEdge(e, pm);
- EdgeList.insert(llbnd, bisector);
- Geom.endPoint(e, d3_voronoi_opposite[pm], v);
- p = Geom.intersect(llbnd, bisector);
- if (p) {
- EventQueue.del(llbnd);
- EventQueue.insert(llbnd, p, Geom.distance(p, bot));
+ if (resizingY && move1(point, y, 1)) {
+ redrawY(g);
+ moved = true;
}
- p = Geom.intersect(bisector, rrbnd);
- if (p) {
- EventQueue.insert(bisector, p, Geom.distance(p, bot));
+ if (moved) {
+ redraw(g);
+ event_({
+ type: "brush",
+ mode: dragging ? "move" : "resize"
+ });
}
- } else {
- break;
- }
- }
- for (lbnd = EdgeList.right(EdgeList.leftEnd); lbnd != EdgeList.rightEnd; lbnd = EdgeList.right(lbnd)) {
- callback(lbnd.edge);
- }
- }
- d3.geom.delaunay = function(vertices) {
- var edges = vertices.map(function() {
- return [];
- }), triangles = [];
- d3_voronoi_tessellate(vertices, function(e) {
- edges[e.region.l.index].push(vertices[e.region.r.index]);
- });
- edges.forEach(function(edge, i) {
- var v = vertices[i], cx = v[0], cy = v[1];
- edge.forEach(function(v) {
- v.angle = Math.atan2(v[0] - cx, v[1] - cy);
- });
- edge.sort(function(a, b) {
- return a.angle - b.angle;
- });
- for (var j = 0, m = edge.length - 1; j < m; j++) {
- triangles.push([ v, edge[j], edge[j + 1] ]);
}
- });
- return triangles;
- };
- d3.geom.quadtree = function(points, x1, y1, x2, y2) {
- var p, i = -1, n = points.length;
- if (arguments.length < 5) {
- if (arguments.length === 3) {
- y2 = y1;
- x2 = x1;
- y1 = x1 = 0;
- } else {
- x1 = y1 = Infinity;
- x2 = y2 = -Infinity;
- while (++i < n) {
- p = points[i];
- if (p.x < x1) x1 = p.x;
- if (p.y < y1) y1 = p.y;
- if (p.x > x2) x2 = p.x;
- if (p.y > y2) y2 = p.y;
- }
- }
- }
- var dx = x2 - x1, dy = y2 - y1;
- if (dx > dy) y2 = y1 + dx; else x2 = x1 + dy;
- function insert(n, p, x1, y1, x2, y2) {
- if (isNaN(p.x) || isNaN(p.y)) return;
- if (n.leaf) {
- var v = n.point;
- if (v) {
- if (Math.abs(v.x - p.x) + Math.abs(v.y - p.y) < .01) {
- insertChild(n, p, x1, y1, x2, y2);
+ function move1(point, scale, i) {
+ var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], size = extent[1][i] - extent[0][i], min, max;
+ if (dragging) {
+ r0 -= position;
+ r1 -= size + position;
+ }
+ min = Math.max(r0, Math.min(r1, point[i]));
+ if (dragging) {
+ max = (min += position) + size;
+ } else {
+ if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
+ if (position < min) {
+ max = min;
+ min = position;
} else {
- n.point = null;
- insertChild(n, v, x1, y1, x2, y2);
- insertChild(n, p, x1, y1, x2, y2);
+ max = position;
}
- } else {
- n.point = p;
}
- } else {
- insertChild(n, p, x1, y1, x2, y2);
+ if (extent[0][i] !== min || extent[1][i] !== max) {
+ extentDomain = null;
+ extent[0][i] = min;
+ extent[1][i] = max;
+ return true;
+ }
+ }
+ function brushend() {
+ brushmove();
+ g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
+ d3.select("body").style("cursor", null);
+ w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
+ event_({
+ type: "brushend"
+ });
+ d3_eventCancel();
}
}
- function insertChild(n, p, x1, y1, x2, y2) {
- var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = p.x >= sx, bottom = p.y >= sy, i = (bottom << 1) + right;
- n.leaf = false;
- n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
- if (right) x1 = sx; else x2 = sx;
- if (bottom) y1 = sy; else y2 = sy;
- insert(n, p, x1, y1, x2, y2);
- }
- var root = d3_geom_quadtreeNode();
- root.add = function(p) {
- insert(root, p, x1, y1, x2, y2);
+ brush.x = function(z) {
+ if (!arguments.length) return x;
+ x = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
};
- root.visit = function(f) {
- d3_geom_quadtreeVisit(f, root, x1, y1, x2, y2);
+ brush.y = function(z) {
+ if (!arguments.length) return y;
+ y = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
+ };
+ brush.extent = function(z) {
+ var x0, x1, y0, y1, t;
+ if (!arguments.length) {
+ z = extentDomain || extent;
+ if (x) {
+ x0 = z[0][0], x1 = z[1][0];
+ if (!extentDomain) {
+ x0 = extent[0][0], x1 = extent[1][0];
+ if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ }
+ }
+ if (y) {
+ y0 = z[0][1], y1 = z[1][1];
+ if (!extentDomain) {
+ y0 = extent[0][1], y1 = extent[1][1];
+ if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
+ }
+ }
+ return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
+ }
+ extentDomain = [ [ 0, 0 ], [ 0, 0 ] ];
+ if (x) {
+ x0 = z[0], x1 = z[1];
+ if (y) x0 = x0[0], x1 = x1[0];
+ extentDomain[0][0] = x0, extentDomain[1][0] = x1;
+ if (x.invert) x0 = x(x0), x1 = x(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ extent[0][0] = x0 | 0, extent[1][0] = x1 | 0;
+ }
+ if (y) {
+ y0 = z[0], y1 = z[1];
+ if (x) y0 = y0[1], y1 = y1[1];
+ extentDomain[0][1] = y0, extentDomain[1][1] = y1;
+ if (y.invert) y0 = y(y0), y1 = y(y1);
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
+ extent[0][1] = y0 | 0, extent[1][1] = y1 | 0;
+ }
+ return brush;
+ };
+ brush.clear = function() {
+ extentDomain = null;
+ extent[0][0] = extent[0][1] = extent[1][0] = extent[1][1] = 0;
+ return brush;
+ };
+ brush.empty = function() {
+ return x && extent[0][0] === extent[1][0] || y && extent[0][1] === extent[1][1];
};
- points.forEach(root.add);
- return root;
+ return d3.rebind(brush, event, "on");
+ };
+ var d3_svg_brushCursor = {
+ n: "ns-resize",
+ e: "ew-resize",
+ s: "ns-resize",
+ w: "ew-resize",
+ nw: "nwse-resize",
+ ne: "nesw-resize",
+ se: "nwse-resize",
+ sw: "nesw-resize"
};
- function d3_geom_quadtreeNode() {
- return {
- leaf: true,
- nodes: [],
- point: null
- };
- }
- function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
- if (!f(node, x1, y1, x2, y2)) {
- var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
- if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
- if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
- if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
- if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
- }
- }
+ var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
d3.time = {};
var d3_time = Date, d3_time_daySymbols = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ];
function d3_time_utc() {
@@ -7243,6 +8022,115 @@ d3 = function() {
var d3_time_prototype = Date.prototype;
var d3_time_formatDateTime = "%a %b %e %X %Y", d3_time_formatDate = "%m/%d/%Y", d3_time_formatTime = "%H:%M:%S";
var d3_time_days = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], d3_time_dayAbbreviations = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], d3_time_months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], d3_time_monthAbbreviations = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
+ function d3_time_interval(local, step, number) {
+ function round(date) {
+ var d0 = local(date), d1 = offset(d0, 1);
+ return date - d0 < d1 - date ? d0 : d1;
+ }
+ function ceil(date) {
+ step(date = local(new d3_time(date - 1)), 1);
+ return date;
+ }
+ function offset(date, k) {
+ step(date = new d3_time(+date), k);
+ return date;
+ }
+ function range(t0, t1, dt) {
+ var time = ceil(t0), times = [];
+ if (dt > 1) {
+ while (time < t1) {
+ if (!(number(time) % dt)) times.push(new Date(+time));
+ step(time, 1);
+ }
+ } else {
+ while (time < t1) times.push(new Date(+time)), step(time, 1);
+ }
+ return times;
+ }
+ function range_utc(t0, t1, dt) {
+ try {
+ d3_time = d3_time_utc;
+ var utc = new d3_time_utc();
+ utc._ = t0;
+ return range(utc, t1, dt);
+ } finally {
+ d3_time = Date;
+ }
+ }
+ local.floor = local;
+ local.round = round;
+ local.ceil = ceil;
+ local.offset = offset;
+ local.range = range;
+ var utc = local.utc = d3_time_interval_utc(local);
+ utc.floor = utc;
+ utc.round = d3_time_interval_utc(round);
+ utc.ceil = d3_time_interval_utc(ceil);
+ utc.offset = d3_time_interval_utc(offset);
+ utc.range = range_utc;
+ return local;
+ }
+ function d3_time_interval_utc(method) {
+ return function(date, k) {
+ try {
+ d3_time = d3_time_utc;
+ var utc = new d3_time_utc();
+ utc._ = date;
+ return method(utc, k)._;
+ } finally {
+ d3_time = Date;
+ }
+ };
+ }
+ d3.time.year = d3_time_interval(function(date) {
+ date = d3.time.day(date);
+ date.setMonth(0, 1);
+ return date;
+ }, function(date, offset) {
+ date.setFullYear(date.getFullYear() + offset);
+ }, function(date) {
+ return date.getFullYear();
+ });
+ d3.time.years = d3.time.year.range;
+ d3.time.years.utc = d3.time.year.utc.range;
+ d3.time.day = d3_time_interval(function(date) {
+ var day = new d3_time(1970, 0);
+ day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+ return day;
+ }, function(date, offset) {
+ date.setDate(date.getDate() + offset);
+ }, function(date) {
+ return date.getDate() - 1;
+ });
+ d3.time.days = d3.time.day.range;
+ d3.time.days.utc = d3.time.day.utc.range;
+ d3.time.dayOfYear = function(date) {
+ var year = d3.time.year(date);
+ return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
+ };
+ d3_time_daySymbols.forEach(function(day, i) {
+ day = day.toLowerCase();
+ i = 7 - i;
+ var interval = d3.time[day] = d3_time_interval(function(date) {
+ (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
+ return date;
+ }, function(date, offset) {
+ date.setDate(date.getDate() + Math.floor(offset) * 7);
+ }, function(date) {
+ var day = d3.time.year(date).getDay();
+ return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
+ });
+ d3.time[day + "s"] = interval.range;
+ d3.time[day + "s"].utc = interval.utc.range;
+ d3.time[day + "OfYear"] = function(date) {
+ var day = d3.time.year(date).getDay();
+ return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7);
+ };
+ });
+ d3.time.week = d3.time.sunday;
+ d3.time.weeks = d3.time.sunday.range;
+ d3.time.weeks.utc = d3.time.sunday.utc.range;
+ d3.time.weekOfYear = d3.time.sundayOfYear;
d3.time.format = function(template) {
var n = template.length;
function format(date) {
@@ -7510,7 +8398,7 @@ d3 = function() {
return format;
};
var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
- d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
+ d3.time.format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
function d3_time_formatIsoNative(date) {
return date.toISOString();
}
@@ -7519,66 +8407,6 @@ d3 = function() {
return isNaN(date) ? null : date;
};
d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
- function d3_time_interval(local, step, number) {
- function round(date) {
- var d0 = local(date), d1 = offset(d0, 1);
- return date - d0 < d1 - date ? d0 : d1;
- }
- function ceil(date) {
- step(date = local(new d3_time(date - 1)), 1);
- return date;
- }
- function offset(date, k) {
- step(date = new d3_time(+date), k);
- return date;
- }
- function range(t0, t1, dt) {
- var time = ceil(t0), times = [];
- if (dt > 1) {
- while (time < t1) {
- if (!(number(time) % dt)) times.push(new Date(+time));
- step(time, 1);
- }
- } else {
- while (time < t1) times.push(new Date(+time)), step(time, 1);
- }
- return times;
- }
- function range_utc(t0, t1, dt) {
- try {
- d3_time = d3_time_utc;
- var utc = new d3_time_utc();
- utc._ = t0;
- return range(utc, t1, dt);
- } finally {
- d3_time = Date;
- }
- }
- local.floor = local;
- local.round = round;
- local.ceil = ceil;
- local.offset = offset;
- local.range = range;
- var utc = local.utc = d3_time_interval_utc(local);
- utc.floor = utc;
- utc.round = d3_time_interval_utc(round);
- utc.ceil = d3_time_interval_utc(ceil);
- utc.offset = d3_time_interval_utc(offset);
- utc.range = range_utc;
- return local;
- }
- function d3_time_interval_utc(method) {
- return function(date, k) {
- try {
- d3_time = d3_time_utc;
- var utc = new d3_time_utc();
- utc._ = date;
- return method(utc, k)._;
- } finally {
- d3_time = Date;
- }
- };
- }
d3.time.second = d3_time_interval(function(date) {
return new d3_time(Math.floor(date / 1e3) * 1e3);
}, function(date, offset) {
@@ -7607,44 +8435,6 @@ d3 = function() {
});
d3.time.hours = d3.time.hour.range;
d3.time.hours.utc = d3.time.hour.utc.range;
- d3.time.day = d3_time_interval(function(date) {
- var day = new d3_time(1970, 0);
- day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
- return day;
- }, function(date, offset) {
- date.setDate(date.getDate() + offset);
- }, function(date) {
- return date.getDate() - 1;
- });
- d3.time.days = d3.time.day.range;
- d3.time.days.utc = d3.time.day.utc.range;
- d3.time.dayOfYear = function(date) {
- var year = d3.time.year(date);
- return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
- };
- d3_time_daySymbols.forEach(function(day, i) {
- day = day.toLowerCase();
- i = 7 - i;
- var interval = d3.time[day] = d3_time_interval(function(date) {
- (date = d3.time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
- return date;
- }, function(date, offset) {
- date.setDate(date.getDate() + Math.floor(offset) * 7);
- }, function(date) {
- var day = d3.time.year(date).getDay();
- return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
- });
- d3.time[day + "s"] = interval.range;
- d3.time[day + "s"].utc = interval.utc.range;
- d3.time[day + "OfYear"] = function(date) {
- var day = d3.time.year(date).getDay();
- return Math.floor((d3.time.dayOfYear(date) + (day + i) % 7) / 7);
- };
- });
- d3.time.week = d3.time.sunday;
- d3.time.weeks = d3.time.sunday.range;
- d3.time.weeks.utc = d3.time.sunday.utc.range;
- d3.time.weekOfYear = d3.time.sundayOfYear;
d3.time.month = d3_time_interval(function(date) {
date = d3.time.day(date);
date.setDate(1);
@@ -7656,17 +8446,6 @@ d3 = function() {
});
d3.time.months = d3.time.month.range;
d3.time.months.utc = d3.time.month.utc.range;
- d3.time.year = d3_time_interval(function(date) {
- date = d3.time.day(date);
- date.setMonth(0, 1);
- return date;
- }, function(date, offset) {
- date.setFullYear(date.getFullYear() + offset);
- }, function(date) {
- return date.getFullYear();
- });
- d3.time.years = d3.time.year.range;
- d3.time.years.utc = d3.time.year.utc.range;
function d3_time_scale(linear, methods, format) {
function scale(x) {
return linear(x);
@@ -7685,7 +8464,7 @@ d3 = function() {
}));
};
scale.ticks = function(m, k) {
- var extent = d3_time_scaleExtent(scale.domain());
+ var extent = d3_scaleExtent(scale.domain());
if (typeof m !== "function") {
var span = extent[1] - extent[0], target = span / m, i = d3.bisect(d3_time_scaleSteps, target);
if (i == d3_time_scaleSteps.length) return methods.year(extent, m);
@@ -7703,11 +8482,7 @@ d3 = function() {
scale.copy = function() {
return d3_time_scale(linear.copy(), methods, format);
};
- return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
- }
- function d3_time_scaleExtent(domain) {
- var start = domain[0], stop = domain[domain.length - 1];
- return start < stop ? [ start, stop ] : [ stop, start ];
+ return d3_scale_linearRebind(scale, linear);
}
function d3_time_scaleDate(t) {
return new Date(t);
@@ -7786,5 +8561,25 @@ d3 = function() {
d3.time.scale.utc = function() {
return d3_time_scale(d3.scale.linear(), d3_time_scaleUTCMethods, d3_time_scaleUTCFormat);
};
+ d3.text = d3_xhrType(function(request) {
+ return request.responseText;
+ });
+ d3.json = function(url, callback) {
+ return d3_xhr(url, "application/json", d3_json, callback);
+ };
+ function d3_json(request) {
+ return JSON.parse(request.responseText);
+ }
+ d3.html = function(url, callback) {
+ return d3_xhr(url, "text/html", d3_html, callback);
+ };
+ function d3_html(request) {
+ var range = d3_document.createRange();
+ range.selectNode(d3_document.body);
+ return range.createContextualFragment(request.responseText);
+ }
+ d3.xml = d3_xhrType(function(request) {
+ return request.responseXML;
+ });
return d3;
}();
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
old mode 100644
new mode 100755
index 9b153cd..3ee7054
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/d3.v3.min.js
@@ -1,4 +1,5 @@
-d3=function(){function t(t){return t.target}function n(t){return t.source}function e(t,n){try{for(var e in n)Object.defineProperty(t.prototype,e,{value:n[e],enumerable:!1})}catch(r){t.prototype=n}}function r(t){for(var n=-1,e=t.length,r=[];e>++n;)r.push(t[n]);return r}function u(t){return Array.prototype.slice.call(t)}function i(){}function a(t){return t}function o(){return!0}function c(t){return"function"==typeof t?t:function(){return t}}function l(t,n,e){return function(){var r=e.apply(n,arguments);return arguments.length?t:r}}function f(t){return null!=t&&!isNaN(t)}function s(t){return t.length}function h(t){return t.trim().replace(/\s+/g," ")}function g(t){for(var n=1;t*n%1;)n*=10;return n}function p(t){return 1===t.length?function(n,e){t(null==n?e:null)}:t}function d(t){return t.responseText}function m(t){return JSON.parse(t.responseText)}function v(t){var n=Di.createRange();return n.selectNode(Di.body),n.createContextualFragment(t.responseText)}function y(t){return t.r
esponseXML}function M(){}function b(t){function n(){for(var n,r=e,u=-1,i=r.length;i>++u;)(n=r[u].on)&&n.apply(this,arguments);return t}var e=[],r=new i;return n.on=function(n,u){var i,a=r.get(n);return 2>arguments.length?a&&a.on:(a&&(a.on=null,e=e.slice(0,i=e.indexOf(a)).concat(e.slice(i+1)),r.remove(n)),u&&e.push(r.set(n,{on:u})),t)},n}function x(t,n){return n-(t?Math.ceil(Math.log(t)/Math.LN10):1)}function _(t){return t+""}function w(t,n){var e=Math.pow(10,3*Math.abs(8-n));return{scale:n>8?function(t){return t/e}:function(t){return t*e},symbol:t}}function S(t){return function(n){return 0>=n?0:n>=1?1:t(n)}}function k(t){return function(n){return 1-t(1-n)}}function E(t){return function(n){return.5*(.5>n?t(2*n):2-t(2-2*n))}}function A(t){return t*t}function N(t){return t*t*t}function T(t){if(0>=t)return 0;if(t>=1)return 1;var n=t*t,e=n*t;return 4*(.5>t?e:3*(t-n)+e-.75)}function q(t){return function(n){return Math.pow(n,t)}}function C(t){return 1-Math.cos(t*Ni/2)}function z(t)
{return Math.pow(2,10*(t-1))}function D(t){return 1-Math.sqrt(1-t*t)}function L(t,n){var e;return 2>arguments.length&&(n=.45),arguments.length?e=n/(2*Ni)*Math.asin(1/t):(t=1,e=n/4),function(r){return 1+t*Math.pow(2,10*-r)*Math.sin(2*(r-e)*Ni/n)}}function F(t){return t||(t=1.70158),function(n){return n*n*((t+1)*n-t)}}function H(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function j(){qi.event.stopPropagation(),qi.event.preventDefault()}function P(){for(var t,n=qi.event;t=n.sourceEvent;)n=t;return n}function R(t){for(var n=new M,e=0,r=arguments.length;r>++e;)n[arguments[e]]=b(n);return n.of=function(e,r){return function(u){try{var i=u.sourceEvent=qi.event;u.target=t,qi.event=u,n[u.type].apply(e,r)}finally{qi.event=i}}},n}function O(t){var n=[t.a,t.b],e=[t.c,t.d],r=U(n),u=Y(n,e),i=U(I(e,n,-u))||0;n[0]*e[1]<e[0]*n[1]&&(n[0]*=-1,n[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(n[1],n[0]
):Math.atan2(-e[0],e[1]))*zi,this.translate=[t.e,t.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*zi:0}function Y(t,n){return t[0]*n[0]+t[1]*n[1]}function U(t){var n=Math.sqrt(Y(t,t));return n&&(t[0]/=n,t[1]/=n),n}function I(t,n,e){return t[0]+=e*n[0],t[1]+=e*n[1],t}function V(t){return"transform"==t?qi.interpolateTransform:qi.interpolate}function X(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return(e-t)*n}}function Z(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return Math.max(0,Math.min(1,(e-t)*n))}}function B(){}function $(t,n,e){return new J(t,n,e)}function J(t,n,e){this.r=t,this.g=n,this.b=e}function G(t){return 16>t?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function K(t,n,e){var r,u,i,a=0,o=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(t))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return n(nn(u[0]),nn(u[1]),nn(u[2]))}return(i=aa.get(t))?n(i.r,i.g,i.b):(null!=t&&"#"===t.charAt(0)&&(4=
==t.length?(a=t.charAt(1),a+=a,o=t.charAt(2),o+=o,c=t.charAt(3),c+=c):7===t.length&&(a=t.substring(1,3),o=t.substring(3,5),c=t.substring(5,7)),a=parseInt(a,16),o=parseInt(o,16),c=parseInt(c,16)),n(a,o,c))}function W(t,n,e){var r,u,i=Math.min(t/=255,n/=255,e/=255),a=Math.max(t,n,e),o=a-i,c=(a+i)/2;return o?(u=.5>c?o/(a+i):o/(2-a-i),r=t==a?(n-e)/o+(e>n?6:0):n==a?(e-t)/o+2:(t-n)/o+4,r*=60):u=r=0,en(r,u,c)}function Q(t,n,e){t=tn(t),n=tn(n),e=tn(e);var r=pn((.4124564*t+.3575761*n+.1804375*e)/fa),u=pn((.2126729*t+.7151522*n+.072175*e)/sa),i=pn((.0193339*t+.119192*n+.9503041*e)/ha);return ln(116*u-16,500*(r-u),200*(u-i))}function tn(t){return.04045>=(t/=255)?t/12.92:Math.pow((t+.055)/1.055,2.4)}function nn(t){var n=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*n):n}function en(t,n,e){return new rn(t,n,e)}function rn(t,n,e){this.h=t,this.s=n,this.l=e}function un(t,n,e){function r(t){return t>360?t-=360:0>t&&(t+=360),60>t?i+(a-i)*t/60:180>t?a:240>t?i+(a-i)*(240-t)/60
:i}function u(t){return Math.round(255*r(t))}var i,a;return t%=360,0>t&&(t+=360),n=0>n?0:n>1?1:n,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+n):e+n-e*n,i=2*e-a,$(u(t+120),u(t),u(t-120))}function an(t,n,e){return new on(t,n,e)}function on(t,n,e){this.h=t,this.c=n,this.l=e}function cn(t,n,e){return ln(e,Math.cos(t*=Ci)*n,Math.sin(t)*n)}function ln(t,n,e){return new fn(t,n,e)}function fn(t,n,e){this.l=t,this.a=n,this.b=e}function sn(t,n,e){var r=(t+16)/116,u=r+n/500,i=r-e/200;return u=gn(u)*fa,r=gn(r)*sa,i=gn(i)*ha,$(dn(3.2404542*u-1.5371385*r-.4985314*i),dn(-.969266*u+1.8760108*r+.041556*i),dn(.0556434*u-.2040259*r+1.0572252*i))}function hn(t,n,e){return an(180*(Math.atan2(e,n)/Ni),Math.sqrt(n*n+e*e),t)}function gn(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function pn(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function dn(t){return Math.round(255*(.00304>=t?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function mn(t){return Ii(t,Ma),t}function vn(t){return function(){return pa(t,this)
}}function yn(t){return function(){return da(t,this)}}function Mn(t,n){function e(){this.removeAttribute(t)}function r(){this.removeAttributeNS(t.space,t.local)}function u(){this.setAttribute(t,n)}function i(){this.setAttributeNS(t.space,t.local,n)}function a(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}function o(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}return t=qi.ns.qualify(t),null==n?t.local?r:e:"function"==typeof n?t.local?o:a:t.local?i:u}function bn(t){return RegExp("(?:^|\\s+)"+qi.requote(t)+"(?:\\s+|$)","g")}function xn(t,n){function e(){for(var e=-1;u>++e;)t[e](this,n)}function r(){for(var e=-1,r=n.apply(this,arguments);u>++e;)t[e](this,r)}t=t.trim().split(/\s+/).map(_n);var u=t.length;return"function"==typeof n?r:e}function _n(t){var n=bn(t);return function(e,r){if(u=e.classList)return r?u.add(t):u.remove(t);var u=e.className,i=null!=u.baseVal,a=i
?u.baseVal:u;r?(n.lastIndex=0,n.test(a)||(a=h(a+" "+t),i?u.baseVal=a:e.className=a)):a&&(a=h(a.replace(n," ")),i?u.baseVal=a:e.className=a)}}function wn(t,n,e){function r(){this.style.removeProperty(t)}function u(){this.style.setProperty(t,n,e)}function i(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}return null==n?r:"function"==typeof n?i:u}function Sn(t,n){function e(){delete this[t]}function r(){this[t]=n}function u(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}return null==n?e:"function"==typeof n?u:r}function kn(t){return{__data__:t}}function En(t){return function(){return ya(this,t)}}function An(t){return arguments.length||(t=qi.ascending),function(n,e){return!n-!e||t(n.__data__,e.__data__)}}function Nn(t,n,e){function r(){var n=this[i];n&&(this.removeEventListener(t,n,n.$),delete this[i])}function u(){function u(t){var e=qi.event;qi.event=t,o[0]=a.__data__;try{n.apply(a,o)}finally{qi.event=e}}var
a=this,o=Yi(arguments);r.call(this),this.addEventListener(t,this[i]=u,u.$=e),u._=n}var i="__on"+t,a=t.indexOf(".");return a>0&&(t=t.substring(0,a)),n?u:r}function Tn(t,n){for(var e=0,r=t.length;r>e;e++)for(var u,i=t[e],a=0,o=i.length;o>a;a++)(u=i[a])&&n(u,a,e);return t}function qn(t){return Ii(t,xa),t}function Cn(t,n){return Ii(t,wa),t.id=n,t}function zn(t,n,e,r){var u=t.__transition__||(t.__transition__={active:0,count:0}),a=u[e];if(!a){var o=r.time;return a=u[e]={tween:new i,event:qi.dispatch("start","end"),time:o,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,qi.timer(function(r){function i(r){return u.active>e?l():(u.active=e,h.start.call(t,f,n),a.tween.forEach(function(e,r){(r=r.call(t,f,n))&&d.push(r)}),c(r)||qi.timer(c,0,o),1)}function c(r){if(u.active!==e)return l();for(var i=(r-g)/p,a=s(i),o=d.length;o>0;)d[--o].call(t,a);return i>=1?(l(),h.end.call(t,f,n),1):void 0}function l(){return--u.count?delete u[e]:delete t.__transition__,1}var f=t.__data__,s=a.eas
e,h=a.event,g=a.delay,p=a.duration,d=[];return r>=g?i(r):qi.timer(i,g,o),1},0,o),a}}function Dn(t){return null==t&&(t=""),function(){this.textContent=t}}function Ln(t,n,e,r){var u=t.id;return Tn(t,"function"==typeof e?function(t,i,a){t.__transition__[u].tween.set(n,r(e.call(t,t.__data__,i,a)))}:(e=r(e),function(t){t.__transition__[u].tween.set(n,e)}))}function Fn(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,t>=e.delay&&(e.flush=e.callback(t)),e=e.next;var r=Hn()-n;r>24?(isFinite(r)&&(clearTimeout(Aa),Aa=setTimeout(Fn,r)),Ea=0):(Ea=1,Ca(Fn))}function Hn(){for(var t=null,n=qa,e=1/0;n;)n.flush?(delete Ta[n.callback.id],n=t?t.next=n.next:qa=n.next):(e=Math.min(e,n.then+n.delay),n=(t=n).next);return e}function jn(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>za&&(Li.scrollX||Li.scrollY)){e=qi.select(Di.body).append("svg").style("position","absolute").style("top",0).style("left",0);var u=e[0][0].getScreenCTM();za=!(u.f||u.e),e.remove()}return za
?(r.x=n.pageX,r.y=n.pageY):(r.x=n.clientX,r.y=n.clientY),r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]}function Pn(){}function Rn(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function On(t){return t.rangeExtent?t.rangeExtent():Rn(t.range())}function Yn(t,n){var e,r=0,u=t.length-1,i=t[r],a=t[u];return i>a&&(e=r,r=u,u=e,e=i,i=a,a=e),(n=n(a-i))&&(t[r]=n.floor(i),t[u]=n.ceil(a)),t}function Un(){return Math}function In(t,n,e,r){function u(){var u=Math.min(t.length,n.length)>2?Gn:Jn,c=r?Z:X;return a=u(t,n,c,e),o=u(n,t,c,qi.interpolate),i}function i(t){return a(t)}var a,o;return i.invert=function(t){return o(t)},i.domain=function(n){return arguments.length?(t=n.map(Number),u()):t},i.range=function(t){return arguments.length?(n=t,u()):n},i.rangeRound=function(t){return i.range(t).interpolate(qi.interpolateRound)},i.clamp=function(t){return arguments.length?(r=t,u()):
r},i.interpolate=function(t){return arguments.length?(e=t,u()):e},i.ticks=function(n){return Bn(t,n)},i.tickFormat=function(n){return $n(t,n)},i.nice=function(){return Yn(t,Xn),u()},i.copy=function(){return In(t,n,e,r)},u()}function Vn(t,n){return qi.rebind(t,n,"range","rangeRound","interpolate","clamp")}function Xn(t){return t=Math.pow(10,Math.round(Math.log(t)/Math.LN10)-1),t&&{floor:function(n){return Math.floor(n/t)*t},ceil:function(n){return Math.ceil(n/t)*t}}}function Zn(t,n){var e=Rn(t),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/n)/Math.LN10)),i=n/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Bn(t,n){return qi.range.apply(qi,Zn(t,n))}function $n(t,n){return qi.format(",."+Math.max(0,-Math.floor(Math.log(Zn(t,n)[2])/Math.LN10+.01))+"f")}function Jn(t,n,e,r){var u=e(t[0],t[1]),i=r(n[0],n[1]);return function(t){return i(u(t))}}function Gn(t,n,e,r){var u=[],i=[],a=0,o=Math.min(t.length,n.le
ngth)-1;for(t[o]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());o>=++a;)u.push(e(t[a-1],t[a])),i.push(r(n[a-1],n[a]));return function(n){var e=qi.bisect(t,n,1,o)-1;return i[e](u[e](n))}}function Kn(t,n){function e(e){return t(n(e))}var r=n.pow;return e.invert=function(n){return r(t.invert(n))},e.domain=function(u){return arguments.length?(n=0>u[0]?Qn:Wn,r=n.pow,t.domain(u.map(n)),e):t.domain().map(r)},e.nice=function(){return t.domain(Yn(t.domain(),Un)),e},e.ticks=function(){var e=Rn(t.domain()),u=[];if(e.every(isFinite)){var i=Math.floor(e[0]),a=Math.ceil(e[1]),o=r(e[0]),c=r(e[1]);if(n===Qn)for(u.push(r(i));a>i++;)for(var l=9;l>0;l--)u.push(r(i)*l);else{for(;a>i;i++)for(var l=1;10>l;l++)u.push(r(i)*l);u.push(r(i))}for(i=0;o>u[i];i++);for(a=u.length;u[a-1]>c;a--);u=u.slice(i,a)}return u},e.tickFormat=function(t,u){if(2>arguments.length&&(u=Da),!arguments.length)return u;var i,a=Math.max(.1,t/e.ticks().length),o=n===Qn?(i=-1e-12,Math.floor):(i=1e-12,Math.ceil);return fun
ction(t){return a>=t/r(o(n(t)+i))?u(t):""}},e.copy=function(){return Kn(t.copy(),n)},Vn(e,t)}function Wn(t){return Math.log(0>t?0:t)/Math.LN10}function Qn(t){return-Math.log(t>0?0:-t)/Math.LN10}function te(t,n){function e(n){return t(r(n))}var r=ne(n),u=ne(1/n);return e.invert=function(n){return u(t.invert(n))},e.domain=function(n){return arguments.length?(t.domain(n.map(r)),e):t.domain().map(u)},e.ticks=function(t){return Bn(e.domain(),t)},e.tickFormat=function(t){return $n(e.domain(),t)},e.nice=function(){return e.domain(Yn(e.domain(),Xn))},e.exponent=function(t){if(!arguments.length)return n;var i=e.domain();return r=ne(n=t),u=ne(1/n),e.domain(i)},e.copy=function(){return te(t.copy(),n)},Vn(e,t)}function ne(t){return function(n){return 0>n?-Math.pow(-n,t):Math.pow(n,t)}}function ee(t,n){function e(n){return a[((u.get(n)||u.set(n,t.push(n)))-1)%a.length]}function r(n,e){return qi.range(t.length).map(function(t){return n+e*t})}var u,a,o;return e.domain=function(r){if(!argum
ents.length)return t;t=[],u=new i;for(var a,o=-1,c=r.length;c>++o;)u.has(a=r[o])||u.set(a,t.push(a));return e[n.t].apply(e,n.a)},e.range=function(t){return arguments.length?(a=t,o=0,n={t:"range",a:arguments},e):a},e.rangePoints=function(u,i){2>arguments.length&&(i=0);var c=u[0],l=u[1],f=(l-c)/(Math.max(1,t.length-1)+i);return a=r(2>t.length?(c+l)/2:c+f*i/2,f),o=0,n={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){2>arguments.length&&(i=0),3>arguments.length&&(c=i);var l=u[1]<u[0],f=u[l-0],s=u[1-l],h=(s-f)/(t.length-i+2*c);return a=r(f+h*c,h),l&&a.reverse(),o=h*(1-i),n={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){2>arguments.length&&(i=0),3>arguments.length&&(c=i);var l=u[1]<u[0],f=u[l-0],s=u[1-l],h=Math.floor((s-f)/(t.length-i+2*c)),g=s-f-(t.length-i)*h;return a=r(f+Math.round(g/2),h),l&&a.reverse(),o=Math.round(h*(1-i)),n={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Rn(n.a[0])},e.copy
=function(){return ee(t,n)},e.domain(t)}function re(t,n){function e(){var e=0,i=n.length;for(u=[];i>++e;)u[e-1]=qi.quantile(t,e/i);return r}function r(t){return isNaN(t=+t)?0/0:n[qi.bisect(u,t)]}var u;return r.domain=function(n){return arguments.length?(t=n.filter(function(t){return!isNaN(t)}).sort(qi.ascending),e()):t},r.range=function(t){return arguments.length?(n=t,e()):n},r.quantiles=function(){return u},r.copy=function(){return re(t,n)},e()}function ue(t,n,e){function r(n){return e[Math.max(0,Math.min(a,Math.floor(i*(n-t))))]}function u(){return i=e.length/(n-t),a=e.length-1,r}var i,a;return r.domain=function(e){return arguments.length?(t=+e[0],n=+e[e.length-1],u()):[t,n]},r.range=function(t){return arguments.length?(e=t,u()):e},r.copy=function(){return ue(t,n,e)},u()}function ie(t,n){function e(e){return n[qi.bisect(t,e)]}return e.domain=function(n){return arguments.length?(t=n,e):t},e.range=function(t){return arguments.length?(n=t,e):n},e.copy=function(){return ie(t,n
)},e}function ae(t){function n(t){return+t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=e.map(n),n):t},n.ticks=function(n){return Bn(t,n)},n.tickFormat=function(n){return $n(t,n)},n.copy=function(){return ae(t)},n}function oe(t){return t.innerRadius}function ce(t){return t.outerRadius}function le(t){return t.startAngle}function fe(t){return t.endAngle}function se(t){function n(n){function a(){f.push("M",i(t(s),l))}for(var o,f=[],s=[],h=-1,g=n.length,p=c(e),d=c(r);g>++h;)u.call(this,o=n[h],h)?s.push([+p.call(this,o,h),+d.call(this,o,h)]):s.length&&(a(),s=[]);return s.length&&a(),f.length?f.join(""):null}var e=he,r=ge,u=o,i=pe,a=i.key,l=.7;return n.x=function(t){return arguments.length?(e=t,n):e},n.y=function(t){return arguments.length?(r=t,n):r},n.defined=function(t){return arguments.length?(u=t,n):u},n.interpolate=function(t){return arguments.length?(a="function"==typeof t?i=t:(i=Oa.get(t)||pe).key,n):a},n.tension=function(t){return arguments.len
gth?(l=t,n):l},n}function he(t){return t[0]}function ge(t){return t[1]}function pe(t){return t.join("L")}function de(t){return pe(t)+"Z"}function me(t){for(var n=0,e=t.length,r=t[0],u=[r[0],",",r[1]];e>++n;)u.push("V",(r=t[n])[1],"H",r[0]);return u.join("")}function ve(t){for(var n=0,e=t.length,r=t[0],u=[r[0],",",r[1]];e>++n;)u.push("H",(r=t[n])[0],"V",r[1]);return u.join("")}function ye(t,n){return 4>t.length?pe(t):t[1]+xe(t.slice(1,t.length-1),_e(t,n))}function Me(t,n){return 3>t.length?pe(t):t[0]+xe((t.push(t[0]),t),_e([t[t.length-2]].concat(t,[t[1]]),n))}function be(t,n){return 3>t.length?pe(t):t[0]+xe(t,_e(t,n))}function xe(t,n){if(1>n.length||t.length!=n.length&&t.length!=n.length+2)return pe(t);var e=t.length!=n.length,r="",u=t[0],i=t[1],a=n[0],o=a,c=1;if(e&&(r+="Q"+(i[0]-2*a[0]/3)+","+(i[1]-2*a[1]/3)+","+i[0]+","+i[1],u=t[1],c=2),n.length>1){o=n[1],i=t[c],c++,r+="C"+(u[0]+a[0])+","+(u[1]+a[1])+","+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1];for(var l=2;n.length>l;l
++,c++)i=t[c],o=n[l],r+="S"+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1]}if(e){var f=t[c];r+="Q"+(i[0]+2*o[0]/3)+","+(i[1]+2*o[1]/3)+","+f[0]+","+f[1]}return r}function _e(t,n){for(var e,r=[],u=(1-n)/2,i=t[0],a=t[1],o=1,c=t.length;c>++o;)e=i,i=a,a=t[o],r.push([u*(a[0]-e[0]),u*(a[1]-e[1])]);return r}function we(t){if(3>t.length)return pe(t);var n=1,e=t.length,r=t[0],u=r[0],i=r[1],a=[u,u,u,(r=t[1])[0]],o=[i,i,i,r[1]],c=[u,",",i];for(Ne(c,a,o);e>++n;)r=t[n],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);for(n=-1;2>++n;)a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);return c.join("")}function Se(t){if(4>t.length)return pe(t);for(var n,e=[],r=-1,u=t.length,i=[0],a=[0];3>++r;)n=t[r],i.push(n[0]),a.push(n[1]);for(e.push(Ae(Ia,i)+","+Ae(Ia,a)),--r;u>++r;)n=t[r],i.shift(),i.push(n[0]),a.shift(),a.push(n[1]),Ne(e,i,a);return e.join("")}function ke(t){for(var n,e,r=-1,u=t.length,i=u+4,a=[],o=[];4>++r;)e=t[r%u],a.push(e[0]),o.push(e[1]);for(n=[Ae(Ia,a),",",Ae(Ia,o)],-
-r;i>++r;)e=t[r%u],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Ne(n,a,o);return n.join("")}function Ee(t,n){var e=t.length-1;if(e)for(var r,u,i=t[0][0],a=t[0][1],o=t[e][0]-i,c=t[e][1]-a,l=-1;e>=++l;)r=t[l],u=l/e,r[0]=n*r[0]+(1-n)*(i+u*o),r[1]=n*r[1]+(1-n)*(a+u*c);return we(t)}function Ae(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function Ne(t,n,e){t.push("C",Ae(Ya,n),",",Ae(Ya,e),",",Ae(Ua,n),",",Ae(Ua,e),",",Ae(Ia,n),",",Ae(Ia,e))}function Te(t,n){return(n[1]-t[1])/(n[0]-t[0])}function qe(t){for(var n=0,e=t.length-1,r=[],u=t[0],i=t[1],a=r[0]=Te(u,i);e>++n;)r[n]=(a+(a=Te(u=i,i=t[n+1])))/2;return r[n]=a,r}function Ce(t){for(var n,e,r,u,i=[],a=qe(t),o=-1,c=t.length-1;c>++o;)n=Te(t[o],t[o+1]),1e-6>Math.abs(n)?a[o]=a[o+1]=0:(e=a[o]/n,r=a[o+1]/n,u=e*e+r*r,u>9&&(u=3*n/Math.sqrt(u),a[o]=u*e,a[o+1]=u*r));for(o=-1;c>=++o;)u=(t[Math.min(c,o+1)][0]-t[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),i.push([u||0,a[o]*u||0]);return i}function ze(t){return 3>t.length?pe(t):t[0]+xe(t,Ce(
t))}function De(t){for(var n,e,r,u=-1,i=t.length;i>++u;)n=t[u],e=n[0],r=n[1]+Pa,n[0]=e*Math.cos(r),n[1]=e*Math.sin(r);return t}function Le(t){function n(n){function o(){m.push("M",l(t(y),g),h,s(t(v.reverse()),g),"Z")}for(var f,p,d,m=[],v=[],y=[],M=-1,b=n.length,x=c(e),_=c(u),w=e===r?function(){return p}:c(r),S=u===i?function(){return d}:c(i);b>++M;)a.call(this,f=n[M],M)?(v.push([p=+x.call(this,f,M),d=+_.call(this,f,M)]),y.push([+w.call(this,f,M),+S.call(this,f,M)])):v.length&&(o(),v=[],y=[]);return v.length&&o(),m.length?m.join(""):null}var e=he,r=he,u=0,i=ge,a=o,l=pe,f=l.key,s=l,h="L",g=.7;return n.x=function(t){return arguments.length?(e=r=t,n):r},n.x0=function(t){return arguments.length?(e=t,n):e},n.x1=function(t){return arguments.length?(r=t,n):r},n.y=function(t){return arguments.length?(u=i=t,n):i},n.y0=function(t){return arguments.length?(u=t,n):u},n.y1=function(t){return arguments.length?(i=t,n):i},n.defined=function(t){return arguments.length?(a=t,n):a},n.interpolate
=function(t){return arguments.length?(f="function"==typeof t?l=t:(l=Oa.get(t)||pe).key,s=l.reverse||l,h=l.closed?"M":"L",n):f},n.tension=function(t){return arguments.length?(g=t,n):g},n}function Fe(t){return t.radius}function He(t){return[t.x,t.y]}function je(t){return function(){var n=t.apply(this,arguments),e=n[0],r=n[1]+Pa;return[e*Math.cos(r),e*Math.sin(r)]}}function Pe(){return 64}function Re(){return"circle"}function Oe(t){var n=Math.sqrt(t/Ni);return"M0,"+n+"A"+n+","+n+" 0 1,1 0,"+-n+"A"+n+","+n+" 0 1,1 0,"+n+"Z"}function Ye(t,n){t.attr("transform",function(t){return"translate("+n(t)+",0)"})}function Ue(t,n){t.attr("transform",function(t){return"translate(0,"+n(t)+")"})}function Ie(t,n,e){if(r=[],e&&n.length>1){for(var r,u,i,a=Rn(t.domain()),o=-1,c=n.length,l=(n[1]-n[0])/++e;c>++o;)for(u=e;--u>0;)(i=+n[o]-u*l)>=a[0]&&r.push(i);for(--o,u=0;e>++u&&(i=+n[o]+u*l)<a[1];)r.push(i)}return r}function Ve(t){for(var n=t.source,e=t.target,r=Ze(n,e),u=[n];n!==r;)n=n.parent,u.push
(n);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Xe(t){for(var n=[],e=t.parent;null!=e;)n.push(t),t=e,e=e.parent;return n.push(t),n}function Ze(t,n){if(t===n)return t;for(var e=Xe(t),r=Xe(n),u=e.pop(),i=r.pop(),a=null;u===i;)a=u,u=e.pop(),i=r.pop();return a}function Be(t){t.fixed|=2}function $e(t){t.fixed&=-7}function Je(t){t.fixed|=4,t.px=t.x,t.py=t.y}function Ge(t){t.fixed&=-5}function Ke(t,n,e){var r=0,u=0;if(t.charge=0,!t.leaf)for(var i,a=t.nodes,o=a.length,c=-1;o>++c;)i=a[c],null!=i&&(Ke(i,n,e),t.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(t.point){t.leaf||(t.point.x+=Math.random()-.5,t.point.y+=Math.random()-.5);var l=n*e[t.point.index];t.charge+=t.pointCharge=l,r+=l*t.point.x,u+=l*t.point.y}t.cx=r/t.charge,t.cy=u/t.charge}function We(t){return t.x}function Qe(t){return t.y}function tr(t,n,e){t.y0=n,t.y=e}function nr(t){return qi.range(t.length)}function er(t){for(var n=-1,e=t[0].length,r=[];e>++n;)r[n]=0;return r}function rr(t){for
(var n,e=1,r=0,u=t[0][1],i=t.length;i>e;++e)(n=t[e][1])>u&&(r=e,u=n);return r}function ur(t){return t.reduce(ir,0)}function ir(t,n){return t+n[1]}function ar(t,n){return or(t,Math.ceil(Math.log(n.length)/Math.LN2+1))}function or(t,n){for(var e=-1,r=+t[0],u=(t[1]-r)/n,i=[];n>=++e;)i[e]=u*e+r;return i}function cr(t){return[qi.min(t),qi.max(t)]}function lr(t,n){return qi.rebind(t,n,"sort","children","value"),t.nodes=t,t.links=gr,t}function fr(t){return t.children}function sr(t){return t.value}function hr(t,n){return n.value-t.value}function gr(t){return qi.merge(t.map(function(t){return(t.children||[]).map(function(n){return{source:t,target:n}})}))}function pr(t,n){return t.value-n.value}function dr(t,n){var e=t._pack_next;t._pack_next=n,n._pack_prev=t,n._pack_next=e,e._pack_prev=n}function mr(t,n){t._pack_next=n,n._pack_prev=t}function vr(t,n){var e=n.x-t.x,r=n.y-t.y,u=t.r+n.r;return u*u-e*e-r*r>.001}function yr(t){function n(t){f=Math.min(t.x-t.r,f),s=Math.max(t.x+t.r,s),h=Ma
th.min(t.y-t.r,h),g=Math.max(t.y+t.r,g)}if((e=t.children)&&(l=e.length)){var e,r,u,i,a,o,c,l,f=1/0,s=-1/0,h=1/0,g=-1/0;if(e.forEach(Mr),r=e[0],r.x=-r.r,r.y=0,n(r),l>1&&(u=e[1],u.x=u.r,u.y=0,n(u),l>2))for(i=e[2],_r(r,u,i),n(i),dr(r,i),r._pack_prev=i,dr(i,u),u=r._pack_next,a=3;l>a;a++){_r(r,u,i=e[a]);var p=0,d=1,m=1;for(o=u._pack_next;o!==u;o=o._pack_next,d++)if(vr(o,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==o._pack_prev&&!vr(c,i);c=c._pack_prev,m++);p?(m>d||d==m&&u.r<r.r?mr(r,u=o):mr(r=c,u),a--):(dr(r,i),u=i,n(i))}var v=(f+s)/2,y=(h+g)/2,M=0;for(a=0;l>a;a++)i=e[a],i.x-=v,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));t.r=M,e.forEach(br)}}function Mr(t){t._pack_next=t._pack_prev=t}function br(t){delete t._pack_next,delete t._pack_prev}function xr(t,n,e,r){var u=t.children;if(t.x=n+=r*t.x,t.y=e+=r*t.y,t.r*=r,u)for(var i=-1,a=u.length;a>++i;)xr(u[i],n,e,r)}function _r(t,n,e){var r=t.r+e.r,u=n.x-t.x,i=n.y-t.y;if(r&&(u||i)){var a=n.r+e.r,o=u*u+i*i;a*=a,r*=r;var c=.5+(r-a)/
(2*o),l=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=t.x+c*u+l*i,e.y=t.y+c*i-l*u}else e.x=t.x+r,e.y=t.y}function wr(t){return 1+qi.max(t,function(t){return t.y})}function Sr(t){return t.reduce(function(t,n){return t+n.x},0)/t.length}function kr(t){var n=t.children;return n&&n.length?kr(n[0]):t}function Er(t){var n,e=t.children;return e&&(n=e.length)?Er(e[n-1]):t}function Ar(t,n){return t.parent==n.parent?1:2}function Nr(t){var n=t.children;return n&&n.length?n[0]:t._tree.thread}function Tr(t){var n,e=t.children;return e&&(n=e.length)?e[n-1]:t._tree.thread}function qr(t,n){var e=t.children;if(e&&(u=e.length))for(var r,u,i=-1;u>++i;)n(r=qr(e[i],n),t)>0&&(t=r);return t}function Cr(t,n){return t.x-n.x}function zr(t,n){return n.x-t.x}function Dr(t,n){return t.depth-n.depth}function Lr(t,n){function e(t,r){var u=t.children;if(u&&(a=u.length))for(var i,a,o=null,c=-1;a>++c;)i=u[c],e(i,o),o=i;n(t,r)}e(t,null)}function Fr(t){for(var n,e=0,r=0,u=t.children,i=u.length;--i>=0;
)n=u[i]._tree,n.prelim+=e,n.mod+=e,e+=n.shift+(r+=n.change)}function Hr(t,n,e){t=t._tree,n=n._tree;var r=e/(n.number-t.number);t.change+=r,n.change-=r,n.shift+=e,n.prelim+=e,n.mod+=e}function jr(t,n,e){return t._tree.ancestor.parent==n.parent?t._tree.ancestor:e}function Pr(t){return{x:t.x,y:t.y,dx:t.dx,dy:t.dy}}function Rr(t,n){var e=t.x+n[3],r=t.y+n[0],u=t.dx-n[1]-n[3],i=t.dy-n[0]-n[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Or(t,n){function e(t,e){return qi.xhr(t,n,e).response(r)}function r(t){return e.parse(t.responseText)}function u(n){return n.map(i).join(t)}function i(t){return a.test(t)?'"'+t.replace(/\"/g,'""')+'"':t}var a=RegExp('["'+t+"\n]"),o=t.charCodeAt(0);return e.parse=function(t){var n;return e.parseRows(t,function(t){return n?n(t):(n=Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}"),void 0)})},e.parseRows=function(t,n){function e(){if(f>=l)return a;if(u)return u=!1,i;var n=f;if(
34===t.charCodeAt(n)){for(var e=n;l>e++;)if(34===t.charCodeAt(e)){if(34!==t.charCodeAt(e+1))break;++e}f=e+2;var r=t.charCodeAt(e+1);return 13===r?(u=!0,10===t.charCodeAt(e+2)&&++f):10===r&&(u=!0),t.substring(n+1,e).replace(/""/g,'"')}for(;l>f;){var r=t.charCodeAt(f++),c=1;if(10===r)u=!0;else if(13===r)u=!0,10===t.charCodeAt(f)&&(++f,++c);else if(r!==o)continue;return t.substring(n,f-c)}return t.substring(n)}for(var r,u,i={},a={},c=[],l=t.length,f=0,s=0;(r=e())!==a;){for(var h=[];r!==i&&r!==a;)h.push(r),r=e();(!n||(h=n(h,s++)))&&c.push(h)}return c},e.format=function(t){return t.map(u).join("\n")},e}function Yr(t,n){ao.hasOwnProperty(t.type)&&ao[t.type](t,n)}function Ur(t,n,e){var r,u=-1,i=t.length-e;for(n.lineStart();i>++u;)r=t[u],n.point(r[0],r[1]);n.lineEnd()}function Ir(t,n){var e=-1,r=t.length;for(n.polygonStart();r>++e;)Ur(t[e],n,1);n.polygonEnd()}function Vr(t){return[Math.atan2(t[1],t[0]),Math.asin(Math.max(-1,Math.min(1,t[2])))]}function Xr(t,n){return Ti>Math.abs(t[0
]-n[0])&&Ti>Math.abs(t[1]-n[1])}function Zr(t){var n=t[0],e=t[1],r=Math.cos(e);return[r*Math.cos(n),r*Math.sin(n),Math.sin(e)]}function Br(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function $r(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Jr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function Gr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Kr(t){var n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Wr(t){function n(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){f=0/0,d.point=a,n.lineStart()}function a(r,i){var a=Zr([r,i]),o=t(r,i);e(f,s,l,h,g,p,f=o[0],s=o[1],l=r,h=a[0],g=a[1],p=a[2],u,n),n.point(f,s)}function o(){d.point=r,n.lineEnd()}function c(){var t,r,c,m,v,y,M;i(),d.point=function(n,e){a(t=n,r=e),c=f,m=s,v=h,y=g,M=p,d.point=a},d.lineEnd=function(){e(f,s,l,h,g,p,c,m,t,v,y,M,u,n),d.lineEnd=o,o()}}var l,f,s,h,g,p,d={point:r,lineStart:i,lineEnd:o,polygonStart:function(){n.polygonStart(),d.lineStart=c},polyg
onEnd:function(){n.polygonEnd(),d.lineStart=i}};return d}function e(n,u,i,a,o,c,l,f,s,h,g,p,d,m){var v=l-n,y=f-u,M=v*v+y*y;if(M>4*r&&d--){var b=a+h,x=o+g,_=c+p,w=Math.sqrt(b*b+x*x+_*_),S=Math.asin(_/=w),k=Ti>Math.abs(Math.abs(_)-1)?(i+s)/2:Math.atan2(x,b),E=t(k,S),A=E[0],N=E[1],T=A-n,q=N-u,C=y*T-v*q;(C*C/M>r||Math.abs((v*T+y*q)/M-.5)>.3)&&(e(n,u,i,a,o,c,A,N,k,b/=w,x/=w,_,d,m),m.point(A,N),e(A,N,k,b,x,_,l,f,s,h,g,p,d,m))}}var r=.5,u=16;return n.precision=function(t){return arguments.length?(u=(r=t*t)>0&&16,n):Math.sqrt(r)},n}function Qr(t,n){function e(t,n){var e=Math.sqrt(i-2*u*Math.sin(n))/u;return[e*Math.sin(t*=u),a-e*Math.cos(t)]}var r=Math.sin(t),u=(r+Math.sin(n))/2,i=1+r*(2*u-r),a=Math.sqrt(i)/u;return e.invert=function(t,n){var e=a-n;return[Math.atan2(t,e)/u,Math.asin((i-(t*t+e*e)*u*u)/(2*u))]},e}function tu(t){function n(t,n){r>t&&(r=t),t>i&&(i=t),u>n&&(u=n),n>a&&(a=n)}function e(){o.point=o.lineEnd=Pn}var r,u,i,a,o={point:n,lineStart:Pn,lineEnd:Pn,polygonStart:functi
on(){o.lineEnd=e},polygonEnd:function(){o.point=n}};return function(n){return a=i=-(r=u=1/0),qi.geo.stream(n,t(o)),[[r,u],[i,a]]}}function nu(t,n){if(!lo){++fo,t*=Ci;var e=Math.cos(n*=Ci);so+=(e*Math.cos(t)-so)/fo,ho+=(e*Math.sin(t)-ho)/fo,go+=(Math.sin(n)-go)/fo}}function eu(){var t,n;lo=1,ru(),lo=2;var e=po.point;po.point=function(r,u){e(t=r,n=u)},po.lineEnd=function(){po.point(t,n),uu(),po.lineEnd=uu}}function ru(){function t(t,u){t*=Ci;var i=Math.cos(u*=Ci),a=i*Math.cos(t),o=i*Math.sin(t),c=Math.sin(u),l=Math.atan2(Math.sqrt((l=e*c-r*o)*l+(l=r*a-n*c)*l+(l=n*o-e*a)*l),n*a+e*o+r*c);fo+=l,so+=l*(n+(n=a)),ho+=l*(e+(e=o)),go+=l*(r+(r=c))}var n,e,r;lo>1||(1>lo&&(lo=1,fo=so=ho=go=0),po.point=function(u,i){u*=Ci;var a=Math.cos(i*=Ci);n=a*Math.cos(u),e=a*Math.sin(u),r=Math.sin(i),po.point=t})}function uu(){po.point=nu}function iu(t,n){var e=Math.cos(t),r=Math.sin(t);return function(u,i,a,o){null!=u?(u=au(e,u),i=au(e,i),(a>0?i>u:u>i)&&(u+=2*a*Ni)):(u=t+2*a*Ni,i=t);for(var c,l=a*n,
f=u;a>0?f>i:i>f;f-=l)o.point((c=Vr([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function au(t,n){var e=Zr(n);e[0]-=t,Kr(e);var r=Math.acos(Math.max(-1,Math.min(1,-e[1])));return((0>-e[2]?-r:r)+2*Math.PI-Ti)%(2*Math.PI)}function ou(t,n,e){return function(r){function u(n,e){t(n,e)&&r.point(n,e)}function i(t,n){m.point(t,n)}function a(){v.point=i,m.lineStart()}function o(){v.point=u,m.lineEnd()}function c(t,n){M.point(t,n),d.push([t,n])}function l(){M.lineStart(),d=[]}function f(){c(d[0][0],d[0][1]),M.lineEnd();var t,n=M.clean(),e=y.buffer(),u=e.length;if(!u)return p=!0,g+=gu(d,-1),d=null,void 0;if(d=null,1&n){t=e[0],h+=gu(t,1);var i,u=t.length-1,a=-1;for(r.lineStart();u>++a;)r.point((i=t[a])[0],i[1]);return r.lineEnd(),void 0}u>1&&2&n&&e.push(e.pop().concat(e.shift())),s.push(e.filter(su))}var s,h,g,p,d,m=n(r),v={point:u,lineStart:a,lineEnd:o,polygonStart:function(){v.point=c,v.lineStart=l,v.lineEnd=f,p=!1,g=h=0,s=[],r.polygonStart()},polygonEnd:function(){v.point=u,v.lineSta
rt=a,v.lineEnd=o,s=qi.merge(s),s.length?cu(s,e,r):(-Ti>h||p&&-Ti>g)&&(r.lineStart(),e(null,null,1,r),r.lineEnd()),r.polygonEnd(),s=null},sphere:function(){r.polygonStart(),r.lineStart(),e(null,null,1,r),r.lineEnd(),r.polygonEnd()}},y=hu(),M=n(y);return v}}function cu(t,n,e){var r=[],u=[];if(t.forEach(function(t){var n=t.length;if(!(1>=n)){var e=t[0],i=t[n-1],a={point:e,points:t,other:null,visited:!1,entry:!0,subject:!0},o={point:e,points:[e],other:a,visited:!1,entry:!1,subject:!1};
-a.other=o,r.push(a),u.push(o),a={point:i,points:[i],other:null,visited:!1,entry:!1,subject:!0},o={point:i,points:[i],other:a,visited:!1,entry:!0,subject:!1},a.other=o,r.push(a),u.push(o)}}),u.sort(fu),lu(r),lu(u),r.length)for(var i,a,o,c=r[0];;){for(i=c;i.visited;)if((i=i.next)===c)return;a=i.points,e.lineStart();do{if(i.visited=i.other.visited=!0,i.entry){if(i.subject)for(var l=0;a.length>l;l++)e.point((o=a[l])[0],o[1]);else n(i.point,i.next.point,1,e);i=i.next}else{if(i.subject){a=i.prev.points;for(var l=a.length;--l>=0;)e.point((o=a[l])[0],o[1])}else n(i.point,i.prev.point,-1,e);i=i.prev}i=i.other,a=i.points}while(!i.visited);e.lineEnd()}}function lu(t){if(n=t.length){for(var n,e,r=0,u=t[0];n>++r;)u.next=e=t[r],e.prev=u,u=e;u.next=e=t[0],e.prev=u}}function fu(t,n){return(0>(t=t.point)[0]?t[1]-Ni/2-Ti:Ni/2-t[1])-(0>(n=n.point)[0]?n[1]-Ni/2-Ti:Ni/2-n[1])}function su(t){return t.length>1}function hu(){var t,n=[];return{lineStart:function(){n.push(t=[])},point:function(n,e){t
.push([n,e])},lineEnd:Pn,buffer:function(){var e=n;return n=[],t=null,e}}}function gu(t,n){if(!(e=t.length))return 0;for(var e,r,u,i=0,a=0,o=t[0],c=o[0],l=o[1],f=Math.cos(l),s=Math.atan2(n*Math.sin(c)*f,Math.sin(l)),h=1-n*Math.cos(c)*f,g=s;e>++i;)o=t[i],f=Math.cos(l=o[1]),r=Math.atan2(n*Math.sin(c=o[0])*f,Math.sin(l)),u=1-n*Math.cos(c)*f,Ti>Math.abs(h-2)&&Ti>Math.abs(u-2)||(Ti>Math.abs(u)||Ti>Math.abs(h)||(Ti>Math.abs(Math.abs(r-s)-Ni)?u+h>2&&(a+=4*(r-s)):a+=Ti>Math.abs(h-2)?4*(r-g):((3*Ni+r-s)%(2*Ni)-Ni)*(h+u)),g=s,s=r,h=u);return a}function pu(t){var n,e=0/0,r=0/0,u=0/0;return{lineStart:function(){t.lineStart(),n=1},point:function(i,a){var o=i>0?Ni:-Ni,c=Math.abs(i-e);Ti>Math.abs(c-Ni)?(t.point(e,r=(r+a)/2>0?Ni/2:-Ni/2),t.point(u,r),t.lineEnd(),t.lineStart(),t.point(o,r),t.point(i,r),n=0):u!==o&&c>=Ni&&(Ti>Math.abs(e-u)&&(e-=u*Ti),Ti>Math.abs(i-o)&&(i-=o*Ti),r=du(e,r,i,a),t.point(u,r),t.lineEnd(),t.lineStart(),t.point(o,r),n=0),t.point(e=i,r=a),u=o},lineEnd:function(){t.li
neEnd(),e=r=0/0},clean:function(){return 2-n}}}function du(t,n,e,r){var u,i,a=Math.sin(t-e);return Math.abs(a)>Ti?Math.atan((Math.sin(n)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(n))*Math.sin(t))/(u*i*a)):(n+r)/2}function mu(t,n,e,r){var u;if(null==t)u=e*Ni/2,r.point(-Ni,u),r.point(0,u),r.point(Ni,u),r.point(Ni,0),r.point(Ni,-u),r.point(0,-u),r.point(-Ni,-u),r.point(-Ni,0),r.point(-Ni,u);else if(Math.abs(t[0]-n[0])>Ti){var i=(t[0]<n[0]?1:-1)*Ni;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(n[0],n[1])}function vu(t){function n(t,n){return Math.cos(t)*Math.cos(n)>i}function e(t){var e,u,i,a;return{lineStart:function(){i=u=!1,a=1},point:function(o,c){var l,f=[o,c],s=n(o,c);!e&&(i=u=s)&&t.lineStart(),s!==u&&(l=r(e,f),(Xr(e,l)||Xr(f,l))&&(f[0]+=Ti,f[1]+=Ti,s=n(f[0],f[1]))),s!==u&&(a=0,(u=s)?(t.lineStart(),l=r(f,e),t.point(l[0],l[1])):(l=r(e,f),t.point(l[0],l[1]),t.lineEnd()),e=l),!s||e&&Xr(e,f)||t.point(f[0],f[1]),e=f},lineEnd:function(){u&&t.lineEnd(),e=
null},clean:function(){return a|(i&&u)<<1}}}function r(t,n){var e=Zr(t,0),r=Zr(n,0),u=[1,0,0],a=$r(e,r),o=Br(a,a),c=a[0],l=o-c*c;if(!l)return t;var f=i*o/l,s=-i*c/l,h=$r(u,a),g=Gr(u,f),p=Gr(a,s);Jr(g,p);var d=h,m=Br(g,d),v=Br(d,d),y=Math.sqrt(m*m-v*(Br(g,g)-1)),M=Gr(d,(-m-y)/v);return Jr(M,g),Vr(M)}var u=t*Ci,i=Math.cos(u),a=iu(u,6*Ci);return ou(n,e,a)}function yu(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e}function Mu(t,n){return[t,n]}function bu(t,n,e){var r=qi.range(t,n-Ti,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function xu(t,n,e){var r=qi.range(t,n-Ti,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function _u(t,n,e,r){function u(t){var n=Math.sin(t*=g)*p,e=Math.sin(g-t)*p,r=e*l+n*s,u=e*f+n*h,i=e*a+n*c;return[Math.atan2(u,r)/Ci,Math.atan2(i,Math.sqrt(r*r+u*u))/Ci]}var i=Math.cos(n),a=Math.sin(n),o=Math.cos(r),c
=Math.sin(r),l=i*Math.cos(t),f=i*Math.sin(t),s=o*Math.cos(e),h=o*Math.sin(e),g=Math.acos(Math.max(-1,Math.min(1,a*c+i*o*Math.cos(e-t)))),p=1/Math.sin(g);return u.distance=g,u}function wu(t,n){return[t/(2*Ni),Math.max(-.5,Math.min(.5,Math.log(Math.tan(Ni/4+n/2))/(2*Ni)))]}function Su(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function ku(t){var n=Wr(function(n,e){return t([n*zi,e*zi])});return function(t){return t=n(t),{point:function(n,e){t.point(n*Ci,e*Ci)},sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}}function Eu(){function t(t,n){a.push("M",t,",",n,i)}function n(t,n){a.push("M",t,",",n),o.point=e}function e(t,n){a.push("L",t,",",n)}function r(){o.point=t}function u(){a.push("Z")}var i=Su(4.5),a=[],o={point:t,lineStart:function(){o.point=n},lineEnd:r,polygonStart:function(){o.lineEnd=u},polygonEnd:function(
){o.lineEnd=r,o.point=t},pointRadius:function(t){return i=Su(t),o},result:function(){if(a.length){var t=a.join("");return a=[],t}}};return o}function Au(t){function n(n,e){t.moveTo(n,e),t.arc(n,e,a,0,2*Ni)}function e(n,e){t.moveTo(n,e),o.point=r}function r(n,e){t.lineTo(n,e)}function u(){o.point=n}function i(){t.closePath()}var a=4.5,o={point:n,lineStart:function(){o.point=e},lineEnd:u,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=u,o.point=n},pointRadius:function(t){return a=t,o},result:Pn};return o}function Nu(){function t(t,n){bo+=u*t-r*n,r=t,u=n}var n,e,r,u;xo.point=function(i,a){xo.point=t,n=r=i,e=u=a},xo.lineEnd=function(){t(n,e)}}function Tu(t,n){lo||(so+=t,ho+=n,++go)}function qu(){function t(t,r){var u=t-n,i=r-e,a=Math.sqrt(u*u+i*i);so+=a*(n+t)/2,ho+=a*(e+r)/2,go+=a,n=t,e=r}var n,e;if(1!==lo){if(!(1>lo))return;lo=1,so=ho=go=0}_o.point=function(r,u){_o.point=t,n=r,e=u}}function Cu(){_o.point=Tu}function zu(){function t(t,n){var e=u*t-r*n;so+=e*
(r+t),ho+=e*(u+n),go+=3*e,r=t,u=n}var n,e,r,u;2>lo&&(lo=2,so=ho=go=0),_o.point=function(i,a){_o.point=t,n=r=i,e=u=a},_o.lineEnd=function(){t(n,e)}}function Du(){function t(t,n){t*=Ci,n=n*Ci/2+Ni/4;var e=t-r,a=Math.cos(n),o=Math.sin(n),c=i*o,l=So,f=ko,s=u*a+c*Math.cos(e),h=c*Math.sin(e);So=l*s-f*h,ko=f*s+l*h,r=t,u=a,i=o}var n,e,r,u,i;Eo.point=function(a,o){Eo.point=t,r=(n=a)*Ci,u=Math.cos(o=(e=o)*Ci/2+Ni/4),i=Math.sin(o)},Eo.lineEnd=function(){t(n,e)}}function Lu(t){return Fu(function(){return t})()}function Fu(t){function n(t){return t=a(t[0]*Ci,t[1]*Ci),[t[0]*f+o,c-t[1]*f]}function e(t){return t=a.invert((t[0]-o)/f,(c-t[1])/f),t&&[t[0]*zi,t[1]*zi]}function r(){a=yu(i=ju(d,m,v),u);var t=u(g,p);return o=s-t[0]*f,c=h+t[1]*f,n}var u,i,a,o,c,l=Wr(function(t,n){return t=u(t,n),[t[0]*f+o,c-t[1]*f]}),f=150,s=480,h=250,g=0,p=0,d=0,m=0,v=0,y=mo,M=null;return n.stream=function(t){return Hu(i,y(l(t)))},n.clipAngle=function(t){return arguments.length?(y=null==t?(M=t,mo):vu(M=+t),n):M},n
.scale=function(t){return arguments.length?(f=+t,r()):f},n.translate=function(t){return arguments.length?(s=+t[0],h=+t[1],r()):[s,h]},n.center=function(t){return arguments.length?(g=t[0]%360*Ci,p=t[1]%360*Ci,r()):[g*zi,p*zi]},n.rotate=function(t){return arguments.length?(d=t[0]%360*Ci,m=t[1]%360*Ci,v=t.length>2?t[2]%360*Ci:0,r()):[d*zi,m*zi,v*zi]},qi.rebind(n,l,"precision"),function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,r()}}function Hu(t,n){return{point:function(e,r){r=t(e*Ci,r*Ci),e=r[0],n.point(e>Ni?e-2*Ni:-Ni>e?e+2*Ni:e,r[1])},sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ju(t,n,e){return t?n||e?yu(Ru(t),Ou(n,e)):Ru(t):n||e?Ou(n,e):Mu}function Pu(t){return function(n,e){return n+=t,[n>Ni?n-2*Ni:-Ni>n?n+2*Ni:n,e]}}function Ru(t){var n=Pu(t);return n.invert=Pu(-t),n}function Ou(t,n){function e(t,n){var e=Math.cos(n)
,o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),f=l*r+o*u;return[Math.atan2(c*i-f*a,o*r-l*u),Math.asin(Math.max(-1,Math.min(1,f*i+c*a)))]}var r=Math.cos(t),u=Math.sin(t),i=Math.cos(n),a=Math.sin(n);return e.invert=function(t,n){var e=Math.cos(n),o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),f=l*i-c*a;return[Math.atan2(c*i+l*a,o*r+f*u),Math.asin(Math.max(-1,Math.min(1,f*r-o*u)))]},e}function Yu(t,n){function e(n,e){var r=Math.cos(n),u=Math.cos(e),i=t(r*u);return[i*u*Math.sin(n),i*Math.sin(e)]}return e.invert=function(t,e){var r=Math.sqrt(t*t+e*e),u=n(r),i=Math.sin(u),a=Math.cos(u);return[Math.atan2(t*i,r*a),Math.asin(r&&e*i/r)]},e}function Uu(t,n,e,r){var u,i,a,o,c,l,f;return u=r[t],i=u[0],a=u[1],u=r[n],o=u[0],c=u[1],u=r[e],l=u[0],f=u[1],(f-a)*(o-i)-(c-a)*(l-i)>0}function Iu(t,n,e){return(e[0]-n[0])*(t[1]-n[1])<(e[1]-n[1])*(t[0]-n[0])}function Vu(t,n,e,r){var u=t[0],i=e[0],a=n[0]-u,o=r[0]-i,c=t[1],l=e[1],f=n[1]-c,s=r[1]-l,h=(o*(c-l)-s*(u-i))/(s*a-o*f);return[u+h*a,c+h*f]}funct
ion Xu(t,n){var e={list:t.map(function(t,n){return{index:n,x:t[0],y:t[1]}}).sort(function(t,n){return t.y<n.y?-1:t.y>n.y?1:t.x<n.x?-1:t.x>n.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,"l"),r.rightEnd=r.createHalfEdge(null,"l"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(t,n){return{edge:t,side:n,vertex:null,l:null,r:null}},insert:function(t,n){n.l=t,n.r=t.r,t.r.l=n,t.r=n},leftBound:function(t){var n=r.leftEnd;do n=n.r;while(n!=r.rightEnd&&u.rightOf(n,t));return n=n.l},del:function(t){t.l.r=t.r,t.r.l=t.l,t.edge=null},right:function(t){return t.r},left:function(t){return t.l},leftRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[t.side]},rightRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[No[t.side]]}},u={bisect:function(t,n){var e={region:{l:t,r:n},ep:{l:null,r:null}},r=n.x-t.x,u=n.y-t.y,i=r>0?r:-r,a=u>0?u:-u;ret
urn e.c=t.x*r+t.y*u+.5*(r*r+u*u),i>a?(e.a=1,e.b=u/r,e.c/=r):(e.b=1,e.a=r/u,e.c/=u),e},intersect:function(t,n){var e=t.edge,r=n.edge;if(!e||!r||e.region.r==r.region.r)return null;var u=e.a*r.b-e.b*r.a;if(1e-10>Math.abs(u))return null;var i,a,o=(e.c*r.b-r.c*e.b)/u,c=(r.c*e.a-e.c*r.a)/u,l=e.region.r,f=r.region.r;l.y<f.y||l.y==f.y&&l.x<f.x?(i=t,a=e):(i=n,a=r);var s=o>=a.region.r.x;return s&&"l"===i.side||!s&&"r"===i.side?null:{x:o,y:c}},rightOf:function(t,n){var e=t.edge,r=e.region.r,u=n.x>r.x;if(u&&"l"===t.side)return 1;if(!u&&"r"===t.side)return 0;if(1===e.a){var i=n.y-r.y,a=n.x-r.x,o=0,c=0;if(!u&&0>e.b||u&&e.b>=0?c=o=i>=e.b*a:(c=n.x+n.y*e.b>e.c,0>e.b&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-i*i)<l*i*(1+2*a/l+e.b*e.b),0>e.b&&(c=!c)}}else{var f=e.c-e.a*n.x,s=n.y-f,h=n.x-r.x,g=f-r.y;c=s*s>h*h+g*g}return"l"===t.side?c:!c},endPoint:function(t,e,r){t.ep[e]=r,t.ep[No[e]]&&n(t)},distance:function(t,n){var e=t.x-n.x,r=t.y-n.y;return Math.sqrt(e*e+r*r)}},i={list:[],inser
t:function(t,n,e){t.vertex=n,t.ystar=n.y+e;for(var r=0,u=i.list,a=u.length;a>r;r++){var o=u[r];if(!(t.ystar>o.ystar||t.ystar==o.ystar&&n.x>o.vertex.x))break}u.splice(r,0,t)},del:function(t){for(var n=0,e=i.list,r=e.length;r>n&&e[n]!=t;++n);e.splice(n,1)},empty:function(){return 0===i.list.length},nextEvent:function(t){for(var n=0,e=i.list,r=e.length;r>n;++n)if(e[n]==t)return e[n+1];return null},min:function(){var t=i.list[0];return{x:t.vertex.x,y:t.ystar}},extractMin:function(){return i.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,f,s,h,g,p,d,m,v,y,M=e.list.shift();;)if(i.empty()||(a=i.min()),M&&(i.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=u.bisect(h,M),s=r.createHalfEdge(v,"l"),r.insert(o,s),d=u.intersect(o,s),d&&(i.del(o),i.insert(o,d,u.distance(d,M))),o=s,s=r.createHalfEdge(v,"r"),r.insert(o,s),d=u.intersect(s,c),d&&i.insert(s,d,u.distance(d,M)),M=e.list.shift();else{if(i.empty())break;o=i.extractMin(),l
=r.left(o),c=r.right(o),f=r.right(c),h=r.leftRegion(o),g=r.rightRegion(c),m=o.vertex,u.endPoint(o.edge,o.side,m),u.endPoint(c.edge,c.side,m),r.del(o),i.del(c),r.del(c),y="l",h.y>g.y&&(p=h,h=g,g=p,y="r"),v=u.bisect(h,g),s=r.createHalfEdge(v,y),r.insert(l,s),u.endPoint(v,No[y],m),d=u.intersect(l,s),d&&(i.del(l),i.insert(l,d,u.distance(d,h))),d=u.intersect(s,f),d&&i.insert(s,d,u.distance(d,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))n(o.edge)}function Zu(){return{leaf:!0,nodes:[],point:null}}function Bu(t,n,e,r,u,i){if(!t(n,e,r,u,i)){var a=.5*(e+u),o=.5*(r+i),c=n.nodes;c[0]&&Bu(t,c[0],e,r,a,o),c[1]&&Bu(t,c[1],a,r,u,o),c[2]&&Bu(t,c[2],e,o,a,i),c[3]&&Bu(t,c[3],a,o,u,i)}}function $u(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ju(t,n,e,r){for(var u,i,a=0,o=n.length,c=e.length;o>a;){if(r>=c)return-1;if(u=n.charCodeAt(a++),37===u){if(i=Bo[n.charAt(a++)],!i||0>(r=i(t,e,r)))return-1}else if(u!=e.charCodeAt(r++))return-1}return
r}function Gu(t){return RegExp("^(?:"+t.map(qi.requote).join("|")+")","i")}function Ku(t){for(var n=new i,e=-1,r=t.length;r>++e;)n.set(t[e].toLowerCase(),e);return n}function Wu(t,n,e){t+="";var r=t.length;return e>r?Array(e-r+1).join(n)+t:t}function Qu(t,n,e){Oo.lastIndex=0;var r=Oo.exec(n.substring(e));return r?e+=r[0].length:-1}function ti(t,n,e){Ro.lastIndex=0;var r=Ro.exec(n.substring(e));return r?e+=r[0].length:-1}function ni(t,n,e){Io.lastIndex=0;var r=Io.exec(n.substring(e));return r?(t.m=Vo.get(r[0].toLowerCase()),e+=r[0].length):-1}function ei(t,n,e){Yo.lastIndex=0;var r=Yo.exec(n.substring(e));return r?(t.m=Uo.get(r[0].toLowerCase()),e+=r[0].length):-1}function ri(t,n,e){return Ju(t,""+Zo.c,n,e)}function ui(t,n,e){return Ju(t,""+Zo.x,n,e)}function ii(t,n,e){return Ju(t,""+Zo.X,n,e)}function ai(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+4));return r?(t.y=+r[0],e+=r[0].length):-1}function oi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(
t.y=ci(+r[0]),e+=r[0].length):-1}function ci(t){return t+(t>68?1900:2e3)}function li(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.m=r[0]-1,e+=r[0].length):-1}function fi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.d=+r[0],e+=r[0].length):-1}function si(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.H=+r[0],e+=r[0].length):-1}function hi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.M=+r[0],e+=r[0].length):-1}function gi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+2));return r?(t.S=+r[0],e+=r[0].length):-1}function pi(t,n,e){$o.lastIndex=0;var r=$o.exec(n.substring(e,e+3));return r?(t.L=+r[0],e+=r[0].length):-1}function di(t,n,e){var r=Jo.get(n.substring(e,e+=2).toLowerCase());return null==r?-1:(t.p=r,e)}function mi(t){var n=t.getTimezoneOffset(),e=n>0?"-":"+",r=~~(Math.abs(n)/60),u=Math.abs(n)%60;return e+Wu(r,"0",2)+Wu(u,"0",2)}function vi(t){return t.toISOString()}function yi(
t,n,e){function r(n){var e=t(n),r=i(e,1);return r-n>n-e?e:r}function u(e){return n(e=t(new To(e-1)),1),e}function i(t,e){return n(t=new To(+t),e),t}function a(t,r,i){var a=u(t),o=[];if(i>1)for(;r>a;)e(a)%i||o.push(new Date(+a)),n(a,1);else for(;r>a;)o.push(new Date(+a)),n(a,1);return o}function o(t,n,e){try{To=$u;var r=new $u;return r._=t,a(r,n,e)}finally{To=Date}}t.floor=t,t.round=r,t.ceil=u,t.offset=i,t.range=a;var c=t.utc=Mi(t);return c.floor=c,c.round=Mi(r),c.ceil=Mi(u),c.offset=Mi(i),c.range=o,t}function Mi(t){return function(n,e){try{To=$u;var r=new $u;return r._=n,t(r,e)._}finally{To=Date}}}function bi(t,n,e){function r(n){return t(n)}return r.invert=function(n){return _i(t.invert(n))},r.domain=function(n){return arguments.length?(t.domain(n),r):t.domain().map(_i)},r.nice=function(t){return r.domain(Yn(r.domain(),function(){return t}))},r.ticks=function(e,u){var i=xi(r.domain());if("function"!=typeof e){var a=i[1]-i[0],o=a/e,c=qi.bisect(Ko,o);if(c==Ko.length)return n.
year(i,e);if(!c)return t.ticks(e).map(_i);Math.log(o/Ko[c-1])<Math.log(Ko[c]/o)&&--c,e=n[c],u=e[1],e=e[0].range}return e(i[0],new Date(+i[1]+1),u)},r.tickFormat=function(){return e},r.copy=function(){return bi(t.copy(),n,e)},qi.rebind(r,t,"range","rangeRound","interpolate","clamp")}function xi(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function _i(t){return new Date(t)}function wi(t){return function(n){for(var e=t.length-1,r=t[e];!r[1](n);)r=t[--e];return r[0](n)}}function Si(t){var n=new Date(t,0,1);return n.setFullYear(t),n}function ki(t){var n=t.getFullYear(),e=Si(n),r=Si(n+1);return n+(t-e)/(r-e)}function Ei(t){var n=new Date(Date.UTC(t,0,1));return n.setUTCFullYear(t),n}function Ai(t){var n=t.getUTCFullYear(),e=Ei(n),r=Ei(n+1);return n+(t-e)/(r-e)}var Ni=Math.PI,Ti=1e-6,qi={version:"3.0.6"},Ci=Ni/180,zi=180/Ni,Di=document,Li=window,Fi=".",Hi=",",ji=[3,3];Date.now||(Date.now=function(){return+new Date});try{Di.createElement("div").style.setProperty("opacity",0,
"")}catch(Pi){var Ri=Li.CSSStyleDeclaration.prototype,Oi=Ri.setProperty;Ri.setProperty=function(t,n,e){Oi.call(this,t,n+"",e)}}var Yi=u;try{Yi(Di.documentElement.childNodes)[0].nodeType}catch(Ui){Yi=r}var Ii=[].__proto__?function(t,n){t.__proto__=n}:function(t,n){for(var e in n)t[e]=n[e]};qi.map=function(t){var n=new i;for(var e in t)n.set(e,t[e]);return n},e(i,{has:function(t){return Vi+t in this},get:function(t){return this[Vi+t]},set:function(t,n){return this[Vi+t]=n},remove:function(t){return t=Vi+t,t in this&&delete this[t]},keys:function(){var t=[];return this.forEach(function(n){t.push(n)}),t},values:function(){var t=[];return this.forEach(function(n,e){t.push(e)}),t},entries:function(){var t=[];return this.forEach(function(n,e){t.push({key:n,value:e})}),t},forEach:function(t){for(var n in this)n.charCodeAt(0)===Xi&&t.call(this,n.substring(1),this[n])}});var Vi="\0",Xi=Vi.charCodeAt(0);qi.functor=c,qi.rebind=function(t,n){for(var e,r=1,u=arguments.length;u>++r;)t[e=ar
guments[r]]=l(t,n,n[e]);return t},qi.ascending=function(t,n){return n>t?-1:t>n?1:t>=n?0:0/0},qi.descending=function(t,n){return t>n?-1:n>t?1:n>=t?0:0/0},qi.mean=function(t,n){var e,r=t.length,u=0,i=-1,a=0;if(1===arguments.length)for(;r>++i;)f(e=t[i])&&(u+=(e-u)/++a);else for(;r>++i;)f(e=n.call(t,t[i],i))&&(u+=(e-u)/++a);return a?u:void 0},qi.median=function(t,n){return arguments.length>1&&(t=t.map(n)),t=t.filter(f),t.length?qi.quantile(t.sort(qi.ascending),.5):void 0},qi.min=function(t,n){var e,r,u=-1,i=t.length;if(1===arguments.length){for(;i>++u&&(null==(e=t[u])||e!=e);)e=void 0;for(;i>++u;)null!=(r=t[u])&&e>r&&(e=r)}else{for(;i>++u&&(null==(e=n.call(t,t[u],u))||e!=e);)e=void 0;for(;i>++u;)null!=(r=n.call(t,t[u],u))&&e>r&&(e=r)}return e},qi.max=function(t,n){var e,r,u=-1,i=t.length;if(1===arguments.length){for(;i>++u&&(null==(e=t[u])||e!=e);)e=void 0;for(;i>++u;)null!=(r=t[u])&&r>e&&(e=r)}else{for(;i>++u&&(null==(e=n.call(t,t[u],u))||e!=e);)e=void 0;for(;i>++u;)null!=(r=n.
call(t,t[u],u))&&r>e&&(e=r)}return e},qi.extent=function(t,n){var e,r,u,i=-1,a=t.length;if(1===arguments.length){for(;a>++i&&(null==(e=u=t[i])||e!=e);)e=u=void 0;for(;a>++i;)null!=(r=t[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;a>++i&&(null==(e=u=n.call(t,t[i],i))||e!=e);)e=void 0;for(;a>++i;)null!=(r=n.call(t,t[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},qi.random={normal:function(t,n){var e=arguments.length;return 2>e&&(n=1),1>e&&(t=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return t+n*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var t=qi.random.normal.apply(qi,arguments);return function(){return Math.exp(t())}},irwinHall:function(t){return function(){for(var n=0,e=0;t>e;e++)n+=Math.random();return n/t}}},qi.sum=function(t,n){var e,r=0,u=t.length,i=-1;if(1===arguments.length)for(;u>++i;)isNaN(e=+t[i])||(r+=e);else for(;u>++i;)isNaN(e=+n.call(t,t[i],i))||(r+=e);return r},qi.quantile=function(t,n){var e=(t.length-1)*n+1,r
=Math.floor(e),u=+t[r-1],i=e-r;return i?u+i*(t[r]-u):u},qi.shuffle=function(t){for(var n,e,r=t.length;r;)e=0|Math.random()*r--,n=t[r],t[r]=t[e],t[e]=n;return t},qi.transpose=function(t){return qi.zip.apply(qi,t)},qi.zip=function(){if(!(r=arguments.length))return[];for(var t=-1,n=qi.min(arguments,s),e=Array(n);n>++t;)for(var r,u=-1,i=e[t]=Array(r);r>++u;)i[u]=arguments[u][t];return e},qi.bisector=function(t){return{left:function(n,e,r,u){for(3>arguments.length&&(r=0),4>arguments.length&&(u=n.length);u>r;){var i=r+u>>>1;e>t.call(n,n[i],i)?r=i+1:u=i}return r},right:function(n,e,r,u){for(3>arguments.length&&(r=0),4>arguments.length&&(u=n.length);u>r;){var i=r+u>>>1;t.call(n,n[i],i)>e?u=i:r=i+1}return r}}};var Zi=qi.bisector(function(t){return t});qi.bisectLeft=Zi.left,qi.bisect=qi.bisectRight=Zi.right,qi.nest=function(){function t(n,o){if(o>=a.length)return r?r.call(u,n):e?n.sort(e):n;for(var c,l,f,s=-1,h=n.length,g=a[o++],p=new i,d={};h>++s;)(f=p.get(c=g(l=n[s])))?f.push(l):p.s
et(c,[l]);return p.forEach(function(n,e){d[n]=t(e,o)}),d}function n(t,e){if(e>=a.length)return t;var r,u=[],i=o[e++];for(r in t)u.push({key:r,values:n(t[r],e)});return i&&u.sort(function(t,n){return i(t.key,n.key)}),u}var e,r,u={},a=[],o=[];return u.map=function(n){return t(n,0)},u.entries=function(e){return n(t(e,0),0)},u.key=function(t){return a.push(t),u},u.sortKeys=function(t){return o[a.length-1]=t,u},u.sortValues=function(t){return e=t,u},u.rollup=function(t){return r=t,u},u},qi.keys=function(t){var n=[];for(var e in t)n.push(e);return n},qi.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},qi.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},qi.permute=function(t,n){for(var e=[],r=-1,u=n.length;u>++r;)e[r]=t[n[r]];return e},qi.merge=function(t){return Array.prototype.concat.apply([],t)},qi.range=function(t,n,e){if(3>arguments.length&&(e=1,2>arguments.length&&(n=t,t=0)),1/0===(n-t)/e)throw Error("infinite range");var r,u=[
],i=g(Math.abs(e)),a=-1;if(t*=i,n*=i,e*=i,0>e)for(;(r=t+e*++a)>n;)u.push(r/i);else for(;n>(r=t+e*++a);)u.push(r/i);return u},qi.requote=function(t){return t.replace(Bi,"\\$&")};var Bi=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;qi.round=function(t,n){return n?Math.round(t*(n=Math.pow(10,n)))/n:Math.round(t)},qi.xhr=function(t,n,e){function r(){var t=l.status;!t&&l.responseText||t>=200&&300>t||304===t?i.load.call(u,c.call(u,l)):i.error.call(u,l)}var u={},i=qi.dispatch("progress","load","error"),o={},c=a,l=new(Li.XDomainRequest&&/^(http(s)?:)?\/\//.test(t)?XDomainRequest:XMLHttpRequest);return"onload"in l?l.onload=l.onerror=r:l.onreadystatechange=function(){l.readyState>3&&r()},l.onprogress=function(t){var n=qi.event;qi.event=t;try{i.progress.call(u,l)}finally{qi.event=n}},u.header=function(t,n){return t=(t+"").toLowerCase(),2>arguments.length?o[t]:(null==n?delete o[t]:o[t]=n+"",u)},u.mimeType=function(t){return arguments.length?(n=null==t?null:t+"",u):n},u.response=function(t){return c
=t,u},["get","post"].forEach(function(t){u[t]=function(){return u.send.apply(u,[t].concat(Yi(arguments)))}}),u.send=function(e,r,i){if(2===arguments.length&&"function"==typeof r&&(i=r,r=null),l.open(e,t,!0),null==n||"accept"in o||(o.accept=n+",*/*"),l.setRequestHeader)for(var a in o)l.setRequestHeader(a,o[a]);return null!=n&&l.overrideMimeType&&l.overrideMimeType(n),null!=i&&u.on("error",i).on("load",function(t){i(null,t)}),l.send(null==r?null:r),u},u.abort=function(){return l.abort(),u},qi.rebind(u,i,"on"),2===arguments.length&&"function"==typeof n&&(e=n,n=null),null==e?u:u.get(p(e))},qi.text=function(){return qi.xhr.apply(qi,arguments).response(d)},qi.json=function(t,n){return qi.xhr(t,"application/json",n).response(m)},qi.html=function(t,n){return qi.xhr(t,"text/html",n).response(v)},qi.xml=function(){return qi.xhr.apply(qi,arguments).response(y)};var $i={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http:/
/www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};qi.ns={prefix:$i,qualify:function(t){var n=t.indexOf(":"),e=t;return n>=0&&(e=t.substring(0,n),t=t.substring(n+1)),$i.hasOwnProperty(e)?{space:$i[e],local:t}:t}},qi.dispatch=function(){for(var t=new M,n=-1,e=arguments.length;e>++n;)t[arguments[n]]=b(t);return t},M.prototype.on=function(t,n){var e=t.indexOf("."),r="";return e>0&&(r=t.substring(e+1),t=t.substring(0,e)),2>arguments.length?this[t].on(r):this[t].on(r,n)},qi.format=function(t){var n=Ji.exec(t),e=n[1]||" ",r=n[2]||">",u=n[3]||"",i=n[4]||"",a=n[5],o=+n[6],c=n[7],l=n[8],f=n[9],s=1,h="",g=!1;switch(l&&(l=+l.substring(1)),(a||"0"===e&&"="===r)&&(a=e="0",r="=",c&&(o-=Math.floor((o-1)/4))),f){case"n":c=!0,f="g";break;case"%":s=100,h="%",f="f";break;case"p":s=100,h="%",f="r";break;case"b":case"o":case"x":case"X":i&&(i="0"+f.toLowerCase());case"c":case"d":g=!0,l=0;break;case"s":s=-1,f="r"}"#"===i&&(i=""),"r"!=f||l||(f="g"),f=Gi.get(f)||_;var p=a&&c;retu
rn function(t){if(g&&t%1)return"";var n=0>t||0===t&&0>1/t?(t=-t,"-"):u;if(0>s){var d=qi.formatPrefix(t,l);t=d.scale(t),h=d.symbol}else t*=s;t=f(t,l),!a&&c&&(t=Ki(t));var m=i.length+t.length+(p?0:n.length),v=o>m?Array(m=o-m+1).join(e):"";return p&&(t=Ki(v+t)),Fi&&t.replace(".",Fi),n+=i,("<"===r?n+t+v:">"===r?v+n+t:"^"===r?v.substring(0,m>>=1)+n+t+v.substring(m):n+(p?t:v+t))+h}};var Ji=/(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,Gi=qi.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,n){return t.toPrecision(n)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},r:function(t,n){return(t=qi.round(t,x(t,n))).toFixed(Math.max(0,Math.min(20,x(t*(1+1e-15),n))))}}),Ki=a;if(ji){var Wi=ji.length;Ki=function(t){for(var n=t.lastIndexOf("."),e=n>=0?"."+t.subs
tring(n+1):(n=t.length,""),r=[],u=0,i=ji[0];n>0&&i>0;)r.push(t.substring(n-=i,n+i)),i=ji[u=(u+1)%Wi];return r.reverse().join(Hi||"")+e}}var Qi=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(w);qi.formatPrefix=function(t,n){var e=0;return t&&(0>t&&(t*=-1),n&&(t=qi.round(t,x(t,n))),e=1+Math.floor(1e-12+Math.log(t)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Qi[8+e/3]};var ta=function(){return a},na=qi.map({linear:ta,poly:q,quad:function(){return A},cubic:function(){return N},sin:function(){return C},exp:function(){return z},circle:function(){return D},elastic:L,back:F,bounce:function(){return H}}),ea=qi.map({"in":a,out:k,"in-out":E,"out-in":function(t){return E(k(t))}});qi.ease=function(t){var n=t.indexOf("-"),e=n>=0?t.substring(0,n):t,r=n>=0?t.substring(n+1):"in";return e=na.get(e)||ta,r=ea.get(r)||a,S(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},qi.event=null,qi.transform=function(t){var n=Di.createElementN
S(qi.ns.prefix.svg,"g");return(qi.transform=function(t){n.setAttribute("transform",t);var e=n.transform.baseVal.consolidate();return new O(e?e.matrix:ra)})(t)},O.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var ra={a:1,b:0,c:0,d:1,e:0,f:0};qi.interpolate=function(t,n){for(var e,r=qi.interpolators.length;--r>=0&&!(e=qi.interpolators[r](t,n)););return e},qi.interpolateNumber=function(t,n){return n-=t,function(e){return t+n*e}},qi.interpolateRound=function(t,n){return n-=t,function(e){return Math.round(t+n*e)}},qi.interpolateString=function(t,n){var e,r,u,i,a,o=0,c=0,l=[],f=[];for(ua.lastIndex=0,r=0;e=ua.exec(n);++r)e.index&&l.push(n.substring(o,c=e.index)),f.push({i:l.length,x:e[0]}),l.push(null),o=ua.lastIndex;for(n.length>o&&l.push(n.substring(o)),r=0,i=f.length;(e=ua.exec(t))&&i>r;++r)if(a=f[r],a.x==e[0]){if(a.i)if(null==l[a.i+1])for(l[a.i-1]+=a.x,l.splice(a.i,1),u=r+1;i>u;++u)f[u].i--;e
lse for(l[a.i-1]+=a.x+l[a.i+1],l.splice(a.i,2),u=r+1;i>u;++u)f[u].i-=2;else if(null==l[a.i+1])l[a.i]=a.x;else for(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1),u=r+1;i>u;++u)f[u].i--;f.splice(r,1),i--,r--}else a.x=qi.interpolateNumber(parseFloat(e[0]),parseFloat(a.x));for(;i>r;)a=f.pop(),null==l[a.i+1]?l[a.i]=a.x:(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1)),i--;return 1===l.length?null==l[0]?f[0].x:function(){return n}:function(t){for(r=0;i>r;++r)l[(a=f[r]).i]=a.x(t);return l.join("")}},qi.interpolateTransform=function(t,n){var e,r=[],u=[],i=qi.transform(t),a=qi.transform(n),o=i.translate,c=a.translate,l=i.rotate,f=a.rotate,s=i.skew,h=a.skew,g=i.scale,p=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:qi.interpolateNumber(o[0],c[0])},{i:3,x:qi.interpolateNumber(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=f?(l-f>180?f+=360:f-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:qi.interpolateNumber(l,f)})):f&&r.pu
sh(r.pop()+"rotate("+f+")"),s!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:qi.interpolateNumber(s,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:qi.interpolateNumber(g[0],p[0])},{i:e-2,x:qi.interpolateNumber(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(t){for(var n,i=-1;e>++i;)r[(n=u[i]).i]=n.x(t);return r.join("")}},qi.interpolateRgb=function(t,n){t=qi.rgb(t),n=qi.rgb(n);var e=t.r,r=t.g,u=t.b,i=n.r-e,a=n.g-r,o=n.b-u;return function(t){return"#"+G(Math.round(e+i*t))+G(Math.round(r+a*t))+G(Math.round(u+o*t))}},qi.interpolateHsl=function(t,n){t=qi.hsl(t),n=qi.hsl(n);var e=t.h,r=t.s,u=t.l,i=n.h-e,a=n.s-r,o=n.l-u;return i>180?i-=360:-180>i&&(i+=360),function(t){return un(e+i*t,r+a*t,u+o*t)+""}},qi.interpolateLab=function(t,n){t=qi.lab(t),n=qi.lab(n);var e=t.l,r=t.a,u=t.b,i=n.l-e,a=n.a-r,o=n.b-u;return function(t){return sn(e+i*t,r+a*t,u+o*t)+""}},qi.interpol
ateHcl=function(t,n){t=qi.hcl(t),n=qi.hcl(n);var e=t.h,r=t.c,u=t.l,i=n.h-e,a=n.c-r,o=n.l-u;return i>180?i-=360:-180>i&&(i+=360),function(t){return cn(e+i*t,r+a*t,u+o*t)+""}},qi.interpolateArray=function(t,n){var e,r=[],u=[],i=t.length,a=n.length,o=Math.min(t.length,n.length);for(e=0;o>e;++e)r.push(qi.interpolate(t[e],n[e]));for(;i>e;++e)u[e]=t[e];for(;a>e;++e)u[e]=n[e];return function(t){for(e=0;o>e;++e)u[e]=r[e](t);return u}},qi.interpolateObject=function(t,n){var e,r={},u={};for(e in t)e in n?r[e]=V(e)(t[e],n[e]):u[e]=t[e];for(e in n)e in t||(u[e]=n[e]);return function(t){for(e in r)u[e]=r[e](t);return u}};var ua=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;qi.interpolators=[qi.interpolateObject,function(t,n){return n instanceof Array&&qi.interpolateArray(t,n)},function(t,n){return("string"==typeof t||"string"==typeof n)&&qi.interpolateString(t+"",n+"")},function(t,n){return("string"==typeof n?aa.has(n)||/^(#|rgb\(|hsl\()/.test(n):n instanceof B)&&qi.interpolateRgb(t,n)},
function(t,n){return!isNaN(t=+t)&&!isNaN(n=+n)&&qi.interpolateNumber(t,n)}],B.prototype.toString=function(){return this.rgb()+""},qi.rgb=function(t,n,e){return 1===arguments.length?t instanceof J?$(t.r,t.g,t.b):K(""+t,$,un):$(~~t,~~n,~~e)};var ia=J.prototype=new B;ia.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var n=this.r,e=this.g,r=this.b,u=30;return n||e||r?(n&&u>n&&(n=u),e&&u>e&&(e=u),r&&u>r&&(r=u),$(Math.min(255,Math.floor(n/t)),Math.min(255,Math.floor(e/t)),Math.min(255,Math.floor(r/t)))):$(u,u,u)},ia.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),$(Math.floor(t*this.r),Math.floor(t*this.g),Math.floor(t*this.b))},ia.hsl=function(){return W(this.r,this.g,this.b)},ia.toString=function(){return"#"+G(this.r)+G(this.g)+G(this.b)};var aa=qi.map({aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",
brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4
b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orch
id:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"});
-aa.forEach(function(t,n){aa.set(t,K(n,$,un))}),qi.hsl=function(t,n,e){return 1===arguments.length?t instanceof rn?en(t.h,t.s,t.l):K(""+t,W,en):en(+t,+n,+e)};var oa=rn.prototype=new B;oa.brighter=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,this.l/t)},oa.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,t*this.l)},oa.rgb=function(){return un(this.h,this.s,this.l)},qi.hcl=function(t,n,e){return 1===arguments.length?t instanceof on?an(t.h,t.c,t.l):t instanceof fn?hn(t.l,t.a,t.b):hn((t=Q((t=qi.rgb(t)).r,t.g,t.b)).l,t.a,t.b):an(+t,+n,+e)};var ca=on.prototype=new B;ca.brighter=function(t){return an(this.h,this.c,Math.min(100,this.l+la*(arguments.length?t:1)))},ca.darker=function(t){return an(this.h,this.c,Math.max(0,this.l-la*(arguments.length?t:1)))},ca.rgb=function(){return cn(this.h,this.c,this.l).rgb()},qi.lab=function(t,n,e){return 1===arguments.length?t instanceof fn?ln(t.l,t.a,t.b):t instanceof on?cn(t.l,t.c,t.h):Q((t=
qi.rgb(t)).r,t.g,t.b):ln(+t,+n,+e)};var la=18,fa=.95047,sa=1,ha=1.08883,ga=fn.prototype=new B;ga.brighter=function(t){return ln(Math.min(100,this.l+la*(arguments.length?t:1)),this.a,this.b)},ga.darker=function(t){return ln(Math.max(0,this.l-la*(arguments.length?t:1)),this.a,this.b)},ga.rgb=function(){return sn(this.l,this.a,this.b)};var pa=function(t,n){return n.querySelector(t)},da=function(t,n){return n.querySelectorAll(t)},ma=Di.documentElement,va=ma.matchesSelector||ma.webkitMatchesSelector||ma.mozMatchesSelector||ma.msMatchesSelector||ma.oMatchesSelector,ya=function(t,n){return va.call(t,n)};"function"==typeof Sizzle&&(pa=function(t,n){return Sizzle(t,n)[0]||null},da=function(t,n){return Sizzle.uniqueSort(Sizzle(t,n))},ya=Sizzle.matchesSelector);var Ma=[];qi.selection=function(){return ba},qi.selection.prototype=Ma,Ma.select=function(t){var n,e,r,u,i=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){i.push(n=[]),n.parentNode=(r=this[a]).parentNode;fo
r(var c=-1,l=r.length;l>++c;)(u=r[c])?(n.push(e=t.call(u,u.__data__,c)),e&&"__data__"in u&&(e.__data__=u.__data__)):n.push(null)}return mn(i)},Ma.selectAll=function(t){var n,e,r=[];"function"!=typeof t&&(t=yn(t));for(var u=-1,i=this.length;i>++u;)for(var a=this[u],o=-1,c=a.length;c>++o;)(e=a[o])&&(r.push(n=Yi(t.call(e,e.__data__,o))),n.parentNode=e);return mn(r)},Ma.attr=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node();return t=qi.ns.qualify(t),t.local?e.getAttributeNS(t.space,t.local):e.getAttribute(t)}for(n in t)this.each(Mn(n,t[n]));return this}return this.each(Mn(t,n))},Ma.classed=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node(),r=(t=t.trim().split(/^|\s+/g)).length,u=-1;if(n=e.classList){for(;r>++u;)if(!n.contains(t[u]))return!1}else for(n=e.className,null!=n.baseVal&&(n=n.baseVal);r>++u;)if(!bn(t[u]).test(n))return!1;return!0}for(n in t)this.each(xn(n,t[n]));return this}return this.each(xn(t,n))},Ma.style=functi
on(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n="");for(e in t)this.each(wn(e,t[e],n));return this}if(2>r)return Li.getComputedStyle(this.node(),null).getPropertyValue(t);e=""}return this.each(wn(t,n,e))},Ma.property=function(t,n){if(2>arguments.length){if("string"==typeof t)return this.node()[t];for(n in t)this.each(Sn(n,t[n]));return this}return this.each(Sn(t,n))},Ma.text=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}:null==t?function(){this.textContent=""}:function(){this.textContent=t}):this.node().textContent},Ma.html=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}:null==t?function(){this.innerHTML=""}:function(){this.innerHTML=t}):this.node().innerHTML},Ma.append=function(t){function n(){return this.appendChild(Di.createElementNS(this.namespaceURI,t))}function e(){re
turn this.appendChild(Di.createElementNS(t.space,t.local))}return t=qi.ns.qualify(t),this.select(t.local?e:n)},Ma.insert=function(t,n){function e(){return this.insertBefore(Di.createElementNS(this.namespaceURI,t),pa(n,this))}function r(){return this.insertBefore(Di.createElementNS(t.space,t.local),pa(n,this))}return t=qi.ns.qualify(t),this.select(t.local?r:e)},Ma.remove=function(){return this.each(function(){var t=this.parentNode;t&&t.removeChild(this)})},Ma.data=function(t,n){function e(t,e){var r,u,a,o=t.length,s=e.length,h=Math.min(o,s),g=Array(s),p=Array(s),d=Array(o);if(n){var m,v=new i,y=new i,M=[];for(r=-1;o>++r;)m=n.call(u=t[r],u.__data__,r),v.has(m)?d[r]=u:v.set(m,u),M.push(m);for(r=-1;s>++r;)m=n.call(e,a=e[r],r),(u=v.get(m))?(g[r]=u,u.__data__=a):y.has(m)||(p[r]=kn(a)),y.set(m,a),v.remove(m);for(r=-1;o>++r;)v.has(M[r])&&(d[r]=t[r])}else{for(r=-1;h>++r;)u=t[r],a=e[r],u?(u.__data__=a,g[r]=u):p[r]=kn(a);for(;s>r;++r)p[r]=kn(e[r]);for(;o>r;++r)d[r]=t[r]}p.update=g,p.pa
rentNode=g.parentNode=d.parentNode=t.parentNode,c.push(p),l.push(g),f.push(d)}var r,u,a=-1,o=this.length;if(!arguments.length){for(t=Array(o=(r=this[0]).length);o>++a;)(u=r[a])&&(t[a]=u.__data__);return t}var c=qn([]),l=mn([]),f=mn([]);if("function"==typeof t)for(;o>++a;)e(r=this[a],t.call(r,r.parentNode.__data__,a));else for(;o>++a;)e(r=this[a],t);return l.enter=function(){return c},l.exit=function(){return f},l},Ma.datum=function(t){return arguments.length?this.property("__data__",t):this.property("__data__")},Ma.filter=function(t){var n,e,r,u=[];"function"!=typeof t&&(t=En(t));for(var i=0,a=this.length;a>i;i++){u.push(n=[]),n.parentNode=(e=this[i]).parentNode;for(var o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return mn(u)},Ma.order=function(){for(var t=-1,n=this.length;n>++t;)for(var e,r=this[t],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Ma.sort=function(t){t=An.apply(this,arguments
);for(var n=-1,e=this.length;e>++n;)this[n].sort(t);return this.order()},Ma.on=function(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n=!1);for(e in t)this.each(Nn(e,t[e],n));return this}if(2>r)return(r=this.node()["__on"+t])&&r._;e=!1}return this.each(Nn(t,n,e))},Ma.each=function(t){return Tn(this,function(n,e,r){t.call(n,n.__data__,e,r)})},Ma.call=function(t){var n=Yi(arguments);return t.apply(n[0]=this,n),this},Ma.empty=function(){return!this.node()},Ma.node=function(){for(var t=0,n=this.length;n>t;t++)for(var e=this[t],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Ma.transition=function(){var t,n,e=_a||++Sa,r=[],u=Object.create(ka);u.time=Date.now();for(var i=-1,a=this.length;a>++i;){r.push(t=[]);for(var o=this[i],c=-1,l=o.length;l>++c;)(n=o[c])&&zn(n,c,e,u),t.push(n)}return Cn(r,e)};var ba=mn([[Di]]);ba[0].parentNode=ma,qi.select=function(t){return"string"==typeof t?ba.select(t):mn([[t]])},qi.selectAll=function(t){return"string"==typ
eof t?ba.selectAll(t):mn([Yi(t)])};var xa=[];qi.selection.enter=qn,qi.selection.enter.prototype=xa,xa.append=Ma.append,xa.insert=Ma.insert,xa.empty=Ma.empty,xa.node=Ma.node,xa.select=function(t){for(var n,e,r,u,i,a=[],o=-1,c=this.length;c>++o;){r=(u=this[o]).update,a.push(n=[]),n.parentNode=u.parentNode;for(var l=-1,f=u.length;f>++l;)(i=u[l])?(n.push(r[l]=e=t.call(u.parentNode,i.__data__,l)),e.__data__=i.__data__):n.push(null)}return mn(a)};var _a,wa=[],Sa=0,ka={ease:T,delay:0,duration:250};wa.call=Ma.call,wa.empty=Ma.empty,wa.node=Ma.node,qi.transition=function(t){return arguments.length?_a?t.transition():t:ba.transition()},qi.transition.prototype=wa,wa.select=function(t){var n,e,r,u=this.id,i=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){i.push(n=[]);for(var c=this[a],l=-1,f=c.length;f>++l;)(r=c[l])&&(e=t.call(r,r.__data__,l))?("__data__"in r&&(e.__data__=r.__data__),zn(e,l,u,r.__transition__[u]),n.push(e)):n.push(null)}return Cn(i,u)},wa.selectAll=
function(t){var n,e,r,u,i,a=this.id,o=[];"function"!=typeof t&&(t=yn(t));for(var c=-1,l=this.length;l>++c;)for(var f=this[c],s=-1,h=f.length;h>++s;)if(r=f[s]){i=r.__transition__[a],e=t.call(r,r.__data__,s),o.push(n=[]);for(var g=-1,p=e.length;p>++g;)zn(u=e[g],g,a,i),n.push(u)}return Cn(o,a)},wa.filter=function(t){var n,e,r,u=[];"function"!=typeof t&&(t=En(t));for(var i=0,a=this.length;a>i;i++){u.push(n=[]);for(var e=this[i],o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return Cn(u,this.id,this.time).ease(this.ease())},wa.attr=function(t,n){function e(){this.removeAttribute(i)}function r(){this.removeAttributeNS(i.space,i.local)}if(2>arguments.length){for(n in t)this.attr(n,t[n]);return this}var u=V(t),i=qi.ns.qualify(t);return Ln(this,"attr."+t,n,function(t){function n(){var n,e=this.getAttribute(i);return e!==t&&(n=u(e,t),function(t){this.setAttribute(i,n(t))})}function a(){var n,e=this.getAttributeNS(i.space,i.local);return e!==t&&(n=u(e,t),function(t)
{this.setAttributeNS(i.space,i.local,n(t))})}return null==t?i.local?r:e:(t+="",i.local?a:n)})},wa.attrTween=function(t,n){function e(t,e){var r=n.call(this,t,e,this.getAttribute(u));return r&&function(t){this.setAttribute(u,r(t))}}function r(t,e){var r=n.call(this,t,e,this.getAttributeNS(u.space,u.local));return r&&function(t){this.setAttributeNS(u.space,u.local,r(t))}}var u=qi.ns.qualify(t);return this.tween("attr."+t,u.local?r:e)},wa.style=function(t,n,e){function r(){this.style.removeProperty(t)}var u=arguments.length;if(3>u){if("string"!=typeof t){2>u&&(n="");for(e in t)this.style(e,t[e],n);return this}e=""}var i=V(t);return Ln(this,"style."+t,n,function(n){function u(){var r,u=Li.getComputedStyle(this,null).getPropertyValue(t);return u!==n&&(r=i(u,n),function(n){this.style.setProperty(t,r(n),e)})}return null==n?r:(n+="",u)})},wa.styleTween=function(t,n,e){return 3>arguments.length&&(e=""),this.tween("style."+t,function(r,u){var i=n.call(this,r,u,Li.getComputedStyle(this
,null).getPropertyValue(t));return i&&function(n){this.style.setProperty(t,i(n),e)}})},wa.text=function(t){return Ln(this,"text",t,Dn)},wa.remove=function(){return this.each("end.transition",function(){var t;!this.__transition__&&(t=this.parentNode)&&t.removeChild(this)})},wa.ease=function(t){var n=this.id;return 1>arguments.length?this.node().__transition__[n].ease:("function"!=typeof t&&(t=qi.ease.apply(qi,arguments)),Tn(this,function(e){e.__transition__[n].ease=t}))},wa.delay=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,u){e.__transition__[n].delay=0|t.call(e,e.__data__,r,u)}:(t|=0,function(e){e.__transition__[n].delay=t}))},wa.duration=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,u){e.__transition__[n].duration=Math.max(1,0|t.call(e,e.__data__,r,u))}:(t=Math.max(1,0|t),function(e){e.__transition__[n].duration=t}))},wa.each=function(t,n){var e=this.id;if(2>arguments.length){var r=ka,u=_a;_a=e,Tn(this,function(n,r
,u){ka=n.__transition__[e],t.call(n,n.__data__,r,u)}),ka=r,_a=u}else Tn(this,function(r){r.__transition__[e].event.on(t,n)});return this},wa.transition=function(){for(var t,n,e,r,u=this.id,i=++Sa,a=[],o=0,c=this.length;c>o;o++){a.push(t=[]);for(var n=this[o],l=0,f=n.length;f>l;l++)(e=n[l])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,zn(e,l,i,r)),t.push(e)}return Cn(a,i)},wa.tween=function(t,n){var e=this.id;return 2>arguments.length?this.node().__transition__[e].tween.get(t):Tn(this,null==n?function(n){n.__transition__[e].tween.remove(t)}:function(r){r.__transition__[e].tween.set(t,n)})};var Ea,Aa,Na=0,Ta={},qa=null;qi.timer=function(t,n,e){if(3>arguments.length){if(2>arguments.length)n=0;else if(!isFinite(n))return;e=Date.now()}var r=Ta[t.id];r&&r.callback===t?(r.then=e,r.delay=n):Ta[t.id=++Na]=qa={callback:t,then:e,delay:n,next:qa},Ea||(Aa=clearTimeout(Aa),Ea=1,Ca(Fn))},qi.timer.flush=function(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,e.delay||(e.flush=e.c
allback(t)),e=e.next;Hn()};var Ca=Li.requestAnimationFrame||Li.webkitRequestAnimationFrame||Li.mozRequestAnimationFrame||Li.oRequestAnimationFrame||Li.msRequestAnimationFrame||function(t){setTimeout(t,17)};qi.mouse=function(t){return jn(t,P())};var za=/WebKit/.test(Li.navigator.userAgent)?-1:0;qi.touches=function(t,n){return 2>arguments.length&&(n=P().touches),n?Yi(n).map(function(n){var e=jn(t,n);return e.identifier=n.identifier,e}):[]},qi.scale={},qi.scale.linear=function(){return In([0,1],[0,1],qi.interpolate,!1)},qi.scale.log=function(){return Kn(qi.scale.linear(),Wn)};var Da=qi.format(".0e");Wn.pow=function(t){return Math.pow(10,t)},Qn.pow=function(t){return-Math.pow(10,-t)},qi.scale.pow=function(){return te(qi.scale.linear(),1)},qi.scale.sqrt=function(){return qi.scale.pow().exponent(.5)},qi.scale.ordinal=function(){return ee([],{t:"range",a:[[]]})},qi.scale.category10=function(){return qi.scale.ordinal().range(La)},qi.scale.category20=function(){return qi.scale.ordina
l().range(Fa)},qi.scale.category20b=function(){return qi.scale.ordinal().range(Ha)},qi.scale.category20c=function(){return qi.scale.ordinal().range(ja)};var La=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],Fa=["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],Ha=["#393b79","#5254a3","#6b6ecf","#9c9ede","#637939","#8ca252","#b5cf6b","#cedb9c","#8c6d31","#bd9e39","#e7ba52","#e7cb94","#843c39","#ad494a","#d6616b","#e7969c","#7b4173","#a55194","#ce6dbd","#de9ed6"],ja=["#3182bd","#6baed6","#9ecae1","#c6dbef","#e6550d","#fd8d3c","#fdae6b","#fdd0a2","#31a354","#74c476","#a1d99b","#c7e9c0","#756bb1","#9e9ac8","#bcbddc","#dadaeb","#636363","#969696","#bdbdbd","#d9d9d9"];qi.scale.quantile=function(){return re([],[])},qi.scale.quantize=function(){return ue(0,1,[0,1])},qi.scale.thres
hold=function(){return ie([.5],[0,1])},qi.scale.identity=function(){return ae([0,1])},qi.svg={},qi.svg.arc=function(){function t(){var t=n.apply(this,arguments),i=e.apply(this,arguments),a=r.apply(this,arguments)+Pa,o=u.apply(this,arguments)+Pa,c=(a>o&&(c=a,a=o,o=c),o-a),l=Ni>c?"0":"1",f=Math.cos(a),s=Math.sin(a),h=Math.cos(o),g=Math.sin(o);return c>=Ra?t?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+t+"A"+t+","+t+" 0 1,0 0,"+-t+"A"+t+","+t+" 0 1,0 0,"+t+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":t?"M"+i*f+","+i*s+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L"+t*h+","+t*g+"A"+t+","+t+" 0 "+l+",0 "+t*f+","+t*s+"Z":"M"+i*f+","+i*s+"A"+i+","+i+" 0 "+l+",1 "+i*h+","+i*g+"L0,0"+"Z"}var n=oe,e=ce,r=le,u=fe;return t.innerRadius=function(e){return arguments.length?(n=c(e),t):n},t.outerRadius=function(n){return arguments.length?(e=c(n),t):e},t.startAngle=function(n){return arguments.length?(r=c(n),t):r},t.endAngle=function(n){return arguments
.length?(u=c(n),t):u},t.centroid=function(){var t=(n.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+Pa;return[Math.cos(i)*t,Math.sin(i)*t]},t};var Pa=-Ni/2,Ra=2*Ni-1e-6;qi.svg.line=function(){return se(a)};var Oa=qi.map({linear:pe,"linear-closed":de,"step-before":me,"step-after":ve,basis:we,"basis-open":Se,"basis-closed":ke,bundle:Ee,cardinal:be,"cardinal-open":ye,"cardinal-closed":Me,monotone:ze});Oa.forEach(function(t,n){n.key=t,n.closed=/-closed$/.test(t)});var Ya=[0,2/3,1/3,0],Ua=[0,1/3,2/3,0],Ia=[0,1/6,2/3,1/6];qi.svg.line.radial=function(){var t=se(De);return t.radius=t.x,delete t.x,t.angle=t.y,delete t.y,t},me.reverse=ve,ve.reverse=me,qi.svg.area=function(){return Le(a)},qi.svg.area.radial=function(){var t=Le(De);return t.radius=t.x,delete t.x,t.innerRadius=t.x0,delete t.x0,t.outerRadius=t.x1,delete t.x1,t.angle=t.y,delete t.y,t.startAngle=t.y0,delete t.y0,t.endAngle=t.y1,delete t.y1,t},qi.svg.chord=function(){fu
nction e(t,n){var e=r(this,o,t,n),c=r(this,l,t,n);return"M"+e.p0+i(e.r,e.p1,e.a1-e.a0)+(u(e,c)?a(e.r,e.p1,e.r,e.p0):a(e.r,e.p1,c.r,c.p0)+i(c.r,c.p1,c.a1-c.a0)+a(c.r,c.p1,e.r,e.p0))+"Z"}function r(t,n,e,r){var u=n.call(t,e,r),i=f.call(t,u,r),a=s.call(t,u,r)+Pa,o=h.call(t,u,r)+Pa;return{r:i,a0:a,a1:o,p0:[i*Math.cos(a),i*Math.sin(a)],p1:[i*Math.cos(o),i*Math.sin(o)]}}function u(t,n){return t.a0==n.a0&&t.a1==n.a1}function i(t,n,e){return"A"+t+","+t+" 0 "+ +(e>Ni)+",1 "+n}function a(t,n,e,r){return"Q 0,0 "+r}var o=n,l=t,f=Fe,s=le,h=fe;return e.radius=function(t){return arguments.length?(f=c(t),e):f},e.source=function(t){return arguments.length?(o=c(t),e):o},e.target=function(t){return arguments.length?(l=c(t),e):l},e.startAngle=function(t){return arguments.length?(s=c(t),e):s},e.endAngle=function(t){return arguments.length?(h=c(t),e):h},e},qi.svg.diagonal=function(){function e(t,n){var e=r.call(this,t,n),a=u.call(this,t,n),o=(e.y+a.y)/2,c=[e,{x:e.x,y:o},{x:a.x,y:o},a];return c=c.
map(i),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var r=n,u=t,i=He;return e.source=function(t){return arguments.length?(r=c(t),e):r},e.target=function(t){return arguments.length?(u=c(t),e):u},e.projection=function(t){return arguments.length?(i=t,e):i},e},qi.svg.diagonal.radial=function(){var t=qi.svg.diagonal(),n=He,e=t.projection;return t.projection=function(t){return arguments.length?e(je(n=t)):n},t},qi.svg.symbol=function(){function t(t,r){return(Va.get(n.call(this,t,r))||Oe)(e.call(this,t,r))}var n=Re,e=Pe;return t.type=function(e){return arguments.length?(n=c(e),t):n},t.size=function(n){return arguments.length?(e=c(n),t):e},t};var Va=qi.map({circle:Oe,cross:function(t){var n=Math.sqrt(t/5)/2;return"M"+-3*n+","+-n+"H"+-n+"V"+-3*n+"H"+n+"V"+-n+"H"+3*n+"V"+n+"H"+n+"V"+3*n+"H"+-n+"V"+n+"H"+-3*n+"Z"},diamond:function(t){var n=Math.sqrt(t/(2*Za)),e=n*Za;return"M0,"+-n+"L"+e+",0"+" 0,"+n+" "+-e+",0"+"Z"},square:function(t){var n=Math.sqrt(t)/2;return"M"+-n+","+-n+"L"+n+","+-n+" "+n+"
,"+n+" "+-n+","+n+"Z"},"triangle-down":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+e+"L"+n+","+-e+" "+-n+","+-e+"Z"},"triangle-up":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+-e+"L"+n+","+e+" "+-n+","+e+"Z"}});qi.svg.symbolTypes=Va.keys();var Xa=Math.sqrt(3),Za=Math.tan(30*Ci);qi.svg.axis=function(){function t(t){t.each(function(){var t,s=qi.select(this),h=null==l?e.ticks?e.ticks.apply(e,c):e.domain():l,g=null==n?e.tickFormat?e.tickFormat.apply(e,c):String:n,p=Ie(e,h,f),d=s.selectAll(".tick.minor").data(p,String),m=d.enter().insert("line",".tick").attr("class","tick minor").style("opacity",1e-6),v=qi.transition(d.exit()).style("opacity",1e-6).remove(),y=qi.transition(d).style("opacity",1),M=s.selectAll(".tick.major").data(h,String),b=M.enter().insert("g","path").attr("class","tick major").style("opacity",1e-6),x=qi.transition(M.exit()).style("opacity",1e-6).remove(),_=qi.transition(M).style("opacity",1),w=On(e),S=s.selectAll(".domain").data([0]),k=(S.en
ter().append("path").attr("class","domain"),qi.transition(S)),E=e.copy(),A=this.__chart__||E;this.__chart__=E,b.append("line"),b.append("text");var N=b.select("line"),T=_.select("line"),q=M.select("text").text(g),C=b.select("text"),z=_.select("text");switch(r){case"bottom":t=Ye,m.attr("y2",i),y.attr("x2",0).attr("y2",i),N.attr("y2",u),C.attr("y",Math.max(u,0)+o),T.attr("x2",0).attr("y2",u),z.attr("x",0).attr("y",Math.max(u,0)+o),q.attr("dy",".71em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+a+"V0H"+w[1]+"V"+a);break;case"top":t=Ye,m.attr("y2",-i),y.attr("x2",0).attr("y2",-i),N.attr("y2",-u),C.attr("y",-(Math.max(u,0)+o)),T.attr("x2",0).attr("y2",-u),z.attr("x",0).attr("y",-(Math.max(u,0)+o)),q.attr("dy","0em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+-a+"V0H"+w[1]+"V"+-a);break;case"left":t=Ue,m.attr("x2",-i),y.attr("x2",-i).attr("y2",0),N.attr("x2",-u),C.attr("x",-(Math.max(u,0)+o)),T.attr("x2",-u).attr("y2",0),z.attr("x",-(Math.max(u,0)+o)).attr("y
",0),q.attr("dy",".32em").style("text-anchor","end"),k.attr("d","M"+-a+","+w[0]+"H0V"+w[1]+"H"+-a);break;case"right":t=Ue,m.attr("x2",i),y.attr("x2",i).attr("y2",0),N.attr("x2",u),C.attr("x",Math.max(u,0)+o),T.attr("x2",u).attr("y2",0),z.attr("x",Math.max(u,0)+o).attr("y",0),q.attr("dy",".32em").style("text-anchor","start"),k.attr("d","M"+a+","+w[0]+"H0V"+w[1]+"H"+a)}if(e.ticks)b.call(t,A),_.call(t,E),x.call(t,E),m.call(t,A),y.call(t,E),v.call(t,E);else{var D=E.rangeBand()/2,L=function(t){return E(t)+D};b.call(t,L),_.call(t,L)}})}var n,e=qi.scale.linear(),r=Ba,u=6,i=6,a=6,o=3,c=[10],l=null,f=0;return t.scale=function(n){return arguments.length?(e=n,t):e},t.orient=function(n){return arguments.length?(r=n in $a?n+"":Ba,t):r},t.ticks=function(){return arguments.length?(c=arguments,t):c},t.tickValues=function(n){return arguments.length?(l=n,t):l},t.tickFormat=function(e){return arguments.length?(n=e,t):n},t.tickSize=function(n,e){if(!arguments.length)return u;var r=arguments.len
gth-1;return u=+n,i=r>1?+e:u,a=r>0?+arguments[r]:u,t},t.tickPadding=function(n){return arguments.length?(o=+n,t):o},t.tickSubdivide=function(n){return arguments.length?(f=+n,t):f},t};var Ba="bottom",$a={top:1,right:1,bottom:1,left:1};qi.svg.brush=function(){function t(i){i.each(function(){var i,a=qi.select(this),f=a.selectAll(".background").data([0]),s=a.selectAll(".extent").data([0]),h=a.selectAll(".resize").data(l,String);a.style("pointer-events","all").on("mousedown.brush",u).on("touchstart.brush",u),f.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),s.enter().append("rect").attr("class","extent").style("cursor","move"),h.enter().append("g").attr("class",function(t){return"resize "+t}).style("cursor",function(t){return Ja[t]}).append("rect").attr("x",function(t){return/[ew]$/.test(t)?-3:null}).attr("y",function(t){return/^[ns]/.test(t)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),h.style(
"display",t.empty()?"none":null),h.exit().remove(),o&&(i=On(o),f.attr("x",i[0]).attr("width",i[1]-i[0]),e(a)),c&&(i=On(c),f.attr("y",i[0]).attr("height",i[1]-i[0]),r(a)),n(a)})}function n(t){t.selectAll(".resize").attr("transform",function(t){return"translate("+f[+/e$/.test(t)][0]+","+f[+/^s/.test(t)][1]+")"})}function e(t){t.select(".extent").attr("x",f[0][0]),t.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1][0]-f[0][0])}function r(t){t.select(".extent").attr("y",f[0][1]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1][1]-f[0][1])}function u(){function u(){var t=qi.event.changedTouches;return t?qi.touches(v,t)[0]:qi.mouse(v)}function l(){32==qi.event.keyCode&&(S||(d=null,k[0]-=f[1][0],k[1]-=f[1][1],S=2),j())}function s(){32==qi.event.keyCode&&2==S&&(k[0]+=f[1][0],k[1]+=f[1][1],S=0,j())}function h(){var t=u(),i=!1;m&&(t[0]+=m[0],t[1]+=m[1]),S||(qi.event.altKey?(d||(d=[(f[0][0]+f[1][0])/2,(f[0][1]+f[1][1])/2]),k[0]=f[+(t[0]<d[0])][0],k[1]=f[+(t[1]<d[1])][1]):
d=null),_&&g(t,o,0)&&(e(b),i=!0),w&&g(t,c,1)&&(r(b),i=!0),i&&(n(b),M({type:"brush",mode:S?"move":"resize"}))}function g(t,n,e){var r,u,a=On(n),o=a[0],c=a[1],l=k[e],s=f[1][e]-f[0][e];return S&&(o-=l,c-=s+l),r=Math.max(o,Math.min(c,t[e])),S?u=(r+=l)+s:(d&&(l=Math.max(o,Math.min(c,2*d[e]-r))),r>l?(u=r,r=l):u=l),f[0][e]!==r||f[1][e]!==u?(i=null,f[0][e]=r,f[1][e]=u,!0):void 0}function p(){h(),b.style("pointer-events","all").selectAll(".resize").style("display",t.empty()?"none":null),qi.select("body").style("cursor",null),E.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),M({type:"brushend"}),j()}var d,m,v=this,y=qi.select(qi.event.target),M=a.of(v,arguments),b=qi.select(v),x=y.datum(),_=!/^(n|s)$/.test(x)&&o,w=!/^(e|w)$/.test(x)&&c,S=y.classed("extent"),k=u(),E=qi.select(Li).on("mousemove.brush",h).on("mouseup.brush",p).on("touchmove.brush",h).on("touchend.brush",p).on("keydown
.brush",l).on("keyup.brush",s);if(S)k[0]=f[0][0]-k[0],k[1]=f[0][1]-k[1];else if(x){var A=+/w$/.test(x),N=+/^n/.test(x);m=[f[1-A][0]-k[0],f[1-N][1]-k[1]],k[0]=f[A][0],k[1]=f[N][1]}else qi.event.altKey&&(d=k.slice());b.style("pointer-events","none").selectAll(".resize").style("display",null),qi.select("body").style("cursor",y.style("cursor")),M({type:"brushstart"}),h(),j()}var i,a=R(t,"brushstart","brush","brushend"),o=null,c=null,l=Ga[0],f=[[0,0],[0,0]];return t.x=function(n){return arguments.length?(o=n,l=Ga[!o<<1|!c],t):o},t.y=function(n){return arguments.length?(c=n,l=Ga[!o<<1|!c],t):c},t.extent=function(n){var e,r,u,a,l;return arguments.length?(i=[[0,0],[0,0]],o&&(e=n[0],r=n[1],c&&(e=e[0],r=r[0]),i[0][0]=e,i[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),f[0][0]=0|e,f[1][0]=0|r),c&&(u=n[0],a=n[1],o&&(u=u[1],a=a[1]),i[0][1]=u,i[1][1]=a,c.invert&&(u=c(u),a=c(a)),u>a&&(l=u,u=a,a=l),f[0][1]=0|u,f[1][1]=0|a),t):(n=i||f,o&&(e=n[0][0],r=n[1][0],i||(e=f[0][0],r=f[1][0],o.in
vert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(u=n[0][1],a=n[1][1],i||(u=f[0][1],a=f[1][1],c.invert&&(u=c.invert(u),a=c.invert(a)),u>a&&(l=u,u=a,a=l))),o&&c?[[e,u],[r,a]]:o?[e,r]:c&&[u,a])},t.clear=function(){return i=null,f[0][0]=f[0][1]=f[1][0]=f[1][1]=0,t},t.empty=function(){return o&&f[0][0]===f[1][0]||c&&f[0][1]===f[1][1]},qi.rebind(t,a,"on")};var Ja={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Ga=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];qi.behavior={},qi.behavior.drag=function(){function t(){this.on("mousedown.drag",n).on("touchstart.drag",n)}function n(){function t(){var t=o.parentNode;return null!=f?qi.touches(t).filter(function(t){return t.identifier===f})[0]:qi.mouse(t)}function n(){if(!o.parentNode)return u();var n=t(),e=n[0]-s[0],r=n[1]-s[1];h|=e|r,s=n,j(),c({type:"drag",x:n[0]+a[0],y:n[1]+a[1],dx:e,dy:r})}function u(){c({type:"dragend"}),h&&(j(),q
i.event.target===l&&g.on("click.drag",i,!0)),g.on(null!=f?"touchmove.drag-"+f:"mousemove.drag",null).on(null!=f?"touchend.drag-"+f:"mouseup.drag",null)}function i(){j(),g.on("click.drag",null)}var a,o=this,c=e.of(o,arguments),l=qi.event.target,f=qi.event.touches?qi.event.changedTouches[0].identifier:null,s=t(),h=0,g=qi.select(Li).on(null!=f?"touchmove.drag-"+f:"mousemove.drag",n).on(null!=f?"touchend.drag-"+f:"mouseup.drag",u,!0);r?(a=r.apply(o,arguments),a=[a.x-s[0],a.y-s[1]]):a=[0,0],null==f&&j(),c({type:"dragstart"})}var e=R(t,"drag","dragstart","dragend"),r=null;return t.origin=function(n){return arguments.length?(r=n,t):r},qi.rebind(t,e,"on")},qi.behavior.zoom=function(){function t(){this.on("mousedown.zoom",o).on("mousemove.zoom",l).on(Qa+".zoom",c).on("dblclick.zoom",f).on("touchstart.zoom",s).on("touchmove.zoom",h).on("touchend.zoom",s)}function n(t){return[(t[0]-b[0])/x,(t[1]-b[1])/x]}function e(t){return[t[0]*x+b[0],t[1]*x+b[1]]}function r(t){x=Math.max(_[0],Math.m
in(_[1],t))}function u(t,n){n=e(n),b[0]+=t[0]-n[0],b[1]+=t[1]-n[1]}function i(){m&&m.domain(d.range().map(function(t){return(t-b[0])/x}).map(d.invert)),y&&y.domain(v.range().map(function(t){return(t-b[1])/x}).map(v.invert))}function a(t){i(),qi.event.preventDefault(),t({type:"zoom",scale:x,translate:b})}function o(){function t(){l=1,u(qi.mouse(i),s),a(o)}function e(){l&&j(),f.on("mousemove.zoom",null).on("mouseup.zoom",null),l&&qi.event.target===c&&f.on("click.zoom",r,!0)}function r(){j(),f.on("click.zoom",null)}var i=this,o=w.of(i,arguments),c=qi.event.target,l=0,f=qi.select(Li).on("mousemove.zoom",t).on("mouseup.zoom",e),s=n(qi.mouse(i));Li.focus(),j()}function c(){g||(g=n(qi.mouse(this))),r(Math.pow(2,.002*Ka())*x),u(qi.mouse(this),g),a(w.of(this,arguments))}function l(){g=null}function f(){var t=qi.mouse(this),e=n(t),i=Math.log(x)/Math.LN2;r(Math.pow(2,qi.event.shiftKey?Math.ceil(i)-1:Math.floor(i)+1)),u(t,e),a(w.of(this,arguments))}function s(){var t=qi.touches(this),e=
Date.now();if(p=x,g={},t.forEach(function(t){g[t.identifier]=n(t)}),j(),1===t.length){if(500>e-M){var i=t[0],o=n(t[0]);r(2*x),u(i,o),a(w.of(this,arguments))}M=e}}function h(){var t=qi.touches(this),n=t[0],e=g[n.identifier];if(i=t[1]){var i,o=g[i.identifier];n=[(n[0]+i[0])/2,(n[1]+i[1])/2],e=[(e[0]+o[0])/2,(e[1]+o[1])/2],r(qi.event.scale*p)}u(n,e),M=null,a(w.of(this,arguments))}var g,p,d,m,v,y,M,b=[0,0],x=1,_=Wa,w=R(t,"zoom");return t.translate=function(n){return arguments.length?(b=n.map(Number),i(),t):b},t.scale=function(n){return arguments.length?(x=+n,i(),t):x},t.scaleExtent=function(n){return arguments.length?(_=null==n?Wa:n.map(Number),t):_},t.x=function(n){return arguments.length?(m=n,d=n.copy(),b=[0,0],x=1,t):m},t.y=function(n){return arguments.length?(y=n,v=n.copy(),b=[0,0],x=1,t):y},qi.rebind(t,w,"on")};var Ka,Wa=[0,1/0],Qa="onwheel"in document?(Ka=function(){return-qi.event.deltaY*(qi.event.deltaMode?120:1)},"wheel"):"onmousewheel"in document?(Ka=function(){return
qi.event.wheelDelta},"mousewheel"):(Ka=function(){return-qi.event.detail},"MozMousePixelScroll");qi.layout={},qi.layout.bundle=function(){return function(t){for(var n=[],e=-1,r=t.length;r>++e;)n.push(Ve(t[e]));return n}},qi.layout.chord=function(){function t(){var t,l,s,h,g,p={},d=[],m=qi.range(i),v=[];for(e=[],r=[],t=0,h=-1;i>++h;){for(l=0,g=-1;i>++g;)l+=u[h][g];d.push(l),v.push(qi.range(i)),t+=l}for(a&&m.sort(function(t,n){return a(d[t],d[n])}),o&&v.forEach(function(t,n){t.sort(function(t,e){return o(u[n][t],u[n][e])})}),t=(2*Ni-f*i)/t,l=0,h=-1;i>++h;){for(s=l,g=-1;i>++g;){var y=m[h],M=v[y][g],b=u[y][M],x=l,_=l+=b*t;p[y+"-"+M]={index:y,subindex:M,startAngle:x,endAngle:_,value:b}}r[y]={index:y,startAngle:s,endAngle:l,value:(l-s)/t},l+=f}for(h=-1;i>++h;)for(g=h-1;i>++g;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&n()}function n(){e.sort(function(t,n){return c((t.source.value+t.target.value)/2,(n.source
.value+n.target.value)/2)})}var e,r,u,i,a,o,c,l={},f=0;return l.matrix=function(t){return arguments.length?(i=(u=t)&&u.length,e=r=null,l):u},l.padding=function(t){return arguments.length?(f=t,e=r=null,l):f},l.sortGroups=function(t){return arguments.length?(a=t,e=r=null,l):a},l.sortSubgroups=function(t){return arguments.length?(o=t,e=null,l):o},l.sortChords=function(t){return arguments.length?(c=t,e&&n(),l):c},l.chords=function(){return e||t(),e},l.groups=function(){return r||t(),r},l},qi.layout.force=function(){function t(t){return function(n,e,r,u){if(n.point!==t){var i=n.cx-t.x,a=n.cy-t.y,o=1/Math.sqrt(i*i+a*a);if(m>(u-e)*o){var c=n.charge*o*o;return t.px-=i*c,t.py-=a*c,!0}if(n.point&&isFinite(o)){var c=n.pointCharge*o*o;t.px-=i*c,t.py-=a*c}}return!n.charge}}function n(t){t.px=qi.event.x,t.py=qi.event.y,c.resume()}var e,r,u,i,o,c={},l=qi.dispatch("start","tick","end"),f=[1,1],s=.9,h=to,g=no,p=-30,d=.1,m=.8,v=[],y=[];return c.tick=function(){if(.005>(r*=.99))return l.end({t
ype:"end",alpha:r=0}),!0;var n,e,a,c,h,g,m,M,b,x=v.length,_=y.length;for(e=0;_>e;++e)a=y[e],c=a.source,h=a.target,M=h.x-c.x,b=h.y-c.y,(g=M*M+b*b)&&(g=r*i[e]*((g=Math.sqrt(g))-u[e])/g,M*=g,b*=g,h.x-=M*(m=c.weight/(h.weight+c.weight)),h.y-=b*m,c.x+=M*(m=1-m),c.y+=b*m);if((m=r*d)&&(M=f[0]/2,b=f[1]/2,e=-1,m))for(;x>++e;)a=v[e],a.x+=(M-a.x)*m,a.y+=(b-a.y)*m;if(p)for(Ke(n=qi.geom.quadtree(v),r,o),e=-1;x>++e;)(a=v[e]).fixed||n.visit(t(a));for(e=-1;x>++e;)a=v[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*s,a.y-=(a.py-(a.py=a.y))*s);l.tick({type:"tick",alpha:r})},c.nodes=function(t){return arguments.length?(v=t,c):v},c.links=function(t){return arguments.length?(y=t,c):y},c.size=function(t){return arguments.length?(f=t,c):f},c.linkDistance=function(t){return arguments.length?(h="function"==typeof t?t:+t,c):h},c.distance=c.linkDistance,c.linkStrength=function(t){return arguments.length?(g="function"==typeof t?t:+t,c):g},c.friction=function(t){return arguments.length?(s=+t,c):s
},c.charge=function(t){return arguments.length?(p="function"==typeof t?t:+t,c):p},c.gravity=function(t){return arguments.length?(d=+t,c):d},c.theta=function(t){return arguments.length?(m=+t,c):m},c.alpha=function(t){return arguments.length?(t=+t,r?r=t>0?t:0:t>0&&(l.start({type:"start",alpha:r=t}),qi.timer(c.tick)),c):r},c.start=function(){function t(t,r){for(var u,i=n(e),a=-1,o=i.length;o>++a;)if(!isNaN(u=i[a][t]))return u;
-return Math.random()*r}function n(){if(!a){for(a=[],r=0;s>r;++r)a[r]=[];for(r=0;d>r;++r){var t=y[r];a[t.source.index].push(t.target),a[t.target.index].push(t.source)}}return a[e]}var e,r,a,l,s=v.length,d=y.length,m=f[0],M=f[1];for(e=0;s>e;++e)(l=v[e]).index=e,l.weight=0;for(e=0;d>e;++e)l=y[e],"number"==typeof l.source&&(l.source=v[l.source]),"number"==typeof l.target&&(l.target=v[l.target]),++l.source.weight,++l.target.weight;for(e=0;s>e;++e)l=v[e],isNaN(l.x)&&(l.x=t("x",m)),isNaN(l.y)&&(l.y=t("y",M)),isNaN(l.px)&&(l.px=l.x),isNaN(l.py)&&(l.py=l.y);if(u=[],"function"==typeof h)for(e=0;d>e;++e)u[e]=+h.call(this,y[e],e);else for(e=0;d>e;++e)u[e]=h;if(i=[],"function"==typeof g)for(e=0;d>e;++e)i[e]=+g.call(this,y[e],e);else for(e=0;d>e;++e)i[e]=g;if(o=[],"function"==typeof p)for(e=0;s>e;++e)o[e]=+p.call(this,v[e],e);else for(e=0;s>e;++e)o[e]=p;return c.resume()},c.resume=function(){return c.alpha(.1)},c.stop=function(){return c.alpha(0)},c.drag=function(){return e||(e=qi.behavio
r.drag().origin(a).on("dragstart.force",Be).on("drag.force",n).on("dragend.force",$e)),arguments.length?(this.on("mouseover.force",Je).on("mouseout.force",Ge).call(e),void 0):e},qi.rebind(c,l,"on")};var to=20,no=1;qi.layout.partition=function(){function t(n,e,r,u){var i=n.children;if(n.x=e,n.y=n.depth*u,n.dx=r,n.dy=u,i&&(a=i.length)){var a,o,c,l=-1;for(r=n.value?r/n.value:0;a>++l;)t(o=i[l],e,c=o.value*r,u),e+=c}}function n(t){var e=t.children,r=0;if(e&&(u=e.length))for(var u,i=-1;u>++i;)r=Math.max(r,n(e[i]));return 1+r}function e(e,i){var a=r.call(this,e,i);return t(a[0],0,u[0],u[1]/n(a[0])),a}var r=qi.layout.hierarchy(),u=[1,1];return e.size=function(t){return arguments.length?(u=t,e):u},lr(e,r)},qi.layout.pie=function(){function t(i){var a=i.map(function(e,r){return+n.call(t,e,r)}),o=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-r)/qi.sum(a),l=qi.range(i.length);null!=e&&l.sort(e===eo?function(t,n){return a[n]-a[t]}:f
unction(t,n){return e(i[t],i[n])});var f=[];return l.forEach(function(t){var n;f[t]={data:i[t],value:n=a[t],startAngle:o,endAngle:o+=n*c}}),f}var n=Number,e=eo,r=0,u=2*Ni;return t.value=function(e){return arguments.length?(n=e,t):n},t.sort=function(n){return arguments.length?(e=n,t):e},t.startAngle=function(n){return arguments.length?(r=n,t):r},t.endAngle=function(n){return arguments.length?(u=n,t):u},t};var eo={};qi.layout.stack=function(){function t(a,c){var l=a.map(function(e,r){return n.call(t,e,r)}),f=l.map(function(n){return n.map(function(n,e){return[i.call(t,n,e),o.call(t,n,e)]})}),s=e.call(t,f,c);l=qi.permute(l,s),f=qi.permute(f,s);var h,g,p,d=r.call(t,f,c),m=l.length,v=l[0].length;for(g=0;v>g;++g)for(u.call(t,l[0][g],p=d[g],f[0][g][1]),h=1;m>h;++h)u.call(t,l[h][g],p+=f[h-1][g][1],f[h][g][1]);return a}var n=a,e=nr,r=er,u=tr,i=We,o=Qe;return t.values=function(e){return arguments.length?(n=e,t):n},t.order=function(n){return arguments.length?(e="function"==typeof n?n:r
o.get(n)||nr,t):e},t.offset=function(n){return arguments.length?(r="function"==typeof n?n:uo.get(n)||er,t):r},t.x=function(n){return arguments.length?(i=n,t):i},t.y=function(n){return arguments.length?(o=n,t):o},t.out=function(n){return arguments.length?(u=n,t):u},t};var ro=qi.map({"inside-out":function(t){var n,e,r=t.length,u=t.map(rr),i=t.map(ur),a=qi.range(r).sort(function(t,n){return u[t]-u[n]}),o=0,c=0,l=[],f=[];for(n=0;r>n;++n)e=a[n],c>o?(o+=i[e],l.push(e)):(c+=i[e],f.push(e));return f.reverse().concat(l)},reverse:function(t){return qi.range(t.length).reverse()},"default":nr}),uo=qi.map({silhouette:function(t){var n,e,r,u=t.length,i=t[0].length,a=[],o=0,c=[];for(e=0;i>e;++e){for(n=0,r=0;u>n;n++)r+=t[n][e][1];r>o&&(o=r),a.push(r)}for(e=0;i>e;++e)c[e]=(o-a[e])/2;return c},wiggle:function(t){var n,e,r,u,i,a,o,c,l,f=t.length,s=t[0],h=s.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(n=0,u=0;f>n;++n)u+=t[n][e][1];for(n=0,i=0,o=s[e][0]-s[e-1][0];f>n;++n){for(r=0,a=(t[n][e][1]-t[
n][e-1][1])/(2*o);n>r;++r)a+=(t[r][e][1]-t[r][e-1][1])/o;i+=a*t[n][e][1]}g[e]=c-=u?i/u*o:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(t){var n,e,r,u=t.length,i=t[0].length,a=1/u,o=[];for(e=0;i>e;++e){for(n=0,r=0;u>n;n++)r+=t[n][e][1];if(r)for(n=0;u>n;n++)t[n][e][1]/=r;else for(n=0;u>n;n++)t[n][e][1]=a}for(e=0;i>e;++e)o[e]=0;return o},zero:er});qi.layout.histogram=function(){function t(t,i){for(var a,o,c=[],l=t.map(e,this),f=r.call(this,l,i),s=u.call(this,f,l,i),i=-1,h=l.length,g=s.length-1,p=n?1:1/h;g>++i;)a=c[i]=[],a.dx=s[i+1]-(a.x=s[i]),a.y=0;if(g>0)for(i=-1;h>++i;)o=l[i],o>=f[0]&&f[1]>=o&&(a=c[qi.bisect(s,o,1,g)-1],a.y+=p,a.push(t[i]));return c}var n=!0,e=Number,r=cr,u=ar;return t.value=function(n){return arguments.length?(e=n,t):e},t.range=function(n){return arguments.length?(r=c(n),t):r},t.bins=function(n){return arguments.length?(u="number"==typeof n?function(t){return or(t,n)}:c(n),t):u},t.frequency=function(e){return arguments.length?(n=!!e,t):n},t}
,qi.layout.hierarchy=function(){function t(n,a,o){var c=u.call(e,n,a);if(n.depth=a,o.push(n),c&&(l=c.length)){for(var l,f,s=-1,h=n.children=[],g=0,p=a+1;l>++s;)f=t(c[s],p,o),f.parent=n,h.push(f),g+=f.value;r&&h.sort(r),i&&(n.value=g)}else i&&(n.value=+i.call(e,n,a)||0);return n}function n(t,r){var u=t.children,a=0;if(u&&(o=u.length))for(var o,c=-1,l=r+1;o>++c;)a+=n(u[c],l);else i&&(a=+i.call(e,t,r)||0);return i&&(t.value=a),a}function e(n){var e=[];return t(n,0,e),e}var r=hr,u=fr,i=sr;return e.sort=function(t){return arguments.length?(r=t,e):r},e.children=function(t){return arguments.length?(u=t,e):u},e.value=function(t){return arguments.length?(i=t,e):i},e.revalue=function(t){return n(t,0),t},e},qi.layout.pack=function(){function t(t,u){var i=n.call(this,t,u),a=i[0];a.x=0,a.y=0,Lr(a,function(t){t.r=Math.sqrt(t.value)}),Lr(a,yr);var o=r[0],c=r[1],l=Math.max(2*a.r/o,2*a.r/c);if(e>0){var f=e*l/2;Lr(a,function(t){t.r+=f}),Lr(a,yr),Lr(a,function(t){t.r-=f}),l=Math.max(2*a.r/o,2*
a.r/c)}return xr(a,o/2,c/2,1/l),i}var n=qi.layout.hierarchy().sort(pr),e=0,r=[1,1];return t.size=function(n){return arguments.length?(r=n,t):r},t.padding=function(n){return arguments.length?(e=+n,t):e},lr(t,n)},qi.layout.cluster=function(){function t(t,u){var i,a=n.call(this,t,u),o=a[0],c=0;Lr(o,function(t){var n=t.children;n&&n.length?(t.x=Sr(n),t.y=wr(n)):(t.x=i?c+=e(t,i):0,t.y=0,i=t)});var l=kr(o),f=Er(o),s=l.x-e(l,f)/2,h=f.x+e(f,l)/2;return Lr(o,function(t){t.x=(t.x-s)/(h-s)*r[0],t.y=(1-(o.y?t.y/o.y:1))*r[1]}),a}var n=qi.layout.hierarchy().sort(null).value(null),e=Ar,r=[1,1];return t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},lr(t,n)},qi.layout.tree=function(){function t(t,u){function i(t,n){var r=t.children,u=t._tree;if(r&&(a=r.length)){for(var a,c,l,f=r[0],s=f,h=-1;a>++h;)l=r[h],i(l,c),s=o(l,c,s),c=l;Fr(t);var g=.5*(f._tree.prelim+l._tree.prelim);n?(u.prelim=n._tree.prelim+e(t,n),u.mod=u.prelim-g):u.p
relim=g}else n&&(u.prelim=n._tree.prelim+e(t,n))}function a(t,n){t.x=t._tree.prelim+n;var e=t.children;if(e&&(r=e.length)){var r,u=-1;for(n+=t._tree.mod;r>++u;)a(e[u],n)}}function o(t,n,r){if(n){for(var u,i=t,a=t,o=n,c=t.parent.children[0],l=i._tree.mod,f=a._tree.mod,s=o._tree.mod,h=c._tree.mod;o=Tr(o),i=Nr(i),o&&i;)c=Nr(c),a=Tr(a),a._tree.ancestor=t,u=o._tree.prelim+s-i._tree.prelim-l+e(o,i),u>0&&(Hr(jr(o,t,r),t,u),l+=u,f+=u),s+=o._tree.mod,l+=i._tree.mod,h+=c._tree.mod,f+=a._tree.mod;o&&!Tr(a)&&(a._tree.thread=o,a._tree.mod+=s-f),i&&!Nr(c)&&(c._tree.thread=i,c._tree.mod+=l-h,r=t)}return r}var c=n.call(this,t,u),l=c[0];Lr(l,function(t,n){t._tree={ancestor:t,prelim:0,mod:0,change:0,shift:0,number:n?n._tree.number+1:0}}),i(l),a(l,-l._tree.prelim);var f=qr(l,zr),s=qr(l,Cr),h=qr(l,Dr),g=f.x-e(f,s)/2,p=s.x+e(s,f)/2,d=h.depth||1;return Lr(l,function(t){t.x=(t.x-g)/(p-g)*r[0],t.y=t.depth/d*r[1],delete t._tree}),c}var n=qi.layout.hierarchy().sort(null).value(null),e=Ar,r=[1,1];retu
rn t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},lr(t,n)},qi.layout.treemap=function(){function t(t,n){for(var e,r,u=-1,i=t.length;i>++u;)r=(e=t[u]).value*(0>n?0:n),e.area=isNaN(r)||0>=r?0:r}function n(e){var i=e.children;if(i&&i.length){var a,o,c,l=s(e),f=[],h=i.slice(),p=1/0,d="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(t(h,l.dx*l.dy/e.value),f.area=0;(c=h.length)>0;)f.push(a=h[c-1]),f.area+=a.area,"squarify"!==g||p>=(o=r(f,d))?(h.pop(),p=o):(f.area-=f.pop().area,u(f,d,l,!1),d=Math.min(l.dx,l.dy),f.length=f.area=0,p=1/0);f.length&&(u(f,d,l,!0),f.length=f.area=0),i.forEach(n)}}function e(n){var r=n.children;if(r&&r.length){var i,a=s(n),o=r.slice(),c=[];for(t(o,a.dx*a.dy/n.value),c.area=0;i=o.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?a.dx:a.dy,a,!o.length),c.length=c.area=0);r.forEach(e)}}function r(t,n){for(var e,r=t.area,u=0,i=1/0,a=-1,o=t.length;
o>++a;)(e=t[a].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,n*=n,r?Math.max(n*u*p/r,r/(n*i*p)):1/0}function u(t,n,e,r){var u,i=-1,a=t.length,o=e.x,l=e.y,f=n?c(t.area/n):0;if(n==e.dx){for((r||f>e.dy)&&(f=e.dy);a>++i;)u=t[i],u.x=o,u.y=l,u.dy=f,o+=u.dx=Math.min(e.x+e.dx-o,f?c(u.area/f):0);u.z=!0,u.dx+=e.x+e.dx-o,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);a>++i;)u=t[i],u.x=o,u.y=l,u.dx=f,l+=u.dy=Math.min(e.y+e.dy-l,f?c(u.area/f):0);u.z=!1,u.dy+=e.y+e.dy-l,e.x+=f,e.dx-=f}}function i(r){var u=a||o(r),i=u[0];return i.x=0,i.y=0,i.dx=l[0],i.dy=l[1],a&&o.revalue(i),t([i],i.dx*i.dy/i.value),(a?e:n)(i),h&&(a=u),u}var a,o=qi.layout.hierarchy(),c=Math.round,l=[1,1],f=null,s=Pr,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(t){return arguments.length?(l=t,i):l},i.padding=function(t){function n(n){var e=t.call(i,n,n.depth);return null==e?Pr(n):Rr(n,"number"==typeof e?[e,e,e,e]:e)}function e(n){return Rr(n,t)}if(!arguments.length)return f;var r;return s=null==(f=t)?Pr:"funct
ion"==(r=typeof t)?n:"number"===r?(t=[t,t,t,t],e):e,i},i.round=function(t){return arguments.length?(c=t?Math.round:Number,i):c!=Number},i.sticky=function(t){return arguments.length?(h=t,a=null,i):h},i.ratio=function(t){return arguments.length?(p=t,i):p},i.mode=function(t){return arguments.length?(g=t+"",i):g},lr(i,o)},qi.csv=Or(",","text/csv"),qi.tsv=Or(" ","text/tab-separated-values"),qi.geo={},qi.geo.stream=function(t,n){io.hasOwnProperty(t.type)?io[t.type](t,n):Yr(t,n)};var io={Feature:function(t,n){Yr(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,u=e.length;u>++r;)Yr(e[r].geometry,n)}},ao={Sphere:function(t,n){n.sphere()},Point:function(t,n){var e=t.coordinates;n.point(e[0],e[1])},MultiPoint:function(t,n){for(var e,r=t.coordinates,u=-1,i=r.length;i>++u;)e=r[u],n.point(e[0],e[1])},LineString:function(t,n){Ur(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,u=e.length;u>++r;)Ur(e[r],n,0)},Polygon:function(t,n){Ir(t.c
oordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,u=e.length;u>++r;)Ir(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,u=e.length;u>++r;)Yr(e[r],n)}};qi.geo.albersUsa=function(){function t(t){return n(t)(t)}function n(t){var n=t[0],a=t[1];return a>50?r:-140>n?u:21>a?i:e}var e=qi.geo.albers(),r=qi.geo.albers().rotate([160,0]).center([0,60]).parallels([55,65]),u=qi.geo.albers().rotate([160,0]).center([0,20]).parallels([8,18]),i=qi.geo.albers().rotate([60,0]).center([0,10]).parallels([8,18]);return t.scale=function(n){return arguments.length?(e.scale(n),r.scale(.6*n),u.scale(n),i.scale(1.5*n),t.translate(e.translate())):e.scale()},t.translate=function(n){if(!arguments.length)return e.translate();var a=e.scale(),o=n[0],c=n[1];return e.translate(n),r.translate([o-.4*a,c+.17*a]),u.translate([o-.19*a,c+.2*a]),i.translate([o+.58*a,c+.43*a]),t},t.scale(e.scale())},(qi.geo.albers=function(){var t=29.5*Ci,n=45.5*Ci,e=Fu(Qr),r=e(t,n);return r.p
arallels=function(r){return arguments.length?e(t=r[0]*Ci,n=r[1]*Ci):[t*zi,n*zi]},r.rotate([98,0]).center([0,38]).scale(1e3)}).raw=Qr;var oo=Yu(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(qi.geo.azimuthalEqualArea=function(){return Lu(oo)}).raw=oo;var co=Yu(function(t){var n=Math.acos(t);return n&&n/Math.sin(n)},a);(qi.geo.azimuthalEquidistant=function(){return Lu(co)}).raw=co,qi.geo.bounds=tu(a),qi.geo.centroid=function(t){lo=fo=so=ho=go=0,qi.geo.stream(t,po);var n;return fo&&Math.abs(n=Math.sqrt(so*so+ho*ho+go*go))>Ti?[Math.atan2(ho,so)*zi,Math.asin(Math.max(-1,Math.min(1,go/n)))*zi]:void 0};var lo,fo,so,ho,go,po={sphere:function(){2>lo&&(lo=2,fo=so=ho=go=0)},point:nu,lineStart:ru,lineEnd:uu,polygonStart:function(){2>lo&&(lo=2,fo=so=ho=go=0),po.lineStart=eu},polygonEnd:function(){po.lineStart=ru}};qi.geo.circle=function(){function t(){var t="function"==typeof r?r.apply(this,arguments):r,n=ju(-t[0]*Ci,-t[1]*Ci,0).invert,u=[];return e(null,nu
ll,1,{point:function(t,e){u.push(t=n(t,e)),t[0]*=zi,t[1]*=zi}}),{type:"Polygon",coordinates:[u]}}var n,e,r=[0,0],u=6;return t.origin=function(n){return arguments.length?(r=n,t):r},t.angle=function(r){return arguments.length?(e=iu((n=+r)*Ci,u*Ci),t):n},t.precision=function(r){return arguments.length?(e=iu(n*Ci,(u=+r)*Ci),t):u},t.angle(90)};var mo=ou(o,pu,mu);(qi.geo.equirectangular=function(){return Lu(Mu).scale(250/Ni)}).raw=Mu.invert=Mu;var vo=Yu(function(t){return 1/t},Math.atan);(qi.geo.gnomonic=function(){return Lu(vo)}).raw=vo,qi.geo.graticule=function(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return qi.range(Math.ceil(r/c)*c,e,c).map(a).concat(qi.range(Math.ceil(i/l)*l,u,l).map(o))}var e,r,u,i,a,o,c=22.5,l=c,f=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[a(r).concat(o(u).slice(1),a(e).reverse().slice(1),o(i).reverse().slice(1))
]}},t.extent=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],i=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),i>u&&(n=i,i=u,u=n),t.precision(f)):[[r,i],[e,u]]},t.step=function(n){return arguments.length?(c=+n[0],l=+n[1],t):[c,l]},t.precision=function(n){return arguments.length?(f=+n,a=bu(i,u,f),o=xu(r,e,f),t):f},t.extent([[-180+Ti,-90+Ti],[180-Ti,90-Ti]])},qi.geo.interpolate=function(t,n){return _u(t[0]*Ci,t[1]*Ci,n[0]*Ci,n[1]*Ci)},qi.geo.greatArc=function(){function e(){for(var t=r||a.apply(this,arguments),n=u||o.apply(this,arguments),e=i||qi.geo.interpolate(t,n),l=0,f=c/e.distance,s=[t];1>(l+=f);)s.push(e(l));return s.push(n),{type:"LineString",coordinates:s}}var r,u,i,a=n,o=t,c=6*Ci;return e.distance=function(){return(i||qi.geo.interpolate(r||a.apply(this,arguments),u||o.apply(this,arguments))).distance},e.source=function(t){return arguments.length?(a=t,r="function"==typeof t?null:t,i=r&&u?qi.geo.interpolate(r,u):null,e):a},e.target=function(t){return arguments.length?
(o=t,u="function"==typeof t?null:t,i=r&&u?qi.geo.interpolate(r,u):null,e):o},e.precision=function(t){return arguments.length?(c=t*Ci,e):c/Ci},e},wu.invert=function(t,n){return[2*Ni*t,2*Math.atan(Math.exp(2*Ni*n))-Ni/2]},(qi.geo.mercator=function(){return Lu(wu).scale(500)}).raw=wu;var yo=Yu(function(){return 1},Math.asin);(qi.geo.orthographic=function(){return Lu(yo)}).raw=yo,qi.geo.path=function(){function t(t){return t&&qi.geo.stream(t,r(u.pointRadius("function"==typeof i?+i.apply(this,arguments):i))),u.result()}var n,e,r,u,i=4.5;return t.area=function(t){return Mo=0,qi.geo.stream(t,r(xo)),Mo},t.centroid=function(t){return lo=so=ho=go=0,qi.geo.stream(t,r(_o)),go?[so/go,ho/go]:void 0},t.bounds=function(t){return tu(r)(t)},t.projection=function(e){return arguments.length?(r=(n=e)?e.stream||ku(e):a,t):n},t.context=function(n){return arguments.length?(u=null==(e=n)?new Eu:new Au(n),t):e},t.pointRadius=function(n){return arguments.length?(i="function"==typeof n?n:+n,t):i},t.pro
jection(qi.geo.albersUsa()).context(null)};var Mo,bo,xo={point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){bo=0,xo.lineStart=Nu},polygonEnd:function(){xo.lineStart=xo.lineEnd=xo.point=Pn,Mo+=Math.abs(bo/2)}},_o={point:Tu,lineStart:qu,lineEnd:Cu,polygonStart:function(){_o.lineStart=zu},polygonEnd:function(){_o.point=Tu,_o.lineStart=qu,_o.lineEnd=Cu}};qi.geo.area=function(t){return wo=0,qi.geo.stream(t,Eo),wo};var wo,So,ko,Eo={sphere:function(){wo+=4*Ni},point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){So=1,ko=0,Eo.lineStart=Du},polygonEnd:function(){var t=2*Math.atan2(ko,So);wo+=0>t?4*Ni+t:t,Eo.lineStart=Eo.lineEnd=Eo.point=Pn}};qi.geo.projection=Lu,qi.geo.projectionMutator=Fu;var Ao=Yu(function(t){return 1/(1+t)},function(t){return 2*Math.atan(t)});(qi.geo.stereographic=function(){return Lu(Ao)}).raw=Ao,qi.geom={},qi.geom.hull=function(t){if(3>t.length)return[];var n,e,r,u,i,a,o,c,l,f,s=t.length,h=s-1,g=[],p=[],d=0;for(n=1;s>n;++n)t[n][1]<t[d][1]?d=n:t[n][1]==
t[d][1]&&(d=t[n][0]<t[d][0]?n:d);for(n=0;s>n;++n)n!==d&&(u=t[n][1]-t[d][1],r=t[n][0]-t[d][0],g.push({angle:Math.atan2(u,r),index:n}));for(g.sort(function(t,n){return t.angle-n.angle}),l=g[0].angle,c=g[0].index,o=0,n=1;h>n;++n)e=g[n].index,l==g[n].angle?(r=t[c][0]-t[d][0],u=t[c][1]-t[d][1],i=t[e][0]-t[d][0],a=t[e][1]-t[d][1],r*r+u*u>=i*i+a*a?g[n].index=-1:(g[o].index=-1,l=g[n].angle,o=n,c=e)):(l=g[n].angle,o=n,c=e);for(p.push(d),n=0,e=0;2>n;++e)-1!==g[e].index&&(p.push(g[e].index),n++);for(f=p.length;h>e;++e)if(-1!==g[e].index){for(;!Uu(p[f-2],p[f-1],g[e].index,t);)--f;p[f++]=g[e].index}var m=[];for(n=0;f>n;++n)m.push(t[p[n]]);return m},qi.geom.polygon=function(t){return t.area=function(){for(var n=0,e=t.length,r=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];e>++n;)r+=t[n-1][1]*t[n][0]-t[n-1][0]*t[n][1];return.5*r},t.centroid=function(n){var e,r,u=-1,i=t.length,a=0,o=0,c=t[i-1];for(arguments.length||(n=-1/(6*t.area()));i>++u;)e=c,c=t[u],r=e[0]*c[1]-c[0]*e[1],a+=(e[0]+c[0])*r,o+=(e[1]+c
[1])*r;return[a*n,o*n]},t.clip=function(n){for(var e,r,u,i,a,o,c=-1,l=t.length,f=t[l-1];l>++c;){for(e=n.slice(),n.length=0,i=t[c],a=e[(u=e.length)-1],r=-1;u>++r;)o=e[r],Iu(o,f,i)?(Iu(a,f,i)||n.push(Vu(a,o,f,i)),n.push(o)):Iu(a,f,i)&&n.push(Vu(a,o,f,i)),a=o;f=i}return n},t},qi.geom.voronoi=function(t){var n=t.map(function(){return[]}),e=1e6;return Xu(t,function(t){var r,u,i,a,o,c;1===t.a&&t.b>=0?(r=t.ep.r,u=t.ep.l):(r=t.ep.l,u=t.ep.r),1===t.a?(o=r?r.y:-e,i=t.c-t.b*o,c=u?u.y:e,a=t.c-t.b*c):(i=r?r.x:-e,o=t.c-t.a*i,a=u?u.x:e,c=t.c-t.a*a);var l=[i,o],f=[a,c];n[t.region.l.index].push(l,f),n[t.region.r.index].push(l,f)}),n=n.map(function(n,e){var r=t[e][0],u=t[e][1],i=n.map(function(t){return Math.atan2(t[0]-r,t[1]-u)}),a=qi.range(n.length).sort(function(t,n){return i[t]-i[n]});return a.filter(function(t,n){return!n||i[t]-i[a[n-1]]>Ti}).map(function(t){return n[t]})}),n.forEach(function(n,r){var u=n.length;if(!u)return n.push([-e,-e],[-e,e],[e,e],[e,-e]);if(!(u>2)){var i=t[r],a=n[0
],o=n[1],c=i[0],l=i[1],f=a[0],s=a[1],h=o[0],g=o[1],p=Math.abs(h-f),d=g-s;if(Ti>Math.abs(d)){var m=s>l?-e:e;n.push([-e,m],[e,m])}else if(Ti>p){var v=f>c?-e:e;n.push([v,-e],[v,e])}else{var m=(f-c)*(g-s)>(h-f)*(s-l)?e:-e,y=Math.abs(d)-p;Ti>Math.abs(y)?n.push([0>d?m:-m,m]):(y>0&&(m*=-1),n.push([-e,m],[e,m]))}}}),n};var No={l:"r",r:"l"};qi.geom.delaunay=function(t){var n=t.map(function(){return[]}),e=[];return Xu(t,function(e){n[e.region.l.index].push(t[e.region.r.index])}),n.forEach(function(n,r){var u=t[r],i=u[0],a=u[1];n.forEach(function(t){t.angle=Math.atan2(t[0]-i,t[1]-a)}),n.sort(function(t,n){return t.angle-n.angle});for(var o=0,c=n.length-1;c>o;o++)e.push([u,n[o],n[o+1]])}),e},qi.geom.quadtree=function(t,n,e,r,u){function i(t,n,e,r,u,i){if(!isNaN(n.x)&&!isNaN(n.y))if(t.leaf){var o=t.point;o?.01>Math.abs(o.x-n.x)+Math.abs(o.y-n.y)?a(t,n,e,r,u,i):(t.point=null,a(t,o,e,r,u,i),a(t,n,e,r,u,i)):t.point=n}else a(t,n,e,r,u,i)}function a(t,n,e,r,u,a){var o=.5*(e+u),c=.5*(r+a),l=n.
x>=o,f=n.y>=c,s=(f<<1)+l;t.leaf=!1,t=t.nodes[s]||(t.nodes[s]=Zu()),l?e=o:u=o,f?r=c:a=c,i(t,n,e,r,u,a)}var o,c=-1,l=t.length;if(5>arguments.length)if(3===arguments.length)u=e,r=n,e=n=0;else for(n=e=1/0,r=u=-1/0;l>++c;)o=t[c],n>o.x&&(n=o.x),e>o.y&&(e=o.y),o.x>r&&(r=o.x),o.y>u&&(u=o.y);var f=r-n,s=u-e;f>s?u=e+f:r=n+s;var h=Zu();return h.add=function(t){i(h,t,n,e,r,u)},h.visit=function(t){Bu(t,h,n,e,r,u)},t.forEach(h.add),h},qi.time={};var To=Date,qo=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];$u.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getT
ime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){Co.setUTCDate.apply(this._,arguments)},setDay:function(){Co.setUTCDay.apply(this._,arguments)},setFullYear:function(){Co.setUTCFullYear.apply(this._,arguments)},setHours:function(){Co.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){Co.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){Co.setUTCMinutes.apply(this._,arguments)},setMonth:function(){Co.setUTCMonth.apply(this._,arguments)},setSeconds:function(){Co.setUTCSeconds.apply(this._,arguments)},setTime:function(){Co.setTime.apply(this._,arguments)}};var Co=Date.prototype,zo="%a %b %e %X %Y",Do="%m/%d/%Y",Lo="%H:%M:%S",Fo=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],Ho=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],jo=["January","February","March","April","May","June","July","August","September","October","November","December"],Po=["Jan","Feb","Mar","Apr","May"
,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"];qi.time.format=function(t){function n(n){for(var r,u,i,a=[],o=-1,c=0;e>++o;)37===t.charCodeAt(o)&&(a.push(t.substring(c,o)),null!=(u=Xo[r=t.charAt(++o)])&&(r=t.charAt(++o)),(i=Zo[r])&&(r=i(n,null==u?"e"===r?" ":"0":u)),a.push(r),c=o+1);return a.push(t.substring(c,o)),a.join("")}var e=t.length;return n.parse=function(n){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Ju(e,t,n,0);if(r!=n.length)return null;"p"in e&&(e.H=e.H%12+12*e.p);var u=new To;return u.setFullYear(e.y,e.m,e.d),u.setHours(e.H,e.M,e.S,e.L),u},n.toString=function(){return t},n};var Ro=Gu(Fo),Oo=Gu(Ho),Yo=Gu(jo),Uo=Ku(jo),Io=Gu(Po),Vo=Ku(Po),Xo={"-":"",_:" ",0:"0"},Zo={a:function(t){return Ho[t.getDay()]},A:function(t){return Fo[t.getDay()]},b:function(t){return Po[t.getMonth()]},B:function(t){return jo[t.getMonth()]},c:qi.time.format(zo),d:function(t,n){return Wu(t.getDate(),n,2)},e:function(t,n){return Wu(t.getDate(),n,2)},H:function(t,n){return Wu(t.getHours(),n,2)},I:fu
nction(t,n){return Wu(t.getHours()%12||12,n,2)},j:function(t,n){return Wu(1+qi.time.dayOfYear(t),n,3)},L:function(t,n){return Wu(t.getMilliseconds(),n,3)},m:function(t,n){return Wu(t.getMonth()+1,n,2)},M:function(t,n){return Wu(t.getMinutes(),n,2)},p:function(t){return t.getHours()>=12?"PM":"AM"},S:function(t,n){return Wu(t.getSeconds(),n,2)},U:function(t,n){return Wu(qi.time.sundayOfYear(t),n,2)},w:function(t){return t.getDay()},W:function(t,n){return Wu(qi.time.mondayOfYear(t),n,2)},x:qi.time.format(Do),X:qi.time.format(Lo),y:function(t,n){return Wu(t.getFullYear()%100,n,2)},Y:function(t,n){return Wu(t.getFullYear()%1e4,n,4)},Z:mi,"%":function(){return"%"}},Bo={a:Qu,A:ti,b:ni,B:ei,c:ri,d:fi,e:fi,H:si,I:si,L:pi,m:li,M:hi,p:di,S:gi,x:ui,X:ii,y:oi,Y:ai},$o=/^\s*\d+/,Jo=qi.map({am:0,pm:1});qi.time.format.utc=function(t){function n(t){try{To=$u;var n=new To;return n._=t,e(n)}finally{To=Date}}var e=qi.time.format(t);return n.parse=function(t){try{To=$u;var n=e.parse(t);return n&
&n._}finally{To=Date}},n.toString=e.toString,n};var Go=qi.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");qi.time.format.iso=Date.prototype.toISOString?vi:Go,vi.parse=function(t){var n=new Date(t);return isNaN(n)?null:n},vi.toString=Go.toString,qi.time.second=yi(function(t){return new To(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(t.getTime()+1e3*Math.floor(n))},function(t){return t.getSeconds()}),qi.time.seconds=qi.time.second.range,qi.time.seconds.utc=qi.time.second.utc.range,qi.time.minute=yi(function(t){return new To(6e4*Math.floor(t/6e4))},function(t,n){t.setTime(t.getTime()+6e4*Math.floor(n))},function(t){return t.getMinutes()}),qi.time.minutes=qi.time.minute.range,qi.time.minutes.utc=qi.time.minute.utc.range,qi.time.hour=yi(function(t){var n=t.getTimezoneOffset()/60;return new To(36e5*(Math.floor(t/36e5-n)+n))},function(t,n){t.setTime(t.getTime()+36e5*Math.floor(n))},function(t){return t.getHours()}),qi.time.hours=qi.time.hour.range,qi.time.hours.utc=qi.time.hour.utc.ran
ge,qi.time.day=yi(function(t){var n=new To(1970,0);return n.setFullYear(t.getFullYear(),t.getMonth(),t.getDate()),n},function(t,n){t.setDate(t.getDate()+n)},function(t){return t.getDate()-1}),qi.time.days=qi.time.day.range,qi.time.days.utc=qi.time.day.utc.range,qi.time.dayOfYear=function(t){var n=qi.time.year(t);return Math.floor((t-n-6e4*(t.getTimezoneOffset()-n.getTimezoneOffset()))/864e5)},qo.forEach(function(t,n){t=t.toLowerCase(),n=7-n;var e=qi.time[t]=yi(function(t){return(t=qi.time.day(t)).setDate(t.getDate()-(t.getDay()+n)%7),t},function(t,n){t.setDate(t.getDate()+7*Math.floor(n))},function(t){var e=qi.time.year(t).getDay();return Math.floor((qi.time.dayOfYear(t)+(e+n)%7)/7)-(e!==n)});qi.time[t+"s"]=e.range,qi.time[t+"s"].utc=e.utc.range,qi.time[t+"OfYear"]=function(t){var e=qi.time.year(t).getDay();return Math.floor((qi.time.dayOfYear(t)+(e+n)%7)/7)}}),qi.time.week=qi.time.sunday,qi.time.weeks=qi.time.sunday.range,qi.time.weeks.utc=qi.time.sunday.utc.range,qi.time.w
eekOfYear=qi.time.sundayOfYear,qi.time.month=yi(function(t){return t=qi.time.day(t),t.setDate(1),t},function(t,n){t.setMonth(t.getMonth()+n)},function(t){return t.getMonth()}),qi.time.months=qi.time.month.range,qi.time.months.utc=qi.time.month.utc.range,qi.time.year=yi(function(t){return t=qi.time.day(t),t.setMonth(0,1),t},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t){return t.getFullYear()}),qi.time.years=qi.time.year.range,qi.time.years.utc=qi.time.year.utc.range;var Ko=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Wo=[[qi.time.second,1],[qi.time.second,5],[qi.time.second,15],[qi.time.second,30],[qi.time.minute,1],[qi.time.minute,5],[qi.time.minute,15],[qi.time.minute,30],[qi.time.hour,1],[qi.time.hour,3],[qi.time.hour,6],[qi.time.hour,12],[qi.time.day,1],[qi.time.day,2],[qi.time.week,1],[qi.time.month,1],[qi.time.month,3],[qi.time.year,1]],Qo=[[qi.time.format("%Y"),o],[qi.time.format("%B"),function(t){re
turn t.getMonth()}],[qi.time.format("%b %d"),function(t){return 1!=t.getDate()}],[qi.time.format("%a %d"),function(t){return t.getDay()&&1!=t.getDate()}],[qi.time.format("%I %p"),function(t){return t.getHours()}],[qi.time.format("%I:%M"),function(t){return t.getMinutes()}],[qi.time.format(":%S"),function(t){return t.getSeconds()}],[qi.time.format(".%L"),function(t){return t.getMilliseconds()}]],tc=qi.scale.linear(),nc=wi(Qo);Wo.year=function(t,n){return tc.domain(t.map(ki)).ticks(n).map(Si)},qi.time.scale=function(){return bi(qi.scale.linear(),Wo,nc)};var ec=Wo.map(function(t){return[t[0].utc,t[1]]}),rc=[[qi.time.format.utc("%Y"),o],[qi.time.format.utc("%B"),function(t){return t.getUTCMonth()}],[qi.time.format.utc("%b %d"),function(t){return 1!=t.getUTCDate()}],[qi.time.format.utc("%a %d"),function(t){return t.getUTCDay()&&1!=t.getUTCDate()}],[qi.time.format.utc("%I %p"),function(t){return t.getUTCHours()}],[qi.time.format.utc("%I:%M"),function(t){return t.getUTCMinutes()}],
[qi.time.format.utc(":%S"),function(t){return t.getUTCSeconds()}],[qi.time.format.utc(".%L"),function(t){return t.getUTCMilliseconds()}]],uc=wi(rc);return ec.year=function(t,n){return tc.domain(t.map(Ai)).ticks(n).map(Ei)},qi.time.scale.utc=function(){return bi(qi.scale.linear(),ec,uc)},qi}();
\ No newline at end of file
+d3=function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function i(){}function u(){}function a(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function o(){}function c(n){function t(){for(var t,r=e,i=-1,u=r.length;++i<u;)(t=r[i].on)&&t.apply(this,arguments);return n}var e=[],r=new i;return t.on=function(t,i){var u,a=r.get(t);return arguments.length<2?a&&a.on:(a&&(a.on=null,e=e.slice(0,u=e.indexOf(a)).concat(e.slice(u+1)),r.remove(t)),i&&e.push(r.set(t,{on:i})),n)},t}function l(){ua.event.stopPropagation(),ua.event.preventDefault()}function f(){for(var n,t=ua.event;n=t.sourceEvent;)t=n;return t}function s(n,t){function e(){n.on(t,null)}n.on(t,function(){l(),e()},!0),setTimeout(e,0)}function h(n){for(var t=new o,e=0,r=arguments.length;++e<r;)t[arguments[e]]=c(
t);return t.of=function(e,r){return function(i){try{var u=i.sourceEvent=ua.event;i.target=n,ua.event=i,t[i.type].apply(e,r)}finally{ua.event=u}}},t}function g(n,t){var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>pa&&(oa.scrollX||oa.scrollY)){e=ua.select(aa.body).append("svg").style("position","absolute").style("top",0).style("left",0);var i=e[0][0].getScreenCTM();pa=!(i.f||i.e),e.remove()}return pa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var u=n.getBoundingClientRect();return[t.clientX-u.left-n.clientLeft,t.clientY-u.top-n.clientTop]}function p(n){for(var t=-1,e=n.length,r=[];++t<e;)r.push(n[t]);return r}function d(n){return Array.prototype.slice.call(n)}function m(n){return va(n,wa),n}function v(n){return function(){return ya(n,this)}}function y(n){return function(){return Ma(n,this)}}function M(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS
(n.space,n.local)}function i(){this.setAttribute(n,t)}function u(){this.setAttributeNS(n.space,n.local,t)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=ua.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?o:a:n.local?u:i}function x(n){return n.trim().replace(/\s+/g," ")}function b(n){return RegExp("(?:^|\\s+)"+ua.requote(n)+"(?:\\s+|$)","g")}function _(n,t){function e(){for(var e=-1;++e<i;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<i;)n[e](this,r)}n=n.trim().split(/\s+/).map(w);var i=n.length;return"function"==typeof t?r:e}function w(n){var t=b(n);return function(e,r){if(i=e.classList)return r?i.add(n):i.remove(n);var i=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(i)||e.setAttribute("class",x(i+" "+n))):e.setAttribute("class",x(i.replace(t,"
")))}}function S(n,t,e){function r(){this.style.removeProperty(n)}function i(){this.style.setProperty(n,t,e)}function u(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?u:i}function E(n,t){function e(){delete this[n]}function r(){this[n]=t}function i(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?i:r}function k(n){return{__data__:n}}function A(n){return function(){return _a(this,n)}}function N(n){return arguments.length||(n=ua.ascending),function(t,e){return!t-!e||n(t.__data__,e.__data__)}}function q(){}function T(n,t,e){function r(){var t=this[a];t&&(this.removeEventListener(n,t,t.$),delete this[a])}function i(){var i=c(t,da(arguments));r.call(this),this.addEventListener(n,this[a]=i,i.$=e),i._=t}function u(){var t,e=RegExp("^__on([^.]+)"+ua.requote(n)+"$");for(var r in this)if(t=r.match(e)){var i=this[r];this.removeEventListener(t[1
],i,i.$),delete this[r]}}var a="__on"+n,o=n.indexOf("."),c=C;o>0&&(n=n.substring(0,o));var l=ka.get(n);return l&&(n=l,c=z),o?t?i:r:t?q:u}function C(n,t){return function(e){var r=ua.event;ua.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ua.event=r}}}function z(n,t){var e=C(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||r.compareDocumentPosition(t)&8)||e.call(t,n)}}function D(n,t){for(var e=0,r=n.length;r>e;e++)for(var i,u=n[e],a=0,o=u.length;o>a;a++)(i=u[a])&&t(i,a,e);return n}function j(n){return va(n,Aa),n}function L(){}function F(n,t,e){return new H(n,t,e)}function H(n,t,e){this.h=n,this.s=t,this.l=e}function P(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?u+(a-u)*n/60:180>n?a:240>n?u+(a-u)*(240-n)/60:u}function i(n){return Math.round(r(n)*255)}var u,a;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+t):e+t-e*t,u=2*e-a,tt(i(n+120),i(n),i(n-120))}function R(n){return n>0?1:0>n?-1:0}functio
n O(n){return Math.acos(Math.max(-1,Math.min(1,n)))}function Y(n){return n>1?Da/2:-1>n?-Da/2:Math.asin(n)}function U(n){return(Math.exp(n)-Math.exp(-n))/2}function I(n){return(Math.exp(n)+Math.exp(-n))/2}function V(n){return(n=Math.sin(n/2))*n}function X(n,t,e){return new Z(n,t,e)}function Z(n,t,e){this.h=n,this.c=t,this.l=e}function B(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),$(e,Math.cos(n*=La)*t,Math.sin(n)*t)}function $(n,t,e){return new J(n,t,e)}function J(n,t,e){this.l=n,this.a=t,this.b=e}function G(n,t,e){var r=(n+16)/116,i=r+t/500,u=r-e/200;return i=W(i)*Ra,r=W(r)*Oa,u=W(u)*Ya,tt(nt(3.2404542*i-1.5371385*r-.4985314*u),nt(-.969266*i+1.8760108*r+.041556*u),nt(.0556434*i-.2040259*r+1.0572252*u))}function K(n,t,e){return n>0?X(Math.atan2(e,t)*Fa,Math.sqrt(t*t+e*e),n):X(0/0,0/0,n)}function W(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function Q(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function nt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.po
w(n,1/2.4)-.055))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.r=n,this.g=t,this.b=e}function rt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function it(n,t,e){var r,i,u,a=0,o=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(ct(i[0]),ct(i[1]),ct(i[2]))}return(u=Va.get(n))?t(u.r,u.g,u.b):(null!=n&&n.charAt(0)==="#"&&(n.length===4?(a=n.charAt(1),a+=a,o=n.charAt(2),o+=o,c=n.charAt(3),c+=c):n.length===7&&(a=n.substring(1,3),o=n.substring(3,5),c=n.substring(5,7)),a=parseInt(a,16),o=parseInt(o,16),c=parseInt(c,16)),t(a,o,c))}function ut(n,t,e){var r,i,u=Math.min(n/=255,t/=255,e/=255),a=Math.max(n,t,e),o=a-u,c=(a+u)/2;return o?(i=.5>c?o/(a+u):o/(2-a-u),r=n==a?(t-e)/o+(e>t?6:0):t==a?(e-n)/o+2:(n-t)/o+4,r*=60):(r=0/0,i=c>0&&1>c?0:r),F(r,i,c)}function at(n,t,e){n=ot(n),t=ot(t),e=ot(e);var r=Q((.4124564*n+.3575761*t+.18
04375*e)/Ra),i=Q((.2126729*n+.7151522*t+.072175*e)/Oa),u=Q((.0193339*n+.119192*t+.9503041*e)/Ya);return $(116*i-16,500*(r-i),200*(i-u))}function ot(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function ct(n){var t=parseFloat(n);return n.charAt(n.length-1)==="%"?Math.round(2.55*t):t}function lt(n){return"function"==typeof n?n:function(){return n}}function ft(n){return n}function st(n){return function(t,e,r){return arguments.length===2&&"function"==typeof e&&(r=e,e=null),ht(t,e,n,r)}}function ht(n,t,e,r){function i(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(u,c)}catch(r){return a.error.call(u,r),void 0}a.load.call(u,n)}else a.error.call(u,c)}var u={},a=ua.dispatch("progress","load","error"),o={},c=new(oa.XDomainRequest&&/^(http(s)?:)?\/\//.test(n)?XDomainRequest:XMLHttpRequest);return"onload"in c?c.onload=c.onerror=i:c.onreadystatechange=function(){c.readyState>3&&i()},c.onprogress=function(n){var t=ua.event;ua.event=n;try{
a.progress.call(u,c)}finally{ua.event=t}},u.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?o[n]:(null==t?delete o[n]:o[n]=t+"",u)},u.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",u):t},u.response=function(n){return e=n,u},["get","post"].forEach(function(n){u[n]=function(){return u.send.apply(u,[n].concat(da(arguments)))}}),u.send=function(e,r,i){if(arguments.length===2&&"function"==typeof r&&(i=r,r=null),c.open(e,n,!0),null==t||"accept"in o||(o.accept=t+",*/*"),c.setRequestHeader)for(var a in o)c.setRequestHeader(a,o[a]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=i&&u.on("error",i).on("load",function(n){i(null,n)}),c.send(null==r?null:r),u},u.abort=function(){return c.abort(),u},ua.rebind(u,a,"on"),null==r?u:u.get(gt(r))}function gt(n){return n.length===1?function(t,e){n(null==t?e:null)}:n}function pt(n,t){function e(n,e,u){arguments.length<3&&(u=e,e=null);var a=ua.xhr(n,t,u);return a.row=function(n){return argu
ments.length?a.response((e=n)==null?r:i(n)):e},a.row(e)}function r(n){return e.parse(n.responseText)}function i(n){return function(t){return e.parse(t.responseText,n)}}function a(t){return t.map(o).join(n)}function o(n){return c.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var c=RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var i=Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(i(n),e)}:i})},e.parseRows=function(n,t){function e(){if(f>=c)return a;if(i)return i=!1,u;var t=f;if(n.charCodeAt(t)===34){for(var e=t;e++<c;)if(n.charCodeAt(e)===34){if(n.charCodeAt(e+1)!==34)break;++e}f=e+2;var r=n.charCodeAt(e+1);return 13===r?(i=!0,n.charCodeAt(e+2)===10&&++f):10===r&&(i=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;c>f;){var r=n.charCodeAt(f++),o=1;if(10===r)i=!0;else if(13===r)i=!0,n.charCodeAt(f)===10&&(++f,++o);else if(r!==
l)continue;return n.substring(t,f-o)}return n.substring(t)}for(var r,i,u={},a={},o=[],c=n.length,f=0,s=0;(r=e())!==a;){for(var h=[];r!==u&&r!==a;)h.push(r),r=e();(!t||(h=t(h,s++)))&&o.push(h)}return o},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new u,i=[];return t.forEach(function(n){for(var t in n)r.has(t)||i.push(r.add(t))}),[i.map(o).join(n)].concat(t.map(function(t){return i.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(a).join("\n")},e}function dt(){var n=mt(),t=vt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(dt,t)),Ba=0):(Ba=1,Ja(dt))}function mt(){for(var n=Date.now(),t=Xa;t;)n>=t.time&&(t.flush=t.callback(n-t.time)),t=t.next;return n}function vt(){for(var n,t=Xa,e=1/0;t;)t.flush?t=n?n.next=t.next:Xa=t.next:(t.time<e&&(e=t.time),t=(n=t).next);return Za=n,e}function yt(n,t){var e=Math.pow(10,Math.abs(8-t)*3);return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}
function Mt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function xt(n){return n+""}function bt(n,t){n&&uo.hasOwnProperty(n.type)&&uo[n.type](n,t)}function _t(n,t,e){var r,i=-1,u=n.length-e;for(t.lineStart();++i<u;)r=n[i],t.point(r[0],r[1]);t.lineEnd()}function wt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)_t(n[e],t,1);t.polygonEnd()}function St(){function n(n,t){n*=La,t=t*La/2+Da/4;var e=n-r,a=Math.cos(t),o=Math.sin(t),c=u*o,l=i*a+c*Math.cos(e),f=c*Math.sin(e);oo+=Math.atan2(f,l),r=n,i=a,u=o}var t,e,r,i,u;co.point=function(a,o){co.point=n,r=(t=a)*La,i=Math.cos(o=(e=o)*La/2+Da/4),u=Math.sin(o)},co.lineEnd=function(){n(t,e)}}function Et(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function kt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function At(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Nt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function qt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function
Tt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function Ct(n){return[Math.atan2(n[1],n[0]),Math.asin(Math.max(-1,Math.min(1,n[2])))]}function zt(n,t){return Math.abs(n[0]-t[0])<ja&&Math.abs(n[1]-t[1])<ja}function Dt(n,t){if(!lo){++fo,n*=La;var e=Math.cos(t*=La);so+=(e*Math.cos(n)-so)/fo,ho+=(e*Math.sin(n)-ho)/fo,go+=(Math.sin(t)-go)/fo}}function jt(){var n,t;lo=1,Lt(),lo=2;var e=po.point;po.point=function(r,i){e(n=r,t=i)},po.lineEnd=function(){po.point(n,t),Ft(),po.lineEnd=Ft}}function Lt(){function n(n,i){n*=La;var u=Math.cos(i*=La),a=u*Math.cos(n),o=u*Math.sin(n),c=Math.sin(i),l=Math.atan2(Math.sqrt((l=e*c-r*o)*l+(l=r*a-t*c)*l+(l=t*o-e*a)*l),t*a+e*o+r*c);fo+=l,so+=l*(t+(t=a)),ho+=l*(e+(e=o)),go+=l*(r+(r=c))}var t,e,r;lo>1||(1>lo&&(lo=1,fo=so=ho=go=0),po.point=function(i,u){i*=La;var a=Math.cos(u*=La);t=a*Math.cos(i),e=a*Math.sin(i),r=Math.sin(u),po.point=n})}function Ft(){po.point=Dt}function Ht(){return!0}function Pt(n,t,e,r,i){var u=[],a=[];
if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(zt(e,r)){i.lineStart();for(var o=0;t>o;++o)i.point((e=n[o])[0],e[1]);return i.lineEnd(),void 0}var c={point:e,points:n,other:null,visited:!1,entry:!0,subject:!0},l={point:e,points:[e],other:c,visited:!1,entry:!1,subject:!1};c.other=l,u.push(c),a.push(l),c={point:r,points:[r],other:null,visited:!1,entry:!1,subject:!0},l={point:r,points:[r],other:c,visited:!1,entry:!0,subject:!1},c.other=l,u.push(c),a.push(l)}}),a.sort(t),Rt(u),Rt(a),u.length){if(e)for(var o=1,c=!e(a[0].point),l=a.length;l>o;++o)a[o].entry=c=!c;for(var f,s,h,g=u[0];;){for(f=g;f.visited;)if((f=f.next)===g)return;s=f.points,i.lineStart();do{if(f.visited=f.other.visited=!0,f.entry){if(f.subject)for(var o=0;o<s.length;o++)i.point((h=s[o])[0],h[1]);else r(f.point,f.next.point,1,i);f=f.next}else{if(f.subject){s=f.prev.points;for(var o=s.length;--o>=0;)i.point((h=s[o])[0],h[1])}else r(f.point,f.prev.point,-1,i);f=f.prev}f=f.other,s=f.points}whil
e(!f.visited);i.lineEnd()}}}function Rt(n){if(t=n.length){for(var t,e,r=0,i=n[0];++r<t;)i.next=e=n[r],e.prev=i,i=e;i.next=e=n[0],e.prev=i}}function Ot(n,t,e){return function(r){function i(t,e){n(t,e)&&r.point(t,e)}function u(n,t){m.point(n,t)}function a(){v.point=u,m.lineStart()}function o(){v.point=i,m.lineEnd()}function c(n,t){M.point(n,t),d.push([n,t])}function l(){M.lineStart(),d=[]}function f(){c(d[0][0],d[0][1]),M.lineEnd();var n,t=M.clean(),e=y.buffer(),i=e.length;if(!i)return p=!0,g+=It(d,-1),d=null,void 0;if(d=null,1&t){n=e[0],h+=It(n,1);var u,i=n.length-1,a=-1;for(r.lineStart();++a<i;)r.point((u=n[a])[0],u[1]);return r.lineEnd(),void 0}i>1&&2&t&&e.push(e.pop().concat(e.shift())),s.push(e.filter(Yt))}var s,h,g,p,d,m=t(r),v={point:i,lineStart:a,lineEnd:o,polygonStart:function(){v.point=c,v.lineStart=l,v.lineEnd=f,p=!1,g=h=0,s=[],r.polygonStart()},polygonEnd:function(){v.point=i,v.lineStart=a,v.lineEnd=o,s=ua.merge(s),s.length?Pt(s,Vt,null,e,r):(-ja>h||p&&-ja>g)&&(r.l
ineStart(),e(null,null,1,r),r.lineEnd()),r.polygonEnd(),s=null},sphere:function(){r.polygonStart(),r.lineStart(),e(null,null,1,r),r.lineEnd(),r.polygonEnd()}},y=Ut(),M=t(y);return v}}function Yt(n){return n.length>1}function Ut(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:q,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function It(n,t){if(!(e=n.length))return 0;for(var e,r,i,u=0,a=0,o=n[0],c=o[0],l=o[1],f=Math.cos(l),s=Math.atan2(t*Math.sin(c)*f,Math.sin(l)),h=1-t*Math.cos(c)*f,g=s;++u<e;)o=n[u],f=Math.cos(l=o[1]),r=Math.atan2(t*Math.sin(c=o[0])*f,Math.sin(l)),i=1-t*Math.cos(c)*f,Math.abs(h-2)<ja&&Math.abs(i-2)<ja||(Math.abs(i)<ja||Math.abs(h)<ja||(Math.abs(Math.abs(r-s)-Da)<ja?i+h>2&&(a+=4*(r-s)):a+=Math.abs(h-2)<ja?4*(r-g):((3*Da+r-s)%(2*Da)-Da)*(h+i)),g=s,s=r,h=i);return a}function Vt(n,t){return((n=n.point)[0]<0?n[1]-Da/2-ja:Da/2-n[1])-((t=t.point)[0]<
0?t[1]-Da/2-ja:Da/2-t[1])}function Xt(n){var t,e=0/0,r=0/0,i=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(u,a){var o=u>0?Da:-Da,c=Math.abs(u-e);Math.abs(c-Da)<ja?(n.point(e,r=(r+a)/2>0?Da/2:-Da/2),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(o,r),n.point(u,r),t=0):i!==o&&c>=Da&&(Math.abs(e-i)<ja&&(e-=i*ja),Math.abs(u-o)<ja&&(u-=o*ja),r=Zt(e,r,u,a),n.point(i,r),n.lineEnd(),n.lineStart(),n.point(o,r),t=0),n.point(e=u,r=a),i=o},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function Zt(n,t,e,r){var i,u,a=Math.sin(n-e);return Math.abs(a)>ja?Math.atan((Math.sin(t)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(t))*Math.sin(n))/(i*u*a)):(t+r)/2}function Bt(n,t,e,r){var i;if(null==n)i=e*Da/2,r.point(-Da,i),r.point(0,i),r.point(Da,i),r.point(Da,0),r.point(Da,-i),r.point(0,-i),r.point(-Da,-i),r.point(-Da,0),r.point(-Da,i);else if(Math.abs(n[0]-t[0])>ja){var u=(n[0]<t[0]?1:-1)*Da;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.
point(t[0],t[1])}function $t(n){function t(n,t){return Math.cos(n)*Math.cos(t)>u}function e(n){var e,u,c,l,f;return{lineStart:function(){l=c=!1,f=1},point:function(s,h){var g,p=[s,h],d=t(s,h),m=a?d?0:i(s,h):d?i(s+(0>s?Da:-Da),h):0;if(!e&&(l=c=d)&&n.lineStart(),d!==c&&(g=r(e,p),(zt(e,g)||zt(p,g))&&(p[0]+=ja,p[1]+=ja,d=t(p[0],p[1]))),d!==c)f=0,d?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(o&&e&&a^d){var v;m&u||!(v=r(p,e,!0))||(f=0,a?(n.lineStart(),n.point(v[0][0],v[0][1]),n.point(v[1][0],v[1][1]),n.lineEnd()):(n.point(v[1][0],v[1][1]),n.lineEnd(),n.lineStart(),n.point(v[0][0],v[0][1])))}!d||e&&zt(e,p)||n.point(p[0],p[1]),e=p,c=d,u=m},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return f|(l&&c)<<1}}}function r(n,t,e){var r=Et(n),i=Et(t),a=[1,0,0],o=At(r,i),c=kt(o,o),l=o[0],f=c-l*l;if(!f)return!e&&n;var s=u*c/f,h=-u*l/f,g=At(a,o),p=qt(a,s),d=qt(o,h);Nt(p,d);var m=g,v=kt(p,m),y=kt(m,m),M=v*v-y*(kt(p,p)-1);if(!(0>
M)){var x=Math.sqrt(M),b=qt(m,(-v-x)/y);if(Nt(b,p),b=Ct(b),!e)return b;var _,w=n[0],S=t[0],E=n[1],k=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=Math.abs(A-Da)<ja,q=N||ja>A;if(!N&&E>k&&(_=E,E=k,k=_),q?N?E+k>0^b[1]<(Math.abs(b[0]-w)<ja?E:k):E<=b[1]&&b[1]<=k:A>Da^(w<=b[0]&&b[0]<=S)){var T=qt(m,(-v+x)/y);return Nt(T,p),[b,Ct(T)]}}}function i(t,e){var r=a?n:Da-n,i=0;return-r>t?i|=1:t>r&&(i|=2),-r>e?i|=4:e>r&&(i|=8),i}var u=Math.cos(n),a=u>0,o=Math.abs(u)>ja,c=oe(n,6*La);return Ot(t,e,c)}function Jt(n,t,e,r){function i(r,i){return Math.abs(r[0]-n)<ja?i>0?0:3:Math.abs(r[0]-e)<ja?i>0?2:1:Math.abs(r[1]-t)<ja?i>0?1:0:i>0?3:2}function u(n,t){return a(n.point,t.point)}function a(n,t){var e=i(n,1),r=i(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}function o(i,u){var a=u[0]-i[0],o=u[1]-i[1],c=[0,1];return Math.abs(a)<ja&&Math.abs(o)<ja?n<=i[0]&&i[0]<=e&&t<=i[1]&&i[1]<=r:Gt(n-i[0],a,c)&&Gt(i[0]-e,-a,c)&&Gt(t-i[1],o,c)&&Gt(i[1]-r,-o,c)?(c[1]<1&&(u[0]=i[0]+c[1]*a,u[
1]=i[1]+c[1]*o),c[0]>0&&(i[0]+=c[0]*a,i[1]+=c[0]*o),!0):!1}return function(c){function l(u){var a=i(u,-1),o=f([0===a||3===a?n:e,a>1?r:t]);return o}function f(n){for(var t=0,e=M.length,r=n[1],i=0;e>i;++i)for(var u,a=1,o=M[i],c=o.length,l=o[0];c>a;++a)u=o[a],l[1]<=r?u[1]>r&&s(l,u,n)>0&&++t:u[1]<=r&&s(l,u,n)<0&&--t,l=u;return 0!==t}function s(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(e[0]-n[0])*(t[1]-n[1])}function h(u,o,c,l){var f=0,s=0;if(null==u||(f=i(u,c))!==(s=i(o,c))||a(u,o)<0^c>0){do l.point(0===f||3===f?n:e,f>1?r:t);while((f=(f+c+4)%4)!==s)}else l.point(o[0],o[1])}function g(i,u){return i>=n&&e>=i&&u>=t&&r>=u}function p(n,t){g(n,t)&&c.point(n,t)}function d(){T.point=v,M&&M.push(x=[]),A=!0,k=!1,S=E=0/0}function m(){y&&(v(b,_),w&&k&&q.rejoin(),y.push(q.buffer())),T.point=p,k&&c.lineEnd()}function v(n,t){n=Math.max(-vo,Math.min(vo,n)),t=Math.max(-vo,Math.min(vo,t));var e=g(n,t);if(M&&x.push([n,t]),A)b=n,_=t,w=e,A=!1,e&&(c.lineStart(),c.point(n,t));else if(e&&k)c.point(n,t);els
e{var r=[S,E],i=[n,t];o(r,i)?(k||(c.lineStart(),c.point(r[0],r[1])),c.point(i[0],i[1]),e||c.lineEnd()):e&&(c.lineStart(),c.point(n,t))}S=n,E=t,k=e}var y,M,x,b,_,w,S,E,k,A,N=c,q=Ut(),T={point:p,lineStart:d,lineEnd:m,polygonStart:function(){c=q,y=[],M=[]},polygonEnd:function(){c=N,(y=ua.merge(y)).length?(c.polygonStart(),Pt(y,u,l,h,c),c.polygonEnd()):f([n,t])&&(c.polygonStart(),c.lineStart(),h(null,null,1,c),c.lineEnd(),c.polygonEnd()),y=M=x=null}};return T}}function Gt(n,t,e){if(Math.abs(t)<ja)return 0>=n;var r=n/t;if(t>0){if(r>e[1])return!1;r>e[0]&&(e[0]=r)}else{if(r<e[0])return!1;r<e[1]&&(e[1]=r)}return!0}function Kt(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function Wt(n){function t(t){function r(e,r){e=n(e,r),t.point(e[0],e[1])}function u(){f=0/0,d.point=a,t.lineStart()}function a(r,u){var a=Et([r,u]),o=n(r,u);e(f,s,l,h,g,p,f=o[0],s=o[1],l=r,h=a[0],g=a[1],p=a[2],i,
t),t.point(f,s)}function o(){d.point=r,t.lineEnd()}function c(){var n,r,c,m,v,y,M;u(),d.point=function(t,e){a(n=t,r=e),c=f,m=s,v=h,y=g,M=p,d.point=a},d.lineEnd=function(){e(f,s,l,h,g,p,c,m,n,v,y,M,i,t),d.lineEnd=o,o()}}var l,f,s,h,g,p,d={point:r,lineStart:u,lineEnd:o,polygonStart:function(){t.polygonStart(),d.lineStart=c},polygonEnd:function(){t.polygonEnd(),d.lineStart=u}};return d}function e(t,i,u,a,o,c,l,f,s,h,g,p,d,m){var v=l-t,y=f-i,M=v*v+y*y;if(M>4*r&&d--){var x=a+h,b=o+g,_=c+p,w=Math.sqrt(x*x+b*b+_*_),S=Math.asin(_/=w),E=Math.abs(Math.abs(_)-1)<ja?(u+s)/2:Math.atan2(b,x),k=n(E,S),A=k[0],N=k[1],q=A-t,T=N-i,C=y*q-v*T;(C*C/M>r||Math.abs((v*q+y*T)/M-.5)>.3)&&(e(t,i,u,a,o,c,A,N,E,x/=w,b/=w,_,d,m),m.point(A,N),e(A,N,E,x,b,_,l,f,s,h,g,p,d,m))}}var r=.5,i=16;return t.precision=function(n){return arguments.length?(i=(r=n*n)>0&&16,t):Math.sqrt(r)},t}function Qt(n){return ne(function(){return n})()}function ne(n){function t(n){return n=a(n[0]*La,n[1]*La),[n[0]*f+o,c-n[1]*f]}func
tion e(n){return n=a.invert((n[0]-o)/f,(c-n[1])/f),n&&[n[0]*Fa,n[1]*Fa]}function r(){a=Kt(u=re(d,m,v),i);var n=i(g,p);return o=s-n[0]*f,c=h+n[1]*f,t}var i,u,a,o,c,l=Wt(function(n,t){return n=i(n,t),[n[0]*f+o,c-n[1]*f]}),f=150,s=480,h=250,g=0,p=0,d=0,m=0,v=0,y=mo,M=ft,x=null,b=null;return t.stream=function(n){return te(u,y(l(M(n))))},t.clipAngle=function(n){return arguments.length?(y=null==n?(x=n,mo):$t((x=+n)*La),t):x},t.clipExtent=function(n){return arguments.length?(b=n,M=null==n?ft:Jt(n[0][0],n[0][1],n[1][0],n[1][1]),t):b},t.scale=function(n){return arguments.length?(f=+n,r()):f},t.translate=function(n){return arguments.length?(s=+n[0],h=+n[1],r()):[s,h]},t.center=function(n){return arguments.length?(g=n[0]%360*La,p=n[1]%360*La,r()):[g*Fa,p*Fa]},t.rotate=function(n){return arguments.length?(d=n[0]%360*La,m=n[1]%360*La,v=n.length>2?n[2]%360*La:0,r()):[d*Fa,m*Fa,v*Fa]},ua.rebind(t,l,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function
te(n,t){return{point:function(e,r){r=n(e*La,r*La),e=r[0],t.point(e>Da?e-2*Da:-Da>e?e+2*Da:e,r[1])},sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}function ee(n,t){return[n,t]}function re(n,t,e){return n?t||e?Kt(ue(n),ae(t,e)):ue(n):t||e?ae(t,e):ee}function ie(n){return function(t,e){return t+=n,[t>Da?t-2*Da:-Da>t?t+2*Da:t,e]}}function ue(n){var t=ie(n);return t.invert=ie(-n),t}function ae(n,t){function e(n,t){var e=Math.cos(t),o=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),f=l*r+o*i;return[Math.atan2(c*u-f*a,o*r-l*i),Math.asin(Math.max(-1,Math.min(1,f*u+c*a)))]}var r=Math.cos(n),i=Math.sin(n),u=Math.cos(t),a=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),o=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),f=l*u-c*a;return[Math.atan2(c*u+l*a,o*r+f*i),Math.asin(Math.max(-1,Math.min(1,f*r-o*i)))]},e}function oe(n,t){var e=Math.cos(n),r=Math.s
in(n);return function(i,u,a,o){null!=i?(i=ce(e,i),u=ce(e,u),(a>0?u>i:i>u)&&(i+=2*a*Da)):(i=n+2*a*Da,u=n);for(var c,l=a*t,f=i;a>0?f>u:u>f;f-=l)o.point((c=Ct([e,-r*Math.cos(f),-r*Math.sin(f)]))[0],c[1])}}function ce(n,t){var e=Et(t);e[0]-=n,Tt(e);var r=O(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ja)%(2*Math.PI)}function le(n,t,e){var r=ua.range(n,t-ja,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fe(n,t,e){var r=ua.range(n,t-ja,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function se(n){return n.source}function he(n){return n.target}function ge(n,t,e,r){var i=Math.cos(t),u=Math.sin(t),a=Math.cos(r),o=Math.sin(r),c=i*Math.cos(n),l=i*Math.sin(n),f=a*Math.cos(e),s=a*Math.sin(e),h=2*Math.asin(Math.sqrt(V(r-t)+i*a*V(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*f,i=e*l+t*s,a=e*u+t*o;return[Math.atan2(i,r)*Fa,Math.atan2(a,Math.sqrt(r*r+i*i))*Fa]}:function(){return[n*Fa,t*Fa]};return
p.distance=h,p}function pe(){function n(n,i){var u=Math.sin(i*=La),a=Math.cos(i),o=Math.abs((n*=La)-t),c=Math.cos(o);yo+=Math.atan2(Math.sqrt((o=a*Math.sin(o))*o+(o=r*u-e*a*c)*o),e*u+r*a*c),t=n,e=u,r=a}var t,e,r;Mo.point=function(i,u){t=i*La,e=Math.sin(u*=La),r=Math.cos(u),Mo.point=n},Mo.lineEnd=function(){Mo.point=Mo.lineEnd=q}}function de(n){var t=0,e=Da/3,r=ne(n),i=r(t,e);return i.parallels=function(n){return arguments.length?r(t=n[0]*Da/180,e=n[1]*Da/180):[180*(t/Da),180*(e/Da)]},i}function me(n,t){function e(n,t){var e=Math.sqrt(u-2*i*Math.sin(t))/i;return[e*Math.sin(n*=i),a-e*Math.cos(n)]}var r=Math.sin(n),i=(r+Math.sin(t))/2,u=1+r*(2*i-r),a=Math.sqrt(u)/i;return e.invert=function(n,t){var e=a-t;return[Math.atan2(n,e)/i,Y((u-(n*n+e*e)*i*i)/(2*i))]},e}function ve(){function n(n,t){bo+=i*n-r*t,r=n,i=t}var t,e,r,i;ko.point=function(u,a){ko.point=n,t=r=u,e=i=a},ko.lineEnd=function(){n(t,e)}}function ye(n,t){_o>n&&(_o=n),n>So&&(So=n),wo>t&&(wo=t),t>Eo&&(Eo=t)}function Me(){
function n(n,t){a.push("M",n,",",t,u)}function t(n,t){a.push("M",n,",",t),o.point=e}function e(n,t){a.push("L",n,",",t)}function r(){o.point=n}function i(){a.push("Z")}var u=xe(4.5),a=[],o={point:n,lineStart:function(){o.point=t},lineEnd:r,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=r,o.point=n},pointRadius:function(n){return u=xe(n),o},result:function(){if(a.length){var n=a.join("");return a=[],n}}};return o}function xe(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function be(n,t){lo||(so+=n,ho+=t,++go)}function _e(){function n(n,r){var i=n-t,u=r-e,a=Math.sqrt(i*i+u*u);so+=a*(t+n)/2,ho+=a*(e+r)/2,go+=a,t=n,e=r}var t,e;if(1!==lo){if(!(1>lo))return;lo=1,so=ho=go=0}No.point=function(r,i){No.point=n,t=r,e=i}}function we(){No.point=be}function Se(){function n(n,t){var e=i*n-r*t;so+=e*(r+n),ho+=e*(i+t),go+=3*e,r=n,i=t}var t,e,r,i;2>lo&&(lo=2,so=ho=go=0),No.point=function(u,a){No.point=n,t=r=u,e=i=a},No.lineEnd=function(){n
(t,e)}}function Ee(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,a,0,2*Da)}function e(t,e){n.moveTo(t,e),o.point=r}function r(t,e){n.lineTo(t,e)}function i(){o.point=t}function u(){n.closePath()}var a=4.5,o={point:t,lineStart:function(){o.point=e},lineEnd:i,polygonStart:function(){o.lineEnd=u},polygonEnd:function(){o.lineEnd=i,o.point=t},pointRadius:function(n){return a=n,o},result:q};return o}function ke(n){var t=Wt(function(t,e){return n([t*Fa,e*Fa])});return function(n){return n=t(n),{point:function(t,e){n.point(t*La,e*La)},sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}}function Ae(n,t){function e(t,e){var r=Math.cos(t),i=Math.cos(e),u=n(r*i);return[u*i*Math.sin(t),u*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),i=t(r),u=Math.sin(i),a=Math.cos(i);return[Math.atan2(n*u,r*a),Math.asin(r&&e*u/r)]},e}function Ne(n,t){function
e(n,t){var e=Math.abs(Math.abs(t)-Da/2)<ja?0:a/Math.pow(i(t),u);return[e*Math.sin(u*n),a-e*Math.cos(u*n)]}var r=Math.cos(n),i=function(n){return Math.tan(Da/4+n/2)},u=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(i(t)/i(n)),a=r*Math.pow(i(n),u)/u;return u?(e.invert=function(n,t){var e=a-t,r=R(u)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/u,2*Math.atan(Math.pow(a/r,1/u))-Da/2]},e):Te}function qe(n,t){function e(n,t){var e=u-t;return[e*Math.sin(i*n),u-e*Math.cos(i*n)]}var r=Math.cos(n),i=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),u=r/i+n;return Math.abs(i)<ja?ee:(e.invert=function(n,t){var e=u-t;return[Math.atan2(n,e)/i,u-R(i)*Math.sqrt(n*n+e*e)]},e)}function Te(n,t){return[n,Math.log(Math.tan(Da/4+t/2))]}function Ce(n){var t,e=Qt(n),r=e.scale,i=e.translate,u=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=i.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){v
ar a=u.apply(e,arguments);if(a===e){if(t=null==n){var o=Da*r(),c=i();u([[c[0]-o,c[1]-o],[c[0]+o,c[1]+o]])}}else t&&(a=null);return a},e.clipExtent(null)}function ze(n,t){var e=Math.cos(t)*Math.sin(n);return[Math.log((1+e)/(1-e))/2,Math.atan2(Math.tan(t),Math.cos(n))]}function De(n){function t(t){function a(){l.push("M",u(n(f),o))}for(var c,l=[],f=[],s=-1,h=t.length,g=lt(e),p=lt(r);++s<h;)i.call(this,c=t[s],s)?f.push([+g.call(this,c,s),+p.call(this,c,s)]):f.length&&(a(),f=[]);return f.length&&a(),l.length?l.join(""):null}var e=je,r=Le,i=Ht,u=Fe,a=u.key,o=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(i=n,t):i},t.interpolate=function(n){return arguments.length?(a="function"==typeof n?u=n:(u=jo.get(n)||Fe).key,t):a},t.tension=function(n){return arguments.length?(o=n,t):o},t}function je(n){return n[0]}function Le(n){return n[1]}function Fe(n){return n.join("L")}functio
n He(n){return Fe(n)+"Z"}function Pe(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("V",(r=n[t])[1],"H",r[0]);return i.join("")}function Re(n){for(var t=0,e=n.length,r=n[0],i=[r[0],",",r[1]];++t<e;)i.push("H",(r=n[t])[0],"V",r[1]);return i.join("")}function Oe(n,t){return n.length<4?Fe(n):n[1]+Ie(n.slice(1,n.length-1),Ve(n,t))}function Ye(n,t){return n.length<3?Fe(n):n[0]+Ie((n.push(n[0]),n),Ve([n[n.length-2]].concat(n,[n[1]]),t))}function Ue(n,t){return n.length<3?Fe(n):n[0]+Ie(n,Ve(n,t))}function Ie(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return Fe(n);var e=n.length!=t.length,r="",i=n[0],u=n[1],a=t[0],o=a,c=1;if(e&&(r+="Q"+(u[0]-a[0]*2/3)+","+(u[1]-a[1]*2/3)+","+u[0]+","+u[1],i=n[1],c=2),t.length>1){o=t[1],u=n[c],c++,r+="C"+(i[0]+a[0])+","+(i[1]+a[1])+","+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1];for(var l=2;l<t.length;l++,c++)u=n[c],o=t[l],r+="S"+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1]}if(e){var f=n[c];r+="Q"+(u[0]+o[0]*2/3
)+","+(u[1]+o[1]*2/3)+","+f[0]+","+f[1]}return r}function Ve(n,t){for(var e,r=[],i=(1-t)/2,u=n[0],a=n[1],o=1,c=n.length;++o<c;)e=u,u=a,a=n[o],r.push([i*(a[0]-e[0]),i*(a[1]-e[1])]);return r}function Xe(n){if(n.length<3)return Fe(n);var t=1,e=n.length,r=n[0],i=r[0],u=r[1],a=[i,i,i,(r=n[1])[0]],o=[u,u,u,r[1]],c=[i,",",u];for(Ge(c,a,o);++t<e;)r=n[t],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ge(c,a,o);for(t=-1;++t<2;)a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ge(c,a,o);return c.join("")}function Ze(n){if(n.length<4)return Fe(n);for(var t,e=[],r=-1,i=n.length,u=[0],a=[0];++r<3;)t=n[r],u.push(t[0]),a.push(t[1]);for(e.push(Je(Ho,u)+","+Je(Ho,a)),--r;++r<i;)t=n[r],u.shift(),u.push(t[0]),a.shift(),a.push(t[1]),Ge(e,u,a);return e.join("")}function Be(n){for(var t,e,r=-1,i=n.length,u=i+4,a=[],o=[];++r<4;)e=n[r%i],a.push(e[0]),o.push(e[1]);for(t=[Je(Ho,a),",",Je(Ho,o)],--r;++r<u;)e=n[r%i],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Ge(t,a,o);return t.join("")}function $e(n,t){va
r e=n.length-1;if(e)for(var r,i,u=n[0][0],a=n[0][1],o=n[e][0]-u,c=n[e][1]-a,l=-1;++l<=e;)r=n[l],i=l/e,r[0]=t*r[0]+(1-t)*(u+i*o),r[1]=t*r[1]+(1-t)*(a+i*c);return Xe(n)}function Je(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Ge(n,t,e){n.push("C",Je(Lo,t),",",Je(Lo,e),",",Je(Fo,t),",",Je(Fo,e),",",Je(Ho,t),",",Je(Ho,e))}function Ke(n,t){return(t[1]-n[1])/(t[0]-n[0])
+}function We(n){for(var t=0,e=n.length-1,r=[],i=n[0],u=n[1],a=r[0]=Ke(i,u);++t<e;)r[t]=(a+(a=Ke(i=u,u=n[t+1])))/2;return r[t]=a,r}function Qe(n){for(var t,e,r,i,u=[],a=We(n),o=-1,c=n.length-1;++o<c;)t=Ke(n[o],n[o+1]),Math.abs(t)<1e-6?a[o]=a[o+1]=0:(e=a[o]/t,r=a[o+1]/t,i=e*e+r*r,i>9&&(i=3*t/Math.sqrt(i),a[o]=i*e,a[o+1]=i*r));for(o=-1;++o<=c;)i=(n[Math.min(c,o+1)][0]-n[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),u.push([i||0,a[o]*i||0]);return u}function nr(n){return n.length<3?Fe(n):n[0]+Ie(n,Qe(n))}function tr(n,t,e,r){var i,u,a,o,c,l,f;return i=r[n],u=i[0],a=i[1],i=r[t],o=i[0],c=i[1],i=r[e],l=i[0],f=i[1],(f-a)*(o-u)-(c-a)*(l-u)>0}function er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function rr(n,t,e,r){var i=n[0],u=e[0],a=t[0]-i,o=r[0]-u,c=n[1],l=e[1],f=t[1]-c,s=r[1]-l,h=(o*(c-l)-s*(i-u))/(s*a-o*f);return[i+h*a,c+h*f]}function ir(n,t){var e={list:n.map(function(n,t){return{index:t,x:n[0],y:n[1]}}).sort(function(n,t){return n.y<t.y?-1:n.y>t.y?1:n.x<t.x?-1:n.x>
t.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,"l"),r.rightEnd=r.createHalfEdge(null,"l"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(n,t){return{edge:n,side:t,vertex:null,l:null,r:null}},insert:function(n,t){t.l=n,t.r=n.r,n.r.l=t,n.r=t},leftBound:function(n){var t=r.leftEnd;do t=t.r;while(t!=r.rightEnd&&i.rightOf(t,n));return t=t.l},del:function(n){n.l.r=n.r,n.r.l=n.l,n.edge=null},right:function(n){return n.r},left:function(n){return n.l},leftRegion:function(n){return n.edge==null?e.bottomSite:n.edge.region[n.side]},rightRegion:function(n){return n.edge==null?e.bottomSite:n.edge.region[Po[n.side]]}},i={bisect:function(n,t){var e={region:{l:n,r:t},ep:{l:null,r:null}},r=t.x-n.x,i=t.y-n.y,u=r>0?r:-r,a=i>0?i:-i;return e.c=n.x*r+n.y*i+.5*(r*r+i*i),u>a?(e.a=1,e.b=i/r,e.c/=r):(e.b=1,e.a=r/i,e.c/=i),e},intersect:function(n,t){var e=n.edge,r=t.edge;if(!e|
|!r||e.region.r==r.region.r)return null;var i=e.a*r.b-e.b*r.a;if(Math.abs(i)<1e-10)return null;var u,a,o=(e.c*r.b-r.c*e.b)/i,c=(r.c*e.a-e.c*r.a)/i,l=e.region.r,f=r.region.r;l.y<f.y||l.y==f.y&&l.x<f.x?(u=n,a=e):(u=t,a=r);var s=o>=a.region.r.x;return s&&u.side==="l"||!s&&u.side==="r"?null:{x:o,y:c}},rightOf:function(n,t){var e=n.edge,r=e.region.r,i=t.x>r.x;if(i&&n.side==="l")return 1;if(!i&&n.side==="r")return 0;if(e.a===1){var u=t.y-r.y,a=t.x-r.x,o=0,c=0;if(!i&&e.b<0||i&&e.b>=0?c=o=u>=e.b*a:(c=t.x+t.y*e.b>e.c,e.b<0&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-u*u)<l*u*(1+2*a/l+e.b*e.b),e.b<0&&(c=!c)}}else{var f=e.c-e.a*t.x,s=t.y-f,h=t.x-r.x,g=f-r.y;c=s*s>h*h+g*g}return n.side==="l"?c:!c},endPoint:function(n,e,r){n.ep[e]=r,n.ep[Po[e]]&&t(n)},distance:function(n,t){var e=n.x-t.x,r=n.y-t.y;return Math.sqrt(e*e+r*r)}},u={list:[],insert:function(n,t,e){n.vertex=t,n.ystar=t.y+e;for(var r=0,i=u.list,a=i.length;a>r;r++){var o=i[r];if(!(n.ystar>o.ystar||n.ystar==o.ystar&&t.
x>o.vertex.x))break}i.splice(r,0,n)},del:function(n){for(var t=0,e=u.list,r=e.length;r>t&&e[t]!=n;++t);e.splice(t,1)},empty:function(){return u.list.length===0},nextEvent:function(n){for(var t=0,e=u.list,r=e.length;r>t;++t)if(e[t]==n)return e[t+1];return null},min:function(){var n=u.list[0];return{x:n.vertex.x,y:n.ystar}},extractMin:function(){return u.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,f,s,h,g,p,d,m,v,y,M=e.list.shift();;)if(u.empty()||(a=u.min()),M&&(u.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=i.bisect(h,M),s=r.createHalfEdge(v,"l"),r.insert(o,s),d=i.intersect(o,s),d&&(u.del(o),u.insert(o,d,i.distance(d,M))),o=s,s=r.createHalfEdge(v,"r"),r.insert(o,s),d=i.intersect(s,c),d&&u.insert(s,d,i.distance(d,M)),M=e.list.shift();else{if(u.empty())break;o=u.extractMin(),l=r.left(o),c=r.right(o),f=r.right(c),h=r.leftRegion(o),g=r.rightRegion(c),m=o.vertex,i.endPoint(o.edge,o.side,m),i.endPoint(c.edge,c.side
,m),r.del(o),u.del(c),r.del(c),y="l",h.y>g.y&&(p=h,h=g,g=p,y="r"),v=i.bisect(h,g),s=r.createHalfEdge(v,y),r.insert(l,s),i.endPoint(v,Po[y],m),d=i.intersect(l,s),d&&(u.del(l),u.insert(l,d,i.distance(d,h))),d=i.intersect(s,f),d&&u.insert(s,d,i.distance(d,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))t(o.edge)}function ur(n){return n.x}function ar(n){return n.y}function or(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function cr(n,t,e,r,i,u){if(!n(t,e,r,i,u)){var a=.5*(e+i),o=.5*(r+u),c=t.nodes;c[0]&&cr(n,c[0],e,r,a,o),c[1]&&cr(n,c[1],a,r,i,o),c[2]&&cr(n,c[2],e,o,a,u),c[3]&&cr(n,c[3],a,o,i,u)}}function lr(n,t){n=ua.rgb(n),t=ua.rgb(t);var e=n.r,r=n.g,i=n.b,u=t.r-e,a=t.g-r,o=t.b-i;return function(n){return"#"+rt(Math.round(e+u*n))+rt(Math.round(r+a*n))+rt(Math.round(i+o*n))}}function fr(n){var t=[n.a,n.b],e=[n.c,n.d],r=hr(t),i=sr(t,e),u=hr(gr(e,t,-i))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1
]))*Fa,this.translate=[n.e,n.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Fa:0}function sr(n,t){return n[0]*t[0]+n[1]*t[1]}function hr(n){var t=Math.sqrt(sr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function gr(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function pr(n,t){return t-=n=+n,function(e){return n+t*e}}function dr(n,t){var e,r=[],i=[],u=ua.transform(n),a=ua.transform(t),o=u.translate,c=a.translate,l=u.rotate,f=a.rotate,s=u.skew,h=a.skew,g=u.scale,p=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),i.push({i:1,x:pr(o[0],c[0])},{i:3,x:pr(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=f?(l-f>180?f+=360:f-l>180&&(l+=360),i.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:pr(l,f)})):f&&r.push(r.pop()+"rotate("+f+")"),s!=h?i.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:pr(s,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),i.push({i:e-4,x:pr(g[0],p[0])},{i:e-2,x:pr(g[1],p[1]
)})):(p[0]!=1||p[1]!=1)&&r.push(r.pop()+"scale("+p+")"),e=i.length,function(n){for(var t,u=-1;++u<e;)r[(t=i[u]).i]=t.x(n);return r.join("")}}function mr(n,t){var e,r={},i={};for(e in n)e in t?r[e]=Mr(e)(n[e],t[e]):i[e]=n[e];for(e in t)e in n||(i[e]=t[e]);return function(n){for(e in r)i[e]=r[e](n);return i}}function vr(n,t){var e,r,i,u,a,o=0,c=0,l=[],f=[];for(n+="",t+="",Oo.lastIndex=0,r=0;e=Oo.exec(t);++r)e.index&&l.push(t.substring(o,c=e.index)),f.push({i:l.length,x:e[0]}),l.push(null),o=Oo.lastIndex;for(o<t.length&&l.push(t.substring(o)),r=0,u=f.length;(e=Oo.exec(n))&&u>r;++r)if(a=f[r],a.x==e[0]){if(a.i)if(l[a.i+1]==null)for(l[a.i-1]+=a.x,l.splice(a.i,1),i=r+1;u>i;++i)f[i].i--;else for(l[a.i-1]+=a.x+l[a.i+1],l.splice(a.i,2),i=r+1;u>i;++i)f[i].i-=2;else if(l[a.i+1]==null)l[a.i]=a.x;else for(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1),i=r+1;u>i;++i)f[i].i--;f.splice(r,1),u--,r--}else a.x=pr(parseFloat(e[0]),parseFloat(a.x));for(;u>r;)a=f.pop(),l[a.i+1]==null?l[a.i]=a.x:(l[a.i]=a.x
+l[a.i+1],l.splice(a.i+1,1)),u--;return l.length===1?l[0]==null?(a=f[0].x,function(n){return a(n)+""}):function(){return t}:function(n){for(r=0;u>r;++r)l[(a=f[r]).i]=a.x(n);return l.join("")}}function yr(n,t){for(var e,r=ua.interpolators.length;--r>=0&&!(e=ua.interpolators[r](n,t)););return e}function Mr(n){return"transform"==n?dr:yr}function xr(n,t){var e,r=[],i=[],u=n.length,a=t.length,o=Math.min(n.length,t.length);for(e=0;o>e;++e)r.push(yr(n[e],t[e]));for(;u>e;++e)i[e]=n[e];for(;a>e;++e)i[e]=t[e];return function(n){for(e=0;o>e;++e)i[e]=r[e](n);return i}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function Er(n){return n*n*n}function kr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Ar(n){return function(t){return Math.pow(t,n)}}function Nr(n){return 1-Math.cos(n*Da/
2)}function qr(n){return Math.pow(2,10*(n-1))}function Tr(n){return 1-Math.sqrt(1-n*n)}function Cr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/(2*Da)*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,10*-r)*Math.sin(2*(r-e)*Da/t)}}function zr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Dr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function jr(n,t){n=ua.hcl(n),t=ua.hcl(t);var e=n.h,r=n.c,i=n.l,u=t.h-e,a=t.c-r,o=t.l-i;return isNaN(a)&&(a=0,r=isNaN(r)?t.c:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return B(e+u*n,r+a*n,i+o*n)+""}}function Lr(n,t){n=ua.hsl(n),t=ua.hsl(t);var e=n.h,r=n.s,i=n.l,u=t.h-e,a=t.s-r,o=t.l-i;return isNaN(a)&&(a=0,r=isNaN(r)?t.s:r),isNaN(u)?(u=0,e=isNaN(e)?t.h:e):u>180?u-=360:-180>u&&(u+=360),function(n){return P(e+u*n,r+a*n,i+o*n)+""}}function Fr(n,t){n=ua.lab(n),t=ua
.lab(t);var e=n.l,r=n.a,i=n.b,u=t.l-e,a=t.a-r,o=t.b-i;return function(n){return G(e+u*n,r+a*n,i+o*n)+""}}function Hr(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Rr(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Or(n){for(var t=n.source,e=n.target,r=Ur(t,e),i=[t];t!==r;)t=t.parent,i.push(t);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Yr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Ur(n,t){if(n===t)return n;for(var e=Yr(n),r=Yr(t),i=e.pop(),u=r.pop(),a=null;i===u;)a=i,i=e.pop(),u=r.pop();return a}function Ir(n){n.fixed|=2}function Vr(n){n.fixed&=-7}function Xr(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Zr(n){n.fixed&=-5}function Br(n,t,e){var r=0,i=0;if(n.charge=0,!n.leaf)for(var u,a=n.nodes,o=a.length,c=-1;++c<o;)u=a[c],null!=u&&(Br(u,t,e),n.charge+=u.charge,r+=u.charge*u
.cx,i+=u.charge*u.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var l=t*e[n.point.index];n.charge+=n.pointCharge=l,r+=l*n.point.x,i+=l*n.point.y}n.cx=r/n.charge,n.cy=i/n.charge}function $r(n,t){return ua.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wr,n}function Jr(n){return n.children}function Gr(n){return n.value}function Kr(n,t){return t.value-n.value}function Wr(n){return ua.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Qr(n){return n.x}function ni(n){return n.y}function ti(n,t,e){n.y0=t,n.y=e}function ei(n){return ua.range(n.length)}function ri(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ii(n){for(var t,e=1,r=0,i=n[0][1],u=n.length;u>e;++e)(t=n[e][1])>i&&(r=e,i=t);return r}function ui(n){return n.reduce(ai,0)}function ai(n,t){return n+t[1]}function oi(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0
],i=(n[1]-r)/t,u=[];++e<=t;)u[e]=i*e+r;return u}function li(n){return[ua.min(n),ua.max(n)]}function fi(n,t){return n.parent==t.parent?1:2}function si(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function hi(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function gi(n,t){var e=n.children;if(e&&(i=e.length))for(var r,i,u=-1;++u<i;)t(r=gi(e[u],t),n)>0&&(n=r);return n}function pi(n,t){return n.x-t.x}function di(n,t){return t.x-n.x}function mi(n,t){return n.depth-t.depth}function vi(n,t){function e(n,r){var i=n.children;if(i&&(a=i.length))for(var u,a,o=null,c=-1;++c<a;)u=i[c],e(u,o),o=u;t(n,r)}e(n,null)}function yi(n){for(var t,e=0,r=0,i=n.children,u=i.length;--u>=0;)t=i[u]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function Mi(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function xi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function bi(n,t){return
n.value-t.value}function _i(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function wi(n,t){n._pack_next=t,t._pack_prev=n}function Si(n,t){var e=t.x-n.x,r=t.y-n.y,i=n.r+t.r;return i*i-e*e-r*r>.001}function Ei(n){function t(n){f=Math.min(n.x-n.r,f),s=Math.max(n.x+n.r,s),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,i,u,a,o,c,l,f=1/0,s=-1/0,h=1/0,g=-1/0;if(e.forEach(ki),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(i=e[1],i.x=i.r,i.y=0,t(i),l>2))for(u=e[2],qi(r,i,u),t(u),_i(r,u),r._pack_prev=u,_i(u,i),i=r._pack_next,a=3;l>a;a++){qi(r,i,u=e[a]);var p=0,d=1,m=1;for(o=i._pack_next;o!==i;o=o._pack_next,d++)if(Si(o,u)){p=1;break}if(1==p)for(c=r._pack_prev;c!==o._pack_prev&&!Si(c,u);c=c._pack_prev,m++);p?(m>d||d==m&&i.r<r.r?wi(r,i=o):wi(r=c,i),a--):(_i(r,u),i=u,t(u))}var v=(f+s)/2,y=(h+g)/2,M=0;for(a=0;l>a;a++)u=e[a],u.x-=v,u.y-=y,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));n.r=M,e.forEach(Ai)}}function ki(n){n._pack_n
ext=n._pack_prev=n}function Ai(n){delete n._pack_next,delete n._pack_prev}function Ni(n,t,e,r){var i=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,i)for(var u=-1,a=i.length;++u<a;)Ni(i[u],t,e,r)}function qi(n,t,e){var r=n.r+e.r,i=t.x-n.x,u=t.y-n.y;if(r&&(i||u)){var a=t.r+e.r,o=i*i+u*u;a*=a,r*=r;var c=.5+(r-a)/(2*o),l=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=n.x+c*i+l*u,e.y=n.y+c*u-l*i}else e.x=n.x+r,e.y=n.y}function Ti(n){return 1+ua.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function zi(n){var t=n.children;return t&&t.length?zi(t[0]):n}function Di(n){var t,e=n.children;return e&&(t=e.length)?Di(e[t-1]):n}function ji(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Li(n,t){var e=n.x+t[3],r=n.y+t[0],i=n.dx-t[1]-t[3],u=n.dy-t[0]-t[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Fi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Hi(n){return n.rangeExtent?n.rangeEx
tent():Fi(n.range())}function Pi(n,t,e,r){var i=e(n[0],n[1]),u=r(t[0],t[1]);return function(n){return u(i(n))}}function Ri(n,t){var e,r=0,i=n.length-1,u=n[r],a=n[i];return u>a&&(e=r,r=i,i=e,e=u,u=a,a=e),(t=t(a-u))&&(n[r]=t.floor(u),n[i]=t.ceil(a)),n}function Oi(n,t,e,r){var i=[],u=[],a=0,o=Math.min(n.length,t.length)-1;for(n[o]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++a<=o;)i.push(e(n[a-1],n[a])),u.push(r(t[a-1],t[a]));return function(t){var e=ua.bisect(n,t,1,o)-1;return u[e](i[e](t))}}function Yi(n,t,e,r){function i(){var i=Math.min(n.length,t.length)>2?Oi:Pi,c=r?Rr:Pr;return a=i(n,t,c,e),o=i(t,n,c,yr),u}function u(n){return a(n)}var a,o;return u.invert=function(n){return o(n)},u.domain=function(t){return arguments.length?(n=t.map(Number),i()):n},u.range=function(n){return arguments.length?(t=n,i()):t},u.rangeRound=function(n){return u.range(n).interpolate(Hr)},u.clamp=function(n){return arguments.length?(r=n,i()):r},u.interpolate=function(n){return arguments.l
ength?(e=n,i()):e},u.ticks=function(t){return Xi(n,t)},u.tickFormat=function(t,e){return Zi(n,t,e)},u.nice=function(){return Ri(n,Ii),i()},u.copy=function(){return Yi(n,t,e,r)},i()}function Ui(n,t){return ua.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Ii(n){return n=Math.pow(10,Math.round(Math.log(n)/Math.LN10)-1),n&&{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}}function Vi(n,t){var e=Fi(n),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),u=t/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Xi(n,t){return ua.range.apply(ua,Vi(n,t))}function Zi(n,t,e){var r=-Math.floor(Math.log(Vi(n,t)[2])/Math.LN10+.01);return ua.format(e?e.replace(no,function(n,t,e,i,u,a,o,c,l,f){return[t,e,i,u,a,o,c,l||"."+(r-2*("%"===f)),f].join("")}):",."+r+"f")}function Bi(n,t,e,r,i){function u(t){return n(e(t))}function a(){return e===$i?{floor:o,ceil:c}
:{floor:function(n){return-c(-n)},ceil:function(n){return-o(-n)}}}function o(n){return Math.pow(t,Math.floor(Math.log(n)/Math.log(t)))}function c(n){return Math.pow(t,Math.ceil(Math.log(n)/Math.log(t)))}return u.invert=function(t){return r(n.invert(t))},u.domain=function(t){return arguments.length?(t[0]<0?(e=Gi,r=Ki):(e=$i,r=Ji),n.domain((i=t.map(Number)).map(e)),u):i},u.base=function(n){return arguments.length?(t=+n,u):t},u.nice=function(){return n.domain(Ri(i,a).map(e)),u},u.ticks=function(){var i=Fi(n.domain()),u=[];if(i.every(isFinite)){var a=Math.log(t),o=Math.floor(i[0]/a),c=Math.ceil(i[1]/a),l=r(i[0]),f=r(i[1]),s=t%1?2:t;if(e===Gi)for(u.push(-Math.pow(t,-o));o++<c;)for(var h=s-1;h>0;h--)u.push(-Math.pow(t,-o)*h);else{for(;c>o;o++)for(var h=1;s>h;h++)u.push(Math.pow(t,o)*h);u.push(Math.pow(t,o))}for(o=0;u[o]<l;o++);for(c=u.length;u[c-1]>f;c--);u=u.slice(o,c)}return u},u.tickFormat=function(n,i){if(arguments.length<2&&(i=Jo),!arguments.length)return i;var a,o=Math.log(t
),c=Math.max(.1,n/u.ticks().length),l=e===Gi?(a=-1e-12,Math.floor):(a=1e-12,Math.ceil);return function(n){return n/r(o*l(e(n)/o+a))<=c?i(n):""}},u.copy=function(){return Bi(n.copy(),t,e,r,i)},Ui(u,n)}function $i(n){return Math.log(0>n?0:n)}function Ji(n){return Math.exp(n)}function Gi(n){return-Math.log(n>0?0:-n)}function Ki(n){return-Math.exp(-n)}function Wi(n,t,e){function r(t){return n(i(t))}var i=Qi(t),u=Qi(1/t);return r.invert=function(t){return u(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(i)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(){return r.domain(Ri(e,Ii))},r.exponent=function(a){return arguments.length?(i=Qi(t=a),u=Qi(1/t),n.domain(e.map(i)),r):t},r.copy=function(){return Wi(n.copy(),t,e)},Ui(r,n)}function Qi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function nu(n,t){function e(t){return a[((u.get(t)||u.set(t,n.push(t)))-1)%a.length]}
function r(t,e){return ua.range(n.length).map(function(n){return t+e*n})}var u,a,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new i;for(var a,o=-1,c=r.length;++o<c;)u.has(a=r[o])||u.set(a,n.push(a));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(a=n,o=0,t={t:"range",a:arguments},e):a},e.rangePoints=function(i,u){arguments.length<2&&(u=0);var c=i[0],l=i[1],f=(l-c)/(Math.max(1,n.length-1)+u);return a=r(n.length<2?(c+l)/2:c+f*u/2,f),o=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(i,u,c){arguments.length<2&&(u=0),arguments.length<3&&(c=u);var l=i[1]<i[0],f=i[l-0],s=i[1-l],h=(s-f)/(n.length-u+2*c);return a=r(f+h*c,h),l&&a.reverse(),o=h*(1-u),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,u,c){arguments.length<2&&(u=0),arguments.length<3&&(c=u);var l=i[1]<i[0],f=i[l-0],s=i[1-l],h=Math.floor((s-f)/(n.length-u+2*c)),g=s-f-(n.length-u)*h;return a=r(f+Math.round(g/2),h),l&&a.reverse(),o=Math.round(h*(1-u)),t=
{t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return Fi(t.a[0])},e.copy=function(){return nu(n,t)},e.domain(n)}function tu(n,t){function e(){var e=0,u=t.length;for(i=[];++e<u;)i[e-1]=ua.quantile(n,e/u);return r}function r(n){return isNaN(n=+n)?0/0:t[ua.bisect(i,n)]}var i;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(ua.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return i},r.copy=function(){return tu(n,t)},e()}function eu(n,t,e){function r(t){return e[Math.max(0,Math.min(a,Math.floor(u*(t-n))))]}function i(){return u=e.length/(t-n),a=e.length-1,r}var u,a;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],i()):[n,t]},r.range=function(n){return arguments.length?(e=n,i()):e},r.copy=function(){return eu(n,t,e)},i()}function ru(n,t){function e(e){return t[ua.bisect(n,e)]}return e.domain=function(t){r
eturn arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.copy=function(){return ru(n,t)},e}function iu(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return iu(n)},t}function uu(n){return n.innerRadius}function au(n){return n.outerRadius}function ou(n){return n.startAngle}function cu(n){return n.endAngle}function lu(n){for(var t,e,r,i=-1,u=n.length;++i<u;)t=n[i],e=t[0],r=t[1]+nc,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function fu(n){function t(t){function c(){d.push("M",o(n(v),s),f,l(n(m.reverse()),s),"Z")}for(var h,g,p,d=[],m=[],v=[],y=-1,M=t.length,x=lt(e),b=lt(i),_=e===r?function(){return g}:lt(r),w=i===u?function(){return p}:lt(u);++y<M;)a.call(this,h=t[y],y)?(m.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),v.push([+_.call(this,h,y),+w.call(this,h,y)])):m.length&&(
c(),m=[],v=[]);return m.length&&c(),d.length?d.join(""):null}var e=je,r=je,i=0,u=Le,a=Ht,o=Fe,c=o.key,l=o,f="L",s=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(i=u=n,t):u},t.y0=function(n){return arguments.length?(i=n,t):i},t.y1=function(n){return arguments.length?(u=n,t):u},t.defined=function(n){return arguments.length?(a=n,t):a},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?o=n:(o=jo.get(n)||Fe).key,l=o.reverse||o,f=o.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(s=n,t):s},t}function su(n){return n.radius}function hu(n){return[n.x,n.y]}function gu(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+nc;return[e*Math.cos(r),e*Math.sin(r)]}}function pu(){return 64}function du(){return"circle"}function mu(n){var t=Math.sqrt(n/Da);return"M0,"+t+"A"+t+","+t+
" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function vu(n,t){return va(n,ac),n.id=t,n}function yu(n,t,e,r){var i=n.id;return D(n,"function"==typeof e?function(n,u,a){n.__transition__[i].tween.set(t,r(e.call(n,n.__data__,u,a)))}:(e=r(e),function(n){n.__transition__[i].tween.set(t,e)}))}function Mu(n){return null==n&&(n=""),function(){this.textContent=n}}function xu(n,t,e,r){var u=n.__transition__||(n.__transition__={active:0,count:0}),a=u[e];if(!a){var o=r.time;return a=u[e]={tween:new i,event:ua.dispatch("start","end"),time:o,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,ua.timer(function(r){function i(r){return u.active>e?l():(u.active=e,h.start.call(n,f,t),a.tween.forEach(function(e,r){(r=r.call(n,f,t))&&d.push(r)}),c(r)||ua.timer(c,0,o),1)}function c(r){if(u.active!==e)return l();for(var i=(r-g)/p,a=s(i),o=d.length;o>0;)d[--o].call(n,a);return i>=1?(l(),h.end.call(n,f,t),1):void 0}function l(){return--u.count?delete u[e]:delete n.__transition__,1}var f=n.__dat
a__,s=a.ease,h=a.event,g=a.delay,p=a.duration,d=[];return r>=g?i(r):ua.timer(i,g,o),1},0,o),a}}function bu(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function _u(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function wu(n,t,e){if(r=[],e&&t.length>1){for(var r,i,u,a=Fi(n.domain()),o=-1,c=t.length,l=(t[1]-t[0])/++e;++o<c;)for(i=e;--i>0;)(u=+t[o]-i*l)>=a[0]&&r.push(u);for(--o,i=0;++i<e&&(u=+t[o]+i*l)<a[1];)r.push(u)}return r}function Su(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Eu(n,t,e){function r(t){var e=n(t),r=u(e,1);return r-t>t-e?e:r}function i(e){return t(e=n(new gc(e-1)),1),e}function u(n,e){return t(n=new gc(+n),e),n}function a(n,r,u){var a=i(n),o=[];if(u>1)for(;r>a;)e(a)%u||o.push(new Date(+a)),t(a,1);else for(;r>a;)o.push(new Date(+a)),t(a,1);return o}function o(n,t,e){try{gc=Su;var r=new Su;return r._=n,a(r,t,e)}finally{gc=Date}}n.floor=n,n.round=r,n.ceil=i,n.offset=u,n.r
ange=a;var c=n.utc=ku(n);return c.floor=c,c.round=ku(r),c.ceil=ku(i),c.offset=ku(u),c.range=o,n}function ku(n){return function(t,e){try{gc=Su;var r=new Su;return r._=t,n(r,e)._}finally{gc=Date}}}function Au(n,t,e,r){for(var i,u,a=0,o=t.length,c=e.length;o>a;){if(r>=c)return-1;if(i=t.charCodeAt(a++),37===i){if(u=Cc[t.charAt(a++)],!u||(r=u(n,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function Nu(n){return RegExp("^(?:"+n.map(ua.requote).join("|")+")","i")}function qu(n){for(var t=new i,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Tu(n,t,e){n+="";var r=n.length;return e>r?Array(e-r+1).join(t)+n:n}function Cu(n,t,e){Sc.lastIndex=0;var r=Sc.exec(t.substring(e));return r?e+=r[0].length:-1}function zu(n,t,e){wc.lastIndex=0;var r=wc.exec(t.substring(e));return r?e+=r[0].length:-1}function Du(n,t,e){Ac.lastIndex=0;var r=Ac.exec(t.substring(e));return r?(n.m=Nc.get(r[0].toLowerCase()),e+=r[0].length):-1}function ju(n,t,e){Ec.lastIndex=0;var
r=Ec.exec(t.substring(e));return r?(n.m=kc.get(r[0].toLowerCase()),e+=r[0].length):-1}function Lu(n,t,e){return Au(n,""+Tc.c,t,e)}function Fu(n,t,e){return Au(n,""+Tc.x,t,e)}function Hu(n,t,e){return Au(n,""+Tc.X,t,e)}function Pu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+=r[0].length):-1}function Ru(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.y=Ou(+r[0]),e+=r[0].length):-1}function Ou(n){return n+(n>68?1900:2e3)}function Yu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+=r[0].length):-1}function Uu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+=r[0].length):-1}function Iu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+=r[0].length):-1}function Vu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+=r[0].length):-1}function Xu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+2));return r?(n.S=+
r[0],e+=r[0].length):-1}function Zu(n,t,e){zc.lastIndex=0;var r=zc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+=r[0].length):-1}function Bu(n,t,e){var r=Dc.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}function $u(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(Math.abs(t)/60),i=Math.abs(t)%60;return e+Tu(r,"0",2)+Tu(i,"0",2)}function Ju(n){return n.toISOString()}function Gu(n,t,e){function r(t){return n(t)}return r.invert=function(t){return Ku(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Ku)},r.nice=function(n){return r.domain(Ri(r.domain(),function(){return n}))},r.ticks=function(e,i){var u=Fi(r.domain());if("function"!=typeof e){var a=u[1]-u[0],o=a/e,c=ua.bisect(Lc,o);if(c==Lc.length)return t.year(u,e);if(!c)return n.ticks(e).map(Ku);Math.log(o/Lc[c-1])<Math.log(Lc[c]/o)&&--c,e=t[c],i=e[1],e=e[0].range}return e(u[0],new Date(+u[1]+1),i)},r.tickFormat=function(){return e},r.copy=function(){return Gu(n.c
opy(),t,e)},Ui(r,n)}function Ku(n){return new Date(n)}function Wu(n){return function(t){for(var e=n.length-1,r=n[e];!r[1](t);)r=n[--e];return r[0](t)}}function Qu(n){var t=new Date(n,0,1);return t.setFullYear(n),t}function na(n){var t=n.getFullYear(),e=Qu(t),r=Qu(t+1);return t+(n-e)/(r-e)}function ta(n){var t=new Date(Date.UTC(n,0,1));return t.setUTCFullYear(n),t}function ea(n){var t=n.getUTCFullYear(),e=ta(t),r=ta(t+1);return t+(n-e)/(r-e)}function ra(n){return JSON.parse(n.responseText)}function ia(n){var t=aa.createRange();return t.selectNode(aa.body),t.createContextualFragment(n.responseText)}var ua={version:"3.1.10"};Date.now||(Date.now=function(){return+new Date});var aa=document,oa=window;try{aa.createElement("div").style.setProperty("opacity",0,"")}catch(ca){var la=oa.CSSStyleDeclaration.prototype,fa=la.setProperty;la.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ua.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},ua.descending=function(n,t){return n>t?-
1:t>n?1:t>=n?0:0/0},ua.min=function(n,t){var e,r,i=-1,u=n.length;if(arguments.length===1){for(;++i<u&&((e=n[i])==null||e!=e);)e=void 0;for(;++i<u;)(r=n[i])!=null&&e>r&&(e=r)}else{for(;++i<u&&((e=t.call(n,n[i],i))==null||e!=e);)e=void 0;for(;++i<u;)(r=t.call(n,n[i],i))!=null&&e>r&&(e=r)}return e},ua.max=function(n,t){var e,r,i=-1,u=n.length;if(arguments.length===1){for(;++i<u&&((e=n[i])==null||e!=e);)e=void 0;for(;++i<u;)(r=n[i])!=null&&r>e&&(e=r)}else{for(;++i<u&&((e=t.call(n,n[i],i))==null||e!=e);)e=void 0;for(;++i<u;)(r=t.call(n,n[i],i))!=null&&r>e&&(e=r)}return e},ua.extent=function(n,t){var e,r,i,u=-1,a=n.length;if(arguments.length===1){for(;++u<a&&((e=i=n[u])==null||e!=e);)e=i=void 0;for(;++u<a;)(r=n[u])!=null&&(e>r&&(e=r),r>i&&(i=r))}else{for(;++u<a&&((e=i=t.call(n,n[u],u))==null||e!=e);)e=void 0;for(;++u<a;)(r=t.call(n,n[u],u))!=null&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},ua.sum=function(n,t){var e,r=0,i=n.length,u=-1;if(arguments.length===1)for(;++u<i;)isNaN(e=+n[u])|
|(r+=e);else for(;++u<i;)isNaN(e=+t.call(n,n[u],u))||(r+=e);return r},ua.mean=function(t,e){var r,i=t.length,u=0,a=-1,o=0;if(arguments.length===1)for(;++a<i;)n(r=t[a])&&(u+=(r-u)/++o);else for(;++a<i;)n(r=e.call(t,t[a],a))&&(u+=(r-u)/++o);return o?u:void 0},ua.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),i=+n[r-1],u=e-r;return u?i+u*(n[r]-i):i},ua.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?ua.quantile(t.sort(ua.ascending),.5):void 0},ua.bisector=function(n){return{left:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;n.call(t,t[u],u)<e?r=u+1:i=u}return r},right:function(t,e,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=t.length);i>r;){var u=r+i>>>1;e<n.call(t,t[u],u)?i=u:r=u+1}return r}}};var sa=ua.bisector(function(n){return n});ua.bisectLeft=sa.left,ua.bisect=ua.bisectRight=sa.right,ua.shuffle=function(n){for(var t,e,r=n.length;r;)e=Math.random()*r--|0,
t=n[r],n[r]=n[e],n[e]=t;return n},ua.permute=function(n,t){for(var e=[],r=-1,i=t.length;++r<i;)e[r]=n[t[r]];return e},ua.zip=function(){if(!(i=arguments.length))return[];for(var n=-1,e=ua.min(arguments,t),r=Array(e);++n<e;)for(var i,u=-1,a=r[n]=Array(i);++u<i;)a[u]=arguments[u][n];return r},ua.transpose=function(n){return ua.zip.apply(ua,n)},ua.keys=function(n){var t=[];for(var e in n)t.push(e);return t},ua.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},ua.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},ua.merge=function(n){return Array.prototype.concat.apply([],n)},ua.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw Error("infinite range");var i,u=[],a=e(Math.abs(r)),o=-1;if(n*=a,t*=a,r*=a,0>r)for(;(i=n+r*++o)>t;)u.push(i/a);else for(;(i=n+r*++o)<t;)u.push(i/a);return u},ua.map=function(n){var t=new i;for(var e in n)t.set(e,n[e]);return t},r(i,{has:function(n){return ha+n
in this},get:function(n){return this[ha+n]},set:function(n,t){return this[ha+n]=t},remove:function(n){return n=ha+n,n in this&&delete this[n]},keys:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===ga&&n.call(this,t.substring(1),this[t])}});var ha="\0",ga=ha.charCodeAt(0);ua.nest=function(){function n(t,o,c){if(c>=a.length)return r?r.call(u,o):e?o.sort(e):o;for(var l,f,s,h,g=-1,p=o.length,d=a[c++],m=new i;++g<p;)(h=m.get(l=d(f=o[g])))?h.push(f):m.set(l,[f]);return t?(f=t(),s=function(e,r){f.set(e,n(t,r,c))}):(f={},s=function(e,r){f[e]=n(t,r,c)}),m.forEach(s),f}function t(n,e){if(e>=a.length)return n;var r=[],i=o[e++];return n.forEach(function(n,i){r.push({key:n,values:t(i,e)})}),i?r.sort(function(n,t){return i(n.key,t.key)}):r}var e,r,u={
},a=[],o=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(ua.map,e,0),0)},u.key=function(n){return a.push(n),u},u.sortKeys=function(n){return o[a.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},ua.set=function(n){var t=new u;if(n)for(var e=0;e<n.length;e++)t.add(n[e]);return t},r(u,{has:function(n){return ha+n in this
+},add:function(n){return this[ha+n]=!0,n},remove:function(n){return n=ha+n,n in this&&delete this[n]},values:function(){var n=[];return this.forEach(function(t){n.push(t)}),n},forEach:function(n){for(var t in this)t.charCodeAt(0)===ga&&n.call(this,t.substring(1))}}),ua.behavior={},ua.rebind=function(n,t){for(var e,r=1,i=arguments.length;++r<i;)n[e=arguments[r]]=a(n,t,t[e]);return n},ua.dispatch=function(){for(var n=new o,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=c(n);return n},o.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(arguments.length===2){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},ua.event=null,ua.mouse=function(n){return g(n,f())};var pa=/WebKit/.test(oa.navigator.userAgent)?-1:0,da=d;try{da(aa.documentElement.childNodes)[0].nodeType}catch(ma){da=p}var va=[].__proto__?function(n,t){n.__proto__=t}:function(n,t
){for(var e in t)n[e]=t[e]};ua.touches=function(n,t){return arguments.length<2&&(t=f().touches),t?da(t).map(function(t){var e=g(n,t);return e.identifier=t.identifier,e}):[]},ua.behavior.drag=function(){function n(){this.on("mousedown.drag",t).on("touchstart.drag",t)}function t(){function n(){var n=a.parentNode;return null!=f?ua.touches(n).filter(function(n){return n.identifier===f})[0]:ua.mouse(n)}function t(){if(!a.parentNode)return i();var t=n(),e=t[0]-h[0],r=t[1]-h[1];g|=e|r,h=t,l(),o({type:"drag",x:t[0]+u[0],y:t[1]+u[1],dx:e,dy:r})}function i(){o({type:"dragend"}),g&&(l(),ua.event.target===c&&s(p,"click")),p.on(null!=f?"touchmove.drag-"+f:"mousemove.drag",null).on(null!=f?"touchend.drag-"+f:"mouseup.drag",null)}var u,a=this,o=e.of(a,arguments),c=ua.event.target,f=ua.event.touches?ua.event.changedTouches[0].identifier:null,h=n(),g=0,p=ua.select(oa).on(null!=f?"touchmove.drag-"+f:"mousemove.drag",t).on(null!=f?"touchend.drag-"+f:"mouseup.drag",i,!0);r?(u=r.apply(a,argument
s),u=[u.x-h[0],u.y-h[1]]):u=[0,0],null==f&&l(),o({type:"dragstart"})}var e=h(n,"drag","dragstart","dragend"),r=null;return n.origin=function(t){return arguments.length?(r=t,n):r},ua.rebind(n,e,"on")};var ya=function(n,t){return t.querySelector(n)},Ma=function(n,t){return t.querySelectorAll(n)},xa=aa.documentElement,ba=xa.matchesSelector||xa.webkitMatchesSelector||xa.mozMatchesSelector||xa.msMatchesSelector||xa.oMatchesSelector,_a=function(n,t){return ba.call(n,t)};"function"==typeof Sizzle&&(ya=function(n,t){return Sizzle(n,t)[0]||null},Ma=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},_a=Sizzle.matchesSelector),ua.selection=function(){return Na};var wa=ua.selection.prototype=[];wa.select=function(n){var t,e,r,i,u=[];"function"!=typeof n&&(n=v(n));for(var a=-1,o=this.length;++a<o;){u.push(t=[]),t.parentNode=(r=this[a]).parentNode;for(var c=-1,l=r.length;++c<l;)(i=r[c])?(t.push(e=n.call(i,i.__data__,c)),e&&"__data__"in i&&(e.__data__=i.__data__)):t.push(null)}return m(u
)},wa.selectAll=function(n){var t,e,r=[];"function"!=typeof n&&(n=y(n));for(var i=-1,u=this.length;++i<u;)for(var a=this[i],o=-1,c=a.length;++o<c;)(e=a[o])&&(r.push(t=da(n.call(e,e.__data__,o))),t.parentNode=e);return m(r)};var Sa={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};ua.ns={prefix:Sa,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),Sa.hasOwnProperty(e)?{space:Sa[e],local:n}:n}},wa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=ua.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(M(t,n[t]));return this}return this.each(M(n,t))},ua.requote=function(n){return n.replace(Ea,"\\$&")};var Ea=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;wa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){
var e=this.node(),r=(n=n.trim().split(/^|\s+/g)).length,i=-1;if(t=e.classList){for(;++i<r;)if(!t.contains(n[i]))return!1}else for(t=e.getAttribute("class");++i<r;)if(!b(n[i]).test(t))return!1;return!0}for(t in n)this.each(_(t,n[t]));return this}return this.each(_(n,t))},wa.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(S(e,n[e],t));return this}if(2>r)return oa.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(S(n,t,e))},wa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},wa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},wa.html=function(n){return arguments.length?this.each("function"==typ
eof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},wa.append=function(n){function t(){return this.appendChild(aa.createElementNS(this.namespaceURI,n))}function e(){return this.appendChild(aa.createElementNS(n.space,n.local))}return n=ua.ns.qualify(n),this.select(n.local?e:t)},wa.insert=function(n,t){function e(e,r){return this.insertBefore(aa.createElementNS(this.namespaceURI,n),t.call(this,e,r))}function r(e,r){return this.insertBefore(aa.createElementNS(n.space,n.local),t.call(this,e,r))}return n=ua.ns.qualify(n),"function"!=typeof t&&(t=v(t)),this.select(n.local?r:e)},wa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},wa.data=function(n,t){function e(n,e){var r,u,a,o=n.length,s=e.length,h=Math.min(o,s),g=Array(s),p=Array(s),d=Array(o);if(t){var m,v=new i,y=new i,M=[];for(r=-1;++r<o;)m=t.call(u=n[r],u.__data__,r),
v.has(m)?d[r]=u:v.set(m,u),M.push(m);for(r=-1;++r<s;)m=t.call(e,a=e[r],r),(u=v.get(m))?(g[r]=u,u.__data__=a):y.has(m)||(p[r]=k(a)),y.set(m,a),v.remove(m);for(r=-1;++r<o;)v.has(M[r])&&(d[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],a=e[r],u?(u.__data__=a,g[r]=u):p[r]=k(a);for(;s>r;++r)p[r]=k(e[r]);for(;o>r;++r)d[r]=n[r]}p.update=g,p.parentNode=g.parentNode=d.parentNode=n.parentNode,c.push(p),l.push(g),f.push(d)}var r,u,a=-1,o=this.length;if(!arguments.length){for(n=Array(o=(r=this[0]).length);++a<o;)(u=r[a])&&(n[a]=u.__data__);return n}var c=j([]),l=m([]),f=m([]);if("function"==typeof n)for(;++a<o;)e(r=this[a],n.call(r,r.parentNode.__data__,a));else for(;++a<o;)e(r=this[a],n);return l.enter=function(){return c},l.exit=function(){return f},l},wa.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},wa.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=A(n));for(var u=0,a=this.length;a>u;u++){i.push(t=[]),t.parentNode=(e=this[u]).paren
tNode;for(var o=0,c=e.length;c>o;o++)(r=e[o])&&n.call(r,r.__data__,o)&&t.push(r)}return m(i)},wa.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},wa.sort=function(n){n=N.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},wa.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(T(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(T(n,t,e))};var ka=ua.map({mouseenter:"mouseover",mouseleave:"mouseout"});ka.forEach(function(n){"on"+n in aa&&ka.remove(n)}),wa.each=function(n){return D(this,function(t,e,r){n.call(t,t.__data__,e,r)})},wa.call=function(n){var t=da(arguments);return n.apply(t[0]=this,t),this},wa.empty=function(){return!this.node()},wa.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,i=
e.length;i>r;r++){var u=e[r];if(u)return u}return null};var Aa=[];ua.selection.enter=j,ua.selection.enter.prototype=Aa,Aa.append=wa.append,Aa.insert=wa.insert,Aa.empty=wa.empty,Aa.node=wa.node,Aa.select=function(n){for(var t,e,r,i,u,a=[],o=-1,c=this.length;++o<c;){r=(i=this[o]).update,a.push(t=[]),t.parentNode=i.parentNode;for(var l=-1,f=i.length;++l<f;)(u=i[l])?(t.push(r[l]=e=n.call(i.parentNode,u.__data__,l)),e.__data__=u.__data__):t.push(null)}return m(a)},wa.transition=function(){var n,t,e=rc||++oc,r=[],i=Object.create(cc);i.time=Date.now();for(var u=-1,a=this.length;++u<a;){r.push(n=[]);for(var o=this[u],c=-1,l=o.length;++c<l;)(t=o[c])&&xu(t,c,e,i),n.push(t)}return vu(r,e)},ua.select=function(n){var t=["string"==typeof n?ya(n,aa):n];return t.parentNode=xa,m([t])},ua.selectAll=function(n){var t=da("string"==typeof n?Ma(n,aa):n);return t.parentNode=xa,m([t])};var Na=ua.select(xa);ua.behavior.zoom=function(){function n(){this.on("mousedown.zoom",o).on("mousemove.zoom",f).o
n(Ca+".zoom",c).on("dblclick.zoom",g).on("touchstart.zoom",p).on("touchmove.zoom",d).on("touchend.zoom",p)}function t(n){return[(n[0]-w[0])/S,(n[1]-w[1])/S]}function e(n){return[n[0]*S+w[0],n[1]*S+w[1]]}function r(n){S=Math.max(E[0],Math.min(E[1],n))}function i(n,t){t=e(t),w[0]+=n[0]-t[0],w[1]+=n[1]-t[1]}function u(){M&&M.domain(y.range().map(function(n){return(n-w[0])/S}).map(y.invert)),b&&b.domain(x.range().map(function(n){return(n-w[1])/S}).map(x.invert))}function a(n){u(),ua.event.preventDefault(),n({type:"zoom",scale:S,translate:w})}function o(){function n(){c=1,i(ua.mouse(r),h),a(u)}function e(){c&&l(),f.on("mousemove.zoom",null).on("mouseup.zoom",null),c&&ua.event.target===o&&s(f,"click.zoom")}var r=this,u=k.of(r,arguments),o=ua.event.target,c=0,f=ua.select(oa).on("mousemove.zoom",n).on("mouseup.zoom",e),h=t(ua.mouse(r));oa.focus(),l()}function c(){m||(m=t(ua.mouse(this))),r(Math.pow(2,qa()*.002)*S),i(ua.mouse(this),m),a(k.of(this,arguments))}function f(){m=null}funct
ion g(){var n=ua.mouse(this),e=t(n),u=Math.log(S)/Math.LN2;r(Math.pow(2,ua.event.shiftKey?Math.ceil(u)-1:Math.floor(u)+1)),i(n,e),a(k.of(this,arguments))}function p(){var n=ua.touches(this),e=Date.now();if(v=S,m={},n.forEach(function(n){m[n.identifier]=t(n)}),l(),n.length===1){if(500>e-_){var u=n[0],o=t(n[0]);r(2*S),i(u,o),a(k.of(this,arguments))}_=e}}function d(){var n=ua.touches(this),t=n[0],e=m[t.identifier];if(u=n[1]){var u,o=m[u.identifier];t=[(t[0]+u[0])/2,(t[1]+u[1])/2],e=[(e[0]+o[0])/2,(e[1]+o[1])/2],r(ua.event.scale*v)}i(t,e),_=null,a(k.of(this,arguments))}var m,v,y,M,x,b,_,w=[0,0],S=1,E=Ta,k=h(n,"zoom");return n.translate=function(t){return arguments.length?(w=t.map(Number),u(),n):w},n.scale=function(t){return arguments.length?(S=+t,u(),n):S},n.scaleExtent=function(t){return arguments.length?(E=null==t?Ta:t.map(Number),n):E},n.x=function(t){return arguments.length?(M=t,y=t.copy(),w=[0,0],S=1,n):M},n.y=function(t){return arguments.length?(b=t,x=t.copy(),w=[0,0],S=1,
n):b},ua.rebind(n,k,"on")};var qa,Ta=[0,1/0],Ca="onwheel"in aa?(qa=function(){return-ua.event.deltaY*(ua.event.deltaMode?120:1)},"wheel"):"onmousewheel"in aa?(qa=function(){return ua.event.wheelDelta},"mousewheel"):(qa=function(){return-ua.event.detail},"MozMousePixelScroll");L.prototype.toString=function(){return this.rgb()+""},ua.hsl=function(n,t,e){return arguments.length===1?n instanceof H?F(n.h,n.s,n.l):it(""+n,ut,F):F(+n,+t,+e)};var za=H.prototype=new L;za.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),F(this.h,this.s,this.l/n)},za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),F(this.h,this.s,n*this.l)},za.rgb=function(){return P(this.h,this.s,this.l)};var Da=Math.PI,ja=1e-6,La=Da/180,Fa=180/Da;ua.hcl=function(n,t,e){return arguments.length===1?n instanceof Z?X(n.h,n.c,n.l):n instanceof J?K(n.l,n.a,n.b):K((n=at((n=ua.rgb(n)).r,n.g,n.b)).l,n.a,n.b):X(+n,+t,+e)};var Ha=Z.prototype=new L;Ha.brighter=function(n){return X(this.h,this.c,Math.
min(100,this.l+Pa*(arguments.length?n:1)))},Ha.darker=function(n){return X(this.h,this.c,Math.max(0,this.l-Pa*(arguments.length?n:1)))},Ha.rgb=function(){return B(this.h,this.c,this.l).rgb()},ua.lab=function(n,t,e){return arguments.length===1?n instanceof J?$(n.l,n.a,n.b):n instanceof Z?B(n.l,n.c,n.h):at((n=ua.rgb(n)).r,n.g,n.b):$(+n,+t,+e)};var Pa=18,Ra=.95047,Oa=1,Ya=1.08883,Ua=J.prototype=new L;Ua.brighter=function(n){return $(Math.min(100,this.l+Pa*(arguments.length?n:1)),this.a,this.b)},Ua.darker=function(n){return $(Math.max(0,this.l-Pa*(arguments.length?n:1)),this.a,this.b)},Ua.rgb=function(){return G(this.l,this.a,this.b)},ua.rgb=function(n,t,e){return arguments.length===1?n instanceof et?tt(n.r,n.g,n.b):it(""+n,tt,P):tt(~~n,~~t,~~e)};var Ia=et.prototype=new L;Ia.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,i=30;return t||e||r?(t&&i>t&&(t=i),e&&i>e&&(e=i),r&&i>r&&(r=i),tt(Math.min(255,Math.floor(t/n)),Math.min(255,Math.floor
(e/n)),Math.min(255,Math.floor(r/n)))):tt(i,i,i)},Ia.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),tt(Math.floor(n*this.r),Math.floor(n*this.g),Math.floor(n*this.b))},Ia.hsl=function(){return ut(this.r,this.g,this.b)},Ia.toString=function(){return"#"+rt(this.r)+rt(this.g)+rt(this.b)};var Va=ua.map({aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagre
en:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime
:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708
090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"});Va.forEach(function(n,t){Va.set(n,it(t,tt,P))}),ua.functor=lt,ua.xhr=st(ft),ua.csv=pt(",","text/csv"),ua.tsv=pt(" ","text/tab-separated-values");var Xa,Za,Ba,$a;ua.timer=function(n,t,e){if(arguments.length<3){if(arguments.length<2)t=0;else if(!isFinite(t))return;e=Date.now()}var r=e+t,i={callback:n,time:r,next:null};Za?Za.next=i:Xa=i,Za=i,Ba||($a=clearTimeout($a),Ba=1,Ja(dt))},ua.timer.flush=function(){mt(),vt()};var Ja=oa.requestAnimationFrame||oa.webkitRequestAnimationFrame||oa.mozRequestAnimationFrame||oa.oRequestAnimationFrame||oa.msRequestAnimationFrame||function(n){setTimeout(n,17)},Ga=".",Ka=",",Wa=[3,3],Qa=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"].map(yt);ua.formatPre
fix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=ua.round(n,Mt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,Math.floor((0>=e?e+1:e-1)/3)*3))),Qa[8+e/3]},ua.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)},ua.format=function(n){var t=no.exec(n),e=t[1]||" ",r=t[2]||">",i=t[3]||"",u=t[4]||"",a=t[5],o=+t[6],c=t[7],l=t[8],f=t[9],s=1,h="",g=!1;switch(l&&(l=+l.substring(1)),(a||"0"===e&&"="===r)&&(a=e="0",r="=",c&&(o-=Math.floor((o-1)/4))),f){case"n":c=!0,f="g";break;case"%":s=100,h="%",f="f";break;case"p":s=100,h="%",f="r";break;case"b":case"o":case"x":case"X":u&&(u="0"+f.toLowerCase());case"c":case"d":g=!0,l=0;break;case"s":s=-1,f="r"}"#"===u&&(u=""),"r"!=f||l||(f="g"),null!=l&&("g"==f?l=Math.max(1,Math.min(21,l)):("e"==f||"f"==f)&&(l=Math.max(0,Math.min(20,l)))),f=to.get(f)||xt;var p=a&&c;return function(n){if(g&&n%1)return"";var t=0>n||0===n&&0>1/n?(n=-n,"-"):i;if(0>s){var d=ua.formatPrefix(n,l);n=d.scale(n),
h=d.symbol}else n*=s;n=f(n,l),!a&&c&&(n=eo(n));var m=u.length+n.length+(p?0:t.length),v=o>m?Array(m=o-m+1).join(e):"";return p&&(n=eo(v+n)),Ga&&n.replace(".",Ga),t+=u,("<"===r?t+n+v:">"===r?v+t+n:"^"===r?v.substring(0,m>>=1)+t+n+v.substring(m):t+(p?n:v+n))+h}};var no=/(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,to=ua.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=ua.round(n,Mt(n,t))).toFixed(Math.max(0,Math.min(20,Mt(n*(1+1e-15),t))))}}),eo=ft;if(Wa){var ro=Wa.length;eo=function(n){for(var t=n.lastIndexOf("."),e=t>=0?"."+n.substring(t+1):(t=n.length,""),r=[],i=0,u=Wa[0];t>0&&u>0;)r.push(n.substring(t-=u,t+u)),u=Wa[i=(i+1)%ro];return r.reverse().jo
in(Ka||"")+e}}ua.geo={},ua.geo.stream=function(n,t){n&&io.hasOwnProperty(n.type)?io[n.type](n,t):bt(n,t)};var io={Feature:function(n,t){bt(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,i=e.length;++r<i;)bt(e[r].geometry,t)}},uo={Sphere:function(n,t){t.sphere()},Point:function(n,t){var e=n.coordinates;t.point(e[0],e[1])},MultiPoint:function(n,t){for(var e,r=n.coordinates,i=-1,u=r.length;++i<u;)e=r[i],t.point(e[0],e[1])},LineString:function(n,t){_t(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)_t(e[r],t,0)},Polygon:function(n,t){wt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,i=e.length;++r<i;)wt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,i=e.length;++r<i;)bt(e[r],t)}};ua.geo.area=function(n){return ao=0,ua.geo.stream(n,co),ao};var ao,oo,co={sphere:function(){ao+=4*Da},point:q,lineStart:q,lineEnd:q,polygonStart:function(){oo=0,co.lineStart=St},p
olygonEnd:function(){var n=2*oo;ao+=0>n?4*Da+n:n,co.lineStart=co.lineEnd=co.point=q}};ua.geo.bounds=function(){function n(n,t){M.push(x=[f=n,h=n]),s>t&&(s=t),t>g&&(g=t)}function t(t,e){var r=Et([t*La,e*La]);if(v){var i=At(v,r),u=[i[1],-i[0],0],a=At(u,i);Tt(a),a=Ct(a);var c=t-p,l=c>0?1:-1,d=a[0]*Fa*l,m=Math.abs(c)>180;if(m^(d>l*p&&l*t>d)){var y=a[1]*Fa;y>g&&(g=y)}else if(d=(d+360)%360-180,m^(d>l*p&&l*t>d)){var y=-a[1]*Fa;s>y&&(s=y)}else s>e&&(s=e),e>g&&(g=e);m?p>t?o(f,t)>o(f,h)&&(h=t):o(t,h)>o(f,h)&&(f=t):h>=f?(f>t&&(f=t),t>h&&(h=t)):t>p?o(f,t)>o(f,h)&&(h=t):o(t,h)>o(f,h)&&(f=t)}else n(t,e);v=r,p=t}function e(){b.point=t}function r(){x[0]=f,x[1]=h,b.point=n,v=null}function i(n,e){if(v){var r=n-p;y+=Math.abs(r)>180?r+(r>0?360:-360):r}else d=n,m=e;co.point(n,e),t(n,e)}function u(){co.lineStart()}function a(){i(d,m),co.lineEnd(),Math.abs(y)>ja&&(f=-(h=180)),x[0]=f,x[1]=h,v=null}function o(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function l(n,t){return t[0]<=t
[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var f,s,h,g,p,d,m,v,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=i,b.lineStart=u,b.lineEnd=a,y=0,co.polygonStart()},polygonEnd:function(){co.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>oo?(f=-(h=180),s=-(g=90)):y>ja?g=90:-ja>y&&(s=-90),x[0]=f,x[1]=h}};return function(n){g=h=-(f=s=1/0),M=[],ua.geo.stream(n,b),M.sort(c);for(var t,e=1,r=M.length,i=M[0],u=[i];r>e;++e)t=M[e],l(t[0],i)||l(t[1],i)?(o(i[0],t[1])>o(i[0],i[1])&&(i[1]=t[1]),o(t[0],i[1])>o(i[0],i[1])&&(i[0]=t[0])):u.push(i=t);for(var a,t,p=-1/0,r=u.length-1,e=0,i=u[r];r>=e;i=t,++e)t=u[e],(a=o(i[1],t[0]))>p&&(p=a,f=t[0],h=i[1]);return M=x=null,[[f,s],[h,g]]}}(),ua.geo.centroid=function(n){lo=fo=so=ho=go=0,ua.geo.stream(n,po);var t;return fo&&Math.abs(t=Math.sqrt(so*so+ho*ho+go*go))>ja?[Math.atan2(ho,so)*Fa,Math.asin(Math.max(-1,Math.min(1,go/t)))*Fa]:void 0};var lo,fo,so,ho,go,po={sphere:function(){2>lo&&(lo=2,fo=so=ho=go=0)},point:Dt,lineStart:Lt,lineE
nd:Ft,polygonStart:function(){2>lo&&(lo=2,fo=so=ho=go=0),po.lineStart=jt},polygonEnd:function(){po.lineStart=Lt}},mo=Ot(Ht,Xt,Bt),vo=1e9;ua.geo.projection=Qt,ua.geo.projectionMutator=ne,(ua.geo.equirectangular=function(){return Qt(ee)}).raw=ee.invert=ee,ua.geo.rotation=function(n){function t(t){return t=n(t[0]*La,t[1]*La),t[0]*=Fa,t[1]*=Fa,t}return n=re(n[0]%360*La,n[1]*La,n.length>2?n[2]*La:0),t.invert=function(t){return t=n.invert(t[0]*La,t[1]*La),t[0]*=Fa,t[1]*=Fa,t},t},ua.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=re(-n[0]*La,-n[1]*La,0).invert,i=[];return e(null,null,1,{point:function(n,e){i.push(n=t(n,e)),n[0]*=Fa,n[1]*=Fa}}),{type:"Polygon",coordinates:[i]}}var t,e,r=[0,0],i=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=oe((t=+r)*La,i*La),n):t},n.precision=function(r){return arguments.length?(e=oe(t*La,(i=+r)*La),n):i},n.angle(90)},ua.geo.distance=function(
n,t){var e,r=(t[0]-n[0])*La,i=n[1]*La,u=t[1]*La,a=Math.sin(r),o=Math.cos(r),c=Math.sin(i),l=Math.cos(i),f=Math.sin(u),s=Math.cos(u);return Math.atan2(Math.sqrt((e=s*a)*e+(e=l*f-c*s*o)*e),c*f+l*s*o)},ua.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return ua.range(Math.ceil(u/m)*m,i,m).map(h).concat(ua.range(Math.ceil(l/v)*v,c,v).map(g)).concat(ua.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Math.abs(n%m)>ja}).map(f)).concat(ua.range(Math.ceil(o/d)*d,a,d).filter(function(n){return Math.abs(n%v)>ja}).map(s))}var e,r,i,u,a,o,c,l,f,s,h,g,p=10,d=p,m=90,v=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(u).concat(g(c).slice(1),h(i).reverse().slice(1),g(l).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return argum
ents.length?(u=+t[0][0],i=+t[1][0],l=+t[0][1],c=+t[1][1],u>i&&(t=u,u=i,i=t),l>c&&(t=l,l=c,c=t),n.precision(y)):[[u,l],[i,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),n.precision(y)):[[r,o],[e,a]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(m=+t[0],v=+t[1],n):[m,v]},n.minorStep=function(t){return arguments.length?(p=+t[0],d=+t[1],n):[p,d]},n.precision=function(t){return arguments.length?(y=+t,f=le(o,a,90),s=fe(r,e,y),h=le(l,c,90),g=fe(u,i,y),n):y},n.majorExtent([[-180,-90+ja],[180,90-ja]]).minorExtent([[-180,-80-ja],[180,80+ja]])},ua.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||i.apply(this,arguments)]}}var t,e,r=se,i=he;return n.distance=function(){return ua.geo.distance(t||r.apply(this,arguments),e||i.apply(this,arguments))},n.source
=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(i=t,e="function"==typeof t?null:t,n):i},n.precision=function(){return arguments.length?n:0},n},ua.geo.interpolate=function(n,t){return ge(n[0]*La,n[1]*La,t[0]*La,t[1]*La)},ua.geo.length=function(n){return yo=0,ua.geo.stream(n,Mo),yo};var yo,Mo={sphere:q,point:q,lineStart:pe,lineEnd:q,polygonStart:q,polygonEnd:q};(ua.geo.conicEqualArea=function(){return de(me)}).raw=me,ua.geo.albers=function(){return ua.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},ua.geo.albersUsa=function(){function n(n){var u=n[0],a=n[1];return t=null,e(u,a),t||(r(u,a),t)||i(u,a),t}var t,e,r,i,u=ua.geo.albers(),a=ua.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),o=ua.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=u.scale()
,e=u.translate(),r=(n[0]-e[0])/t,i=(n[1]-e[1])/t;return(i>=.12&&.234>i&&r>=-.425&&-.214>r?a:i>=.166&&.234>i&&r>=-.214&&-.115>r?o:u).invert(n)},n.stream=function(n){var t=u.stream(n),e=a.stream(n),r=o.stream(n);return{point:function(n,i){t.point(n,i),e.point(n,i),r.point(n,i)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(u.precision(t),a.precision(t),o.precision(t),n):u.precision()},n.scale=function(t){return arguments.length?(u.scale(t),a.scale(.35*t),o.scale(t),n.translate(u.translate())):u.scale()},n.translate=function(t){if(!arguments.length)return u.translate();var l=u.scale(),f=+t[0],s=+t[1];return e=u.translate(t).clipExtent([[f-.455*l,s-.238*l],[f+.455
*l,s+.238*l]]).stream(c).point,r=a.translate([f-.307*l,s+.201*l]).clipExtent([[f-.425*l+ja,s+.12*l+ja],[f-.214*l-ja,s+.234*l-ja]]).stream(c).point,i=o.translate([f-.205*l,s+.212*l]).clipExtent([[f-.214*l+ja,s+.166*l+ja],[f-.115*l-ja,s+.234*l-ja]]).stream(c).point,n},n.scale(1070)};var xo,bo,_o,wo,So,Eo,ko={point:q,lineStart:q,lineEnd:q,polygonStart:function(){bo=0,ko.lineStart=ve},polygonEnd:function(){ko.lineStart=ko.lineEnd=ko.point=q,xo+=Math.abs(bo/2)}},Ao={point:ye,lineStart:q,lineEnd:q,polygonStart:q,polygonEnd:q},No={point:be,lineStart:_e,lineEnd:we,polygonStart:function(){No.lineStart=Se},polygonEnd:function(){No.point=be,No.lineStart=_e,No.lineEnd=we}};ua.geo.path=function(){function n(n){return n&&ua.geo.stream(n,r(i.pointRadius("function"==typeof u?+u.apply(this,arguments):u))),i.result()}var t,e,r,i,u=4.5;return n.area=function(n){return xo=0,ua.geo.stream(n,r(ko)),xo},n.centroid=function(n){return lo=so=ho=go=0,ua.geo.stream(n,r(No)),go?[so/go,ho/go]:void 0},n.b
ounds=function(n){return So=Eo=-(_o=wo=1/0),ua.geo.stream(n,r(Ao)),[[_o,wo],[So,Eo]]},n.projection=function(e){return arguments.length?(r=(t=e)?e.stream||ke(e):ft,n):t},n.context=function(t){return arguments.length?(i=(e=t)==null?new Me:new Ee(t),n):e},n.pointRadius=function(t){return arguments.length?(u="function"==typeof t?t:+t,n):u},n.projection(ua.geo.albersUsa()).context(null)};var qo=Ae(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(ua.geo.azimuthalEqualArea=function(){return Qt(qo)}).raw=qo;var To=Ae(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},ft);(ua.geo.azimuthalEquidistant=function(){return Qt(To)}).raw=To,(ua.geo.conicConformal=function(){return de(Ne)}).raw=Ne,(ua.geo.conicEquidistant=function(){return de(qe)}).raw=qe;var Co=Ae(function(n){return 1/n},Math.atan);(ua.geo.gnomonic=function(){return Qt(Co)}).raw=Co,Te.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Da/2]},(ua.geo.mercator=function(){return Ce(Te)}).r
aw=Te;var zo=Ae(function(){return 1},Math.asin);(ua.geo.orthographic=function(){return Qt(zo)}).raw=zo;var Do=Ae(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(ua.geo.stereographic=function(){return Qt(Do)}).raw=Do,ze.invert=function(n,t){return[Math.atan2(U(n),Math.cos(t)),Y(Math.sin(t)/I(n))]},(ua.geo.transverseMercator=function(){return Ce(ze)}).raw=ze,ua.geom={},ua.svg={},ua.svg.line=function(){return De(ft)};var jo=ua.map({linear:Fe,"linear-closed":He,"step-before":Pe,"step-after":Re,basis:Xe,"basis-open":Ze,"basis-closed":Be,bundle:$e,cardinal:Ue,"cardinal-open":Oe,"cardinal-closed":Ye,monotone:nr});jo.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Lo=[0,2/3,1/3,0],Fo=[0,1/3,2/3,0],Ho=[0,1/6,2/3,1/6];ua.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,i,u,a,o,c,l,f,s,h,g,p,d=lt(e),m=lt(r),v=n.length,y=v-1,M=[],x=[],b=0;if(d===je&&r===Le)t=n;else for(u=0,t=[];v>u;++u)t.push([+d.call(this,i=n[u],u),+m.call(this,i,u)]);fo
r(u=1;v>u;++u)(t[u][1]<t[b][1]||t[u][1]==t[b][1]&&t[u][0]<t[b][0])&&(b=u);for(u=0;v>u;++u)u!==b&&(c=t[u][1]-t[b][1],o=t[u][0]-t[b][0],M.push({angle:Math.atan2(c,o),index:u}));for(M.sort(function(n,t){return n.angle-t.angle}),g=M[0].angle,h=M[0].index,s=0,u=1;y>u;++u){if(a=M[u].index,g==M[u].angle){if(o=t[h][0]-t[b][0],c=t[h][1]-t[b][1],l=t[a][0]-t[b][0],f=t[a][1]-t[b][1],o*o+c*c>=l*l+f*f){M[u].index=-1;continue}M[s].index=-1}g=M[u].angle,s=u,h=a}for(x.push(b),u=0,a=0;2>u;++a)M[a].index>-1&&(x.push(M[a].index),u++);for(p=x.length;y>a;++a)if(!(M[a].index<0)){for(;!tr(x[p-2],x[p-1],M[a].index,t);)--p;x[p++]=M[a].index}var _=[];for(u=p-1;u>=0;--u)_.push(n[x[u]]);return _}var e=je,r=Le;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},ua.geom.polygon=function(n){return n.area=function(){for(var t=0,e=n.length,r=n[e-1][1]*n[0][0]-n[e-1][0]*n[0][1];++t<e;)r+=n[t-1][1]*n[t][0]-n[t-1][0]*n[t][1];ret
urn.5*r},n.centroid=function(t){var e,r,i=-1,u=n.length,a=0,o=0,c=n[u-1];for(arguments.length||(t=-1/(6*n.area()));++i<u;)e=c,c=n[i],r=e[0]*c[1]-c[0]*e[1],a+=(e[0]+c[0])*r,o+=(e[1]+c[1])*r;return[a*t,o*t]},n.clip=function(t){for(var e,r,i,u,a,o,c=-1,l=n.length,f=n[l-1];++c<l;){for(e=t.slice(),t.length=0,u=n[c],a=e[(i=e.length)-1],r=-1;++r<i;)o=e[r],er(o,f,u)?(er(a,f,u)||t.push(rr(a,o,f,u)),t.push(o)):er(a,f,u)&&t.push(rr(a,o,f,u)),a=o;f=u}return t},n},ua.geom.delaunay=function(n){var t=n.map(function(){return[]}),e=[];return ir(n,function(e){t[e.region.l.index].push(n[e.region.r.index])}),t.forEach(function(t,r){var i=n[r],u=i[0],a=i[1];t.forEach(function(n){n.angle=Math.atan2(n[0]-u,n[1]-a)}),t.sort(function(n,t){return n.angle-t.angle});for(var o=0,c=t.length-1;c>o;o++)e.push([i,t[o],t[o+1]])}),e},ua.geom.voronoi=function(n){function t(n){var t,r,a,o=n.map(function(){return[]}),c=lt(i),l=lt(u),f=n.length,s=1e6;if(c===je&&l===Le)t=n;else for(t=[],a=0;f>a;++a)t.push([+c.call
(this,r=n[a],a),+l.call(this,r,a)]);if(ir(t,function(n){var t,e,r,i,u,a;n.a===1&&n.b>=0?(t=n.ep.r,e=n.ep.l):(t=n.ep.l,e=n.ep.r),n.a===1?(u=t?t.y:-s,r=n.c-n.b*u,a=e?e.y:s,i=n.c-n.b*a):(r=t?t.x:-s,u=n.c-n.a*r,i=e?e.x:s,a=n.c-n.a*i);var c=[r,u],l=[i,a];o[n.region.l.index].push(c,l),o[n.region.r.index].push(c,l)}),o=o.map(function(n,e){var r=t[e][0],i=t[e][1],u=n.map(function(n){return Math.atan2(n[0]-r,n[1]-i)
+}),a=ua.range(n.length).sort(function(n,t){return u[n]-u[t]});return a.filter(function(n,t){return!t||u[n]-u[a[t-1]]>ja}).map(function(t){return n[t]})}),o.forEach(function(n,e){var r=n.length;if(!r)return n.push([-s,-s],[-s,s],[s,s],[s,-s]);if(!(r>2)){var i=t[e],u=n[0],a=n[1],o=i[0],c=i[1],l=u[0],f=u[1],h=a[0],g=a[1],p=Math.abs(h-l),d=g-f;if(Math.abs(d)<ja){var m=f>c?-s:s;n.push([-s,m],[s,m])}else if(ja>p){var v=l>o?-s:s;n.push([v,-s],[v,s])}else{var m=(l-o)*(g-f)>(h-l)*(f-c)?s:-s,y=Math.abs(d)-p;Math.abs(y)<ja?n.push([0>d?m:-m,m]):(y>0&&(m*=-1),n.push([-s,m],[s,m]))}}}),e)for(a=0;f>a;++a)e(o[a]);for(a=0;f>a;++a)o[a].point=n[a];return o}var e,r=null,i=je,u=Le;return arguments.length?t(n):(t.x=function(n){return arguments.length?(i=n,t):i},t.y=function(n){return arguments.length?(u=n,t):u},t.size=function(n){return arguments.length?(null==n?e=null:(r=[+n[0],+n[1]],e=ua.geom.polygon([[0,0],[0,r[1]],r,[r[0],0]]).clip),t):r},t.links=function(n){var t,e,r,a=n.map(function(){retu
rn[]}),o=[],c=lt(i),l=lt(u),f=n.length;if(c===je&&l===Le)t=n;else for(r=0;f>r;++r)t.push([+c.call(this,e=n[r],r),+l.call(this,e,r)]);return ir(t,function(t){var e=t.region.l.index,r=t.region.r.index;a[e][r]||(a[e][r]=a[r][e]=!0,o.push({source:n[e],target:n[r]}))}),o},t.triangles=function(n){if(i===je&&u===Le)return ua.geom.delaunay(n);var t,e,r,a,o,c=lt(i),l=lt(u);for(a=0,t=[],o=n.length;o>a;++a)e=[+c.call(this,r=n[a],a),+l.call(this,r,a)],e.data=r,t.push(e);return ua.geom.delaunay(t).map(function(n){return n.map(function(n){return n.data})})},t)};var Po={l:"r",r:"l"};ua.geom.quadtree=function(n,t,e,r,i){function u(n){function u(n,t,e,r,i,u,a,o){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,f=n.y;if(null!=c)if(Math.abs(c-e)+Math.abs(f-r)<.01)l(n,t,e,r,i,u,a,o);else{var s=n.point;n.x=n.y=n.point=null,l(n,s,c,f,i,u,a,o),l(n,t,e,r,i,u,a,o)}else n.x=e,n.y=r,n.point=t}else l(n,t,e,r,i,u,a,o)}function l(n,t,e,r,i,a,o,c){var l=.5*(i+o),f=.5*(a+c),s=e>=l,h=r>=f,g=(h<<1)+s;n.leaf=!1,n
=n.nodes[g]||(n.nodes[g]=or()),s?i=l:o=l,h?a=f:c=f,u(n,t,e,r,i,a,o,c)}var f,s,h,g,p,d,m,v,y,M=lt(o),x=lt(c);if(null!=t)d=t,m=e,v=r,y=i;else if(v=y=-(d=m=1/0),s=[],h=[],p=n.length,a)for(g=0;p>g;++g)f=n[g],f.x<d&&(d=f.x),f.y<m&&(m=f.y),f.x>v&&(v=f.x),f.y>y&&(y=f.y),s.push(f.x),h.push(f.y);else for(g=0;p>g;++g){var b=+M(f=n[g],g),_=+x(f,g);d>b&&(d=b),m>_&&(m=_),b>v&&(v=b),_>y&&(y=_),s.push(b),h.push(_)}var w=v-d,S=y-m;w>S?y=m+w:v=d+S;var E=or();if(E.add=function(n){u(E,n,+M(n,++g),+x(n,g),d,m,v,y)},E.visit=function(n){cr(n,E,d,m,v,y)},g=-1,null==t){for(;++g<p;)u(E,n[g],s[g],h[g],d,m,v,y);--g}else n.forEach(E.add);return s=h=n=f=null,E}var a,o=je,c=Le;return(a=arguments.length)?(o=ur,c=ar,3===a&&(i=e,r=t,e=t=0),u(n)):(u.x=function(n){return arguments.length?(o=n,u):o},u.y=function(n){return arguments.length?(c=n,u):c},u.size=function(n){return arguments.length?(null==n?t=e=r=i=null:(t=e=0,r=+n[0],i=+n[1]),u):null==t?null:[r,i]},u)},ua.interpolateRgb=lr,ua.transform=function(n){v
ar t=aa.createElementNS(ua.ns.prefix.svg,"g");return(ua.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new fr(e?e.matrix:Ro)})(n)},fr.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var Ro={a:1,b:0,c:0,d:1,e:0,f:0};ua.interpolateNumber=pr,ua.interpolateTransform=dr,ua.interpolateObject=mr,ua.interpolateString=vr;var Oo=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;ua.interpolate=yr,ua.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?lr:vr:t instanceof L?lr:"object"===e?Array.isArray(t)?xr:mr:pr)(n,t)}],ua.interpolateArray=xr;var Yo=function(){return ft},Uo=ua.map({linear:Yo,poly:Ar,quad:function(){return Sr},cubic:function(){return Er},sin:function(){return Nr},exp:function(){return qr},circle:function(){return Tr},elastic:Cr,back:zr,bounce:function(){return Dr}}),Io=ua.map({"
in":ft,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});ua.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=Uo.get(e)||Yo,r=Io.get(r)||ft,br(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},ua.interpolateHcl=jr,ua.interpolateHsl=Lr,ua.interpolateLab=Fr,ua.interpolateRound=Hr,ua.layout={},ua.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Or(n[e]));return t}},ua.layout.chord=function(){function n(){var n,l,s,h,g,p={},d=[],m=ua.range(u),v=[];for(e=[],r=[],n=0,h=-1;++h<u;){for(l=0,g=-1;++g<u;)l+=i[h][g];d.push(l),v.push(ua.range(u)),n+=l}for(a&&m.sort(function(n,t){return a(d[n],d[t])}),o&&v.forEach(function(n,t){n.sort(function(n,e){return o(i[t][n],i[t][e])})}),n=(2*Da-f*u)/n,l=0,h=-1;++h<u;){for(s=l,g=-1;++g<u;){var y=m[h],M=v[y][g],x=i[y][M],b=l,_=l+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:s,endAngle:l,value:(l
-s)/n},l+=f}for(h=-1;++h<u;)for(g=h-1;++g<u;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,i,u,a,o,c,l={},f=0;return l.matrix=function(n){return arguments.length?(u=(i=n)&&i.length,e=r=null,l):i},l.padding=function(n){return arguments.length?(f=n,e=r=null,l):f},l.sortGroups=function(n){return arguments.length?(a=n,e=r=null,l):a},l.sortSubgroups=function(n){return arguments.length?(o=n,e=null,l):o},l.sortChords=function(n){return arguments.length?(c=n,e&&t(),l):c},l.chords=function(){return e||n(),e},l.groups=function(){return r||n(),r},l},ua.layout.force=function(){function n(n){return function(t,e,r,i){if(t.point!==n){var u=t.cx-n.x,a=t.cy-n.y,o=1/Math.sqrt(u*u+a*a);if(d>(i-e)*o){var c=t.charge*o*o;return n.px-=u*c,n.py-=a*c,!0}if(t.point&&isFinite(o)){var c=t.pointCharge*o*o;n.p
x-=u*c,n.py-=a*c}}return!t.charge}}function t(n){n.px=ua.event.x,n.py=ua.event.y,o.resume()}var e,r,i,u,a,o={},c=ua.dispatch("start","tick","end"),l=[1,1],f=.9,s=Vo,h=Xo,g=-30,p=.1,d=.8,m=[],v=[];return o.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,o,s,h,d,y,M,x,b=m.length,_=v.length;for(e=0;_>e;++e)o=v[e],s=o.source,h=o.target,M=h.x-s.x,x=h.y-s.y,(d=M*M+x*x)&&(d=r*u[e]*((d=Math.sqrt(d))-i[e])/d,M*=d,x*=d,h.x-=M*(y=s.weight/(h.weight+s.weight)),h.y-=x*y,s.x+=M*(y=1-y),s.y+=x*y);if((y=r*p)&&(M=l[0]/2,x=l[1]/2,e=-1,y))for(;++e<b;)o=m[e],o.x+=(M-o.x)*y,o.y+=(x-o.y)*y;if(g)for(Br(t=ua.geom.quadtree(m),r,a),e=-1;++e<b;)(o=m[e]).fixed||t.visit(n(o));for(e=-1;++e<b;)o=m[e],o.fixed?(o.x=o.px,o.y=o.py):(o.x-=(o.px-(o.px=o.x))*f,o.y-=(o.py-(o.py=o.y))*f);c.tick({type:"tick",alpha:r})},o.nodes=function(n){return arguments.length?(m=n,o):m},o.links=function(n){return arguments.length?(v=n,o):v},o.size=function(n){return arguments.length?(l=n,o):l},o.
linkDistance=function(n){return arguments.length?(s="function"==typeof n?n:+n,o):s},o.distance=o.linkDistance,o.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,o):h},o.friction=function(n){return arguments.length?(f=+n,o):f},o.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,o):g},o.gravity=function(n){return arguments.length?(p=+n,o):p},o.theta=function(n){return arguments.length?(d=+n,o):d},o.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),ua.timer(o.tick)),o):r},o.start=function(){function n(n,r){for(var i,u=t(e),a=-1,o=u.length;++a<o;)if(!isNaN(i=u[a][n]))return i;return Math.random()*r}function t(){if(!c){for(c=[],r=0;p>r;++r)c[r]=[];for(r=0;d>r;++r){var n=v[r];c[n.source.index].push(n.target),c[n.target.index].push(n.source)}}return c[e]}var e,r,c,f,p=m.length,d=v.length,y=l[0],M=l[1];for(e=0;p>e;++e)(f=m[e]).index=e,f.weight=0;for(e=0;d>e;++e)f=v[e],typeof f.source
=="number"&&(f.source=m[f.source]),typeof f.target=="number"&&(f.target=m[f.target]),++f.source.weight,++f.target.weight;for(e=0;p>e;++e)f=m[e],isNaN(f.x)&&(f.x=n("x",y)),isNaN(f.y)&&(f.y=n("y",M)),isNaN(f.px)&&(f.px=f.x),isNaN(f.py)&&(f.py=f.y);if(i=[],"function"==typeof s)for(e=0;d>e;++e)i[e]=+s.call(this,v[e],e);else for(e=0;d>e;++e)i[e]=s;if(u=[],"function"==typeof h)for(e=0;d>e;++e)u[e]=+h.call(this,v[e],e);else for(e=0;d>e;++e)u[e]=h;if(a=[],"function"==typeof g)for(e=0;p>e;++e)a[e]=+g.call(this,m[e],e);else for(e=0;p>e;++e)a[e]=g;return o.resume()},o.resume=function(){return o.alpha(.1)},o.stop=function(){return o.alpha(0)},o.drag=function(){return e||(e=ua.behavior.drag().origin(ft).on("dragstart.force",Ir).on("drag.force",t).on("dragend.force",Vr)),arguments.length?(this.on("mouseover.force",Xr).on("mouseout.force",Zr).call(e),void 0):e},ua.rebind(o,c,"on")};var Vo=20,Xo=1;ua.layout.hierarchy=function(){function n(t,a,o){var c=i.call(e,t,a);if(t.depth=a,o.push(t),c&
&(l=c.length)){for(var l,f,s=-1,h=t.children=[],g=0,p=a+1;++s<l;)f=n(c[s],p,o),f.parent=t,h.push(f),g+=f.value;r&&h.sort(r),u&&(t.value=g)}else u&&(t.value=+u.call(e,t,a)||0);return t}function t(n,r){var i=n.children,a=0;if(i&&(o=i.length))for(var o,c=-1,l=r+1;++c<o;)a+=t(i[c],l);else u&&(a=+u.call(e,n,r)||0);return u&&(n.value=a),a}function e(t){var e=[];return n(t,0,e),e}var r=Kr,i=Jr,u=Gr;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(i=n,e):i},e.value=function(n){return arguments.length?(u=n,e):u},e.revalue=function(n){return t(n,0),n},e},ua.layout.partition=function(){function n(t,e,r,i){var u=t.children;if(t.x=e,t.y=t.depth*i,t.dx=r,t.dy=i,u&&(a=u.length)){var a,o,c,l=-1;for(r=t.value?r/t.value:0;++l<a;)n(o=u[l],e,c=o.value*r,i),e+=c}}function t(n){var e=n.children,r=0;if(e&&(i=e.length))for(var i,u=-1;++u<i;)r=Math.max(r,t(e[u]));return 1+r}function e(e,u){var a=r.call(this,e,u);return n(a[0],0,i[0],i[1]/t(
a[0])),a}var r=ua.layout.hierarchy(),i=[1,1];return e.size=function(n){return arguments.length?(i=n,e):i},$r(e,r)},ua.layout.pie=function(){function n(u){var a=u.map(function(e,r){return+t.call(n,e,r)}),o=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof i?i.apply(this,arguments):i)-o)/ua.sum(a),l=ua.range(u.length);null!=e&&l.sort(e===Zo?function(n,t){return a[t]-a[n]}:function(n,t){return e(u[n],u[t])});var f=[];return l.forEach(function(n){var t;f[n]={data:u[n],value:t=a[n],startAngle:o,endAngle:o+=t*c}}),f}var t=Number,e=Zo,r=0,i=2*Da;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(i=t,n):i},n};var Zo={};ua.layout.stack=function(){function n(o,c){var l=o.map(function(e,r){return t.call(n,e,r)}),f=l.map(function(t){return t.map(function(t,e){return[u.call(n,t,e),a.call(n,t,e)]
})}),s=e.call(n,f,c);l=ua.permute(l,s),f=ua.permute(f,s);var h,g,p,d=r.call(n,f,c),m=l.length,v=l[0].length;for(g=0;v>g;++g)for(i.call(n,l[0][g],p=d[g],f[0][g][1]),h=1;m>h;++h)i.call(n,l[h][g],p+=f[h-1][g][1],f[h][g][1]);return o}var t=ft,e=ei,r=ri,i=ti,u=Qr,a=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:Bo.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:$o.get(t)||ri,n):r},n.x=function(t){return arguments.length?(u=t,n):u},n.y=function(t){return arguments.length?(a=t,n):a},n.out=function(t){return arguments.length?(i=t,n):i},n};var Bo=ua.map({"inside-out":function(n){var t,e,r=n.length,i=n.map(ii),u=n.map(ui),a=ua.range(r).sort(function(n,t){return i[n]-i[t]}),o=0,c=0,l=[],f=[];for(t=0;r>t;++t)e=a[t],c>o?(o+=u[e],l.push(e)):(c+=u[e],f.push(e));return f.reverse().concat(l)},reverse:function(n){return ua.range(n.length).reverse()},"default":ei}),$
o=ua.map({silhouette:function(n){var t,e,r,i=n.length,u=n[0].length,a=[],o=0,c=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];r>o&&(o=r),a.push(r)}for(e=0;u>e;++e)c[e]=(o-a[e])/2;return c},wiggle:function(n){var t,e,r,i,u,a,o,c,l,f=n.length,s=n[0],h=s.length,g=[];for(g[0]=c=l=0,e=1;h>e;++e){for(t=0,i=0;f>t;++t)i+=n[t][e][1];for(t=0,u=0,o=s[e][0]-s[e-1][0];f>t;++t){for(r=0,a=(n[t][e][1]-n[t][e-1][1])/(2*o);t>r;++r)a+=(n[r][e][1]-n[r][e-1][1])/o;u+=a*n[t][e][1]}g[e]=c-=i?u/i*o:0,l>c&&(l=c)}for(e=0;h>e;++e)g[e]-=l;return g},expand:function(n){var t,e,r,i=n.length,u=n[0].length,a=1/i,o=[];for(e=0;u>e;++e){for(t=0,r=0;i>t;t++)r+=n[t][e][1];if(r)for(t=0;i>t;t++)n[t][e][1]/=r;else for(t=0;i>t;t++)n[t][e][1]=a}for(e=0;u>e;++e)o[e]=0;return o},zero:ri});ua.layout.histogram=function(){function n(n,u){for(var a,o,c=[],l=n.map(e,this),f=r.call(this,l,u),s=i.call(this,f,l,u),u=-1,h=l.length,g=s.length-1,p=t?1:1/h;++u<g;)a=c[u]=[],a.dx=s[u+1]-(a.x=s[u]),a.y=0;if(g>0)for(u=-1;++u<h;
)o=l[u],o>=f[0]&&o<=f[1]&&(a=c[ua.bisect(s,o,1,g)-1],a.y+=p,a.push(n[u]));return c}var t=!0,e=Number,r=li,i=oi;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=lt(t),n):r},n.bins=function(t){return arguments.length?(i="number"==typeof t?function(n){return ci(n,t)}:lt(t),n):i},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},ua.layout.tree=function(){function n(n,i){function u(n,t){var r=n.children,i=n._tree;if(r&&(a=r.length)){for(var a,c,l,f=r[0],s=f,h=-1;++h<a;)l=r[h],u(l,c),s=o(l,c,s),c=l;yi(n);var g=.5*(f._tree.prelim+l._tree.prelim);t?(i.prelim=t._tree.prelim+e(n,t),i.mod=i.prelim-g):i.prelim=g}else t&&(i.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,i=-1;for(t+=n._tree.mod;++i<r;)a(e[i],t)}}function o(n,t,r){if(t){for(var i,u=n,a=n,o=t,c=n.parent.children[0],l=u._tree.mod,f=a._tree.mod,s=o._tree.mod,h=c._tree.mod;o=hi(o),u=si(u),o&&
u;)c=si(c),a=hi(a),a._tree.ancestor=n,i=o._tree.prelim+s-u._tree.prelim-l+e(o,u),i>0&&(Mi(xi(o,n,r),n,i),l+=i,f+=i),s+=o._tree.mod,l+=u._tree.mod,h+=c._tree.mod,f+=a._tree.mod;o&&!hi(a)&&(a._tree.thread=o,a._tree.mod+=s-f),u&&!si(c)&&(c._tree.thread=u,c._tree.mod+=l-h,r=n)}return r}var c=t.call(this,n,i),l=c[0];vi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),u(l),a(l,-l._tree.prelim);var f=gi(l,di),s=gi(l,pi),h=gi(l,mi),g=f.x-e(f,s)/2,p=s.x+e(s,f)/2,d=h.depth||1;return vi(l,function(n){n.x=(n.x-g)/(p-g)*r[0],n.y=n.depth/d*r[1],delete n._tree}),c}var t=ua.layout.hierarchy().sort(null).value(null),e=fi,r=[1,1];return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(r=t,n):r},$r(n,t)},ua.layout.pack=function(){function n(n,i){var u=t.call(this,n,i),a=u[0];a.x=0,a.y=0,vi(a,function(n){n.r=Math.sqrt(n.value)}),vi(a,Ei);var o=r[0],c=r[1],l=Math.max(2*a.r/o,2*a.r/c);if(e>0){
var f=e*l/2;vi(a,function(n){n.r+=f}),vi(a,Ei),vi(a,function(n){n.r-=f}),l=Math.max(2*a.r/o,2*a.r/c)}return Ni(a,o/2,c/2,1/l),u}var t=ua.layout.hierarchy().sort(bi),e=0,r=[1,1];return n.size=function(t){return arguments.length?(r=t,n):r},n.padding=function(t){return arguments.length?(e=+t,n):e},$r(n,t)},ua.layout.cluster=function(){function n(n,i){var u,a=t.call(this,n,i),o=a[0],c=0;vi(o,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ti(t)):(n.x=u?c+=e(n,u):0,n.y=0,u=n)});var l=zi(o),f=Di(o),s=l.x-e(l,f)/2,h=f.x+e(f,l)/2;return vi(o,function(n){n.x=(n.x-s)/(h-s)*r[0],n.y=(1-(o.y?n.y/o.y:1))*r[1]}),a}var t=ua.layout.hierarchy().sort(null).value(null),e=fi,r=[1,1];return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(r=t,n):r},$r(n,t)},ua.layout.treemap=function(){function n(n,t){for(var e,r,i=-1,u=n.length;++i<u;)r=(e=n[i]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var u=e.children;if(u&&u.length)
{var a,o,c,l=s(e),f=[],h=u.slice(),p=1/0,d="slice"===g?l.dx:"dice"===g?l.dy:"slice-dice"===g?e.depth&1?l.dy:l.dx:Math.min(l.dx,l.dy);for(n(h,l.dx*l.dy/e.value),f.area=0;(c=h.length)>0;)f.push(a=h[c-1]),f.area+=a.area,"squarify"!==g||(o=r(f,d))<=p?(h.pop(),p=o):(f.area-=f.pop().area,i(f,d,l,!1),d=Math.min(l.dx,l.dy),f.length=f.area=0,p=1/0);f.length&&(i(f,d,l,!0),f.length=f.area=0),u.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var u,a=s(t),o=r.slice(),c=[];for(n(o,a.dx*a.dy/t.value),c.area=0;u=o.pop();)c.push(u),c.area+=u.area,u.z!=null&&(i(c,u.z?a.dx:a.dy,a,!o.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,i=0,u=1/0,a=-1,o=n.length;++a<o;)(e=n[a].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,t*=t,r?Math.max(t*i*p/r,r/(t*u*p)):1/0}function i(n,t,e,r){var i,u=-1,a=n.length,o=e.x,l=e.y,f=t?c(n.area/t):0;if(t==e.dx){for((r||f>e.dy)&&(f=e.dy);++u<a;)i=n[u],i.x=o,i.y=l,i.dy=f,o+=i.dx=Math.min(e.x+e.dx-o,f?c(i.area/f):0);i.z=!0,i.dx+=e.x+e.d
x-o,e.y+=f,e.dy-=f}else{for((r||f>e.dx)&&(f=e.dx);++u<a;)i=n[u],i.x=o,i.y=l,i.dx=f,l+=i.dy=Math.min(e.y+e.dy-l,f?c(i.area/f):0);i.z=!1,i.dy+=e.y+e.dy-l,e.x+=f,e.dx-=f}}function u(r){var i=a||o(r),u=i[0];return u.x=0,u.y=0,u.dx=l[0],u.dy=l[1],a&&o.revalue(u),n([u],u.dx*u.dy/u.value),(a?e:t)(u),h&&(a=i),i}var a,o=ua.layout.hierarchy(),c=Math.round,l=[1,1],f=null,s=ji,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return u.size=function(n){return arguments.length?(l=n,u):l},u.padding=function(n){function t(t){var e=n.call(u,t,t.depth);return null==e?ji(t):Li(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Li(t,n)}if(!arguments.length)return f;var r;return s=(f=n)==null?ji:(r=typeof n)=="function"?t:"number"===r?(n=[n,n,n,n],e):e,u},u.round=function(n){return arguments.length?(c=n?Math.round:Number,u):c!=Number},u.sticky=function(n){return arguments.length?(h=n,a=null,u):h},u.ratio=function(n){return arguments.length?(p=n,u):p},u.mode=function(n){return arguments.length?(g=n+"",
u):g},$r(u,o)},ua.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,i;do e=Math.random()*2-1,r=Math.random()*2-1,i=e*e+r*r;while(!i||i>1);return n+t*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(){var n=ua.random.normal.apply(ua,arguments);return function(){return Math.exp(n())}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t/n}}},ua.scale={},ua.scale.linear=function(){return Yi([0,1],[0,1],yr,!1)},ua.scale.log=function(){return Bi(ua.scale.linear().domain([0,Math.LN10]),10,$i,Ji,[1,10])};var Jo=ua.format(".0e");ua.scale.pow=function(){return Wi(ua.scale.linear(),1,[0,1])},ua.scale.sqrt=function(){return ua.scale.pow().exponent(.5)},ua.scale.ordinal=function(){return nu([],{t:"range",a:[[]]})},ua.scale.category10=function(){return ua.scale.ordinal().range(Go)},ua.scale.category20=function(){return ua.scale.ordinal().range(Ko)},ua.scale.category20b=function(){return ua.scale.ordi
nal().range(Wo)},ua.scale.category20c=function(){return ua.scale.ordinal().range(Qo)};var Go=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],Ko=["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],Wo=["#393b79","#5254a3","#6b6ecf","#9c9ede","#637939","#8ca252","#b5cf6b","#cedb9c","#8c6d31","#bd9e39","#e7ba52","#e7cb94","#843c39","#ad494a","#d6616b","#e7969c","#7b4173","#a55194","#ce6dbd","#de9ed6"],Qo=["#3182bd","#6baed6","#9ecae1","#c6dbef","#e6550d","#fd8d3c","#fdae6b","#fdd0a2","#31a354","#74c476","#a1d99b","#c7e9c0","#756bb1","#9e9ac8","#bcbddc","#dadaeb","#636363","#969696","#bdbdbd","#d9d9d9"];ua.scale.quantile=function(){return tu([],[])},ua.scale.quantize=function(){return eu(0,1,[0,1])},ua.scale.threshold=function(){return ru([.5],[0,1])},ua.scale.identity=function()
{return iu([0,1])},ua.svg.arc=function(){function n(){var n=t.apply(this,arguments),u=e.apply(this,arguments),a=r.apply(this,arguments)+nc,o=i.apply(this,arguments)+nc,c=(a>o&&(c=a,a=o,o=c),o-a),l=Da>c?"0":"1",f=Math.cos(a),s=Math.sin(a),h=Math.cos(o),g=Math.sin(o);return c>=tc?n?"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"Z":n?"M"+u*f+","+u*s+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+l+",0 "+n*f+","+n*s+"Z":"M"+u*f+","+u*s+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*g+"L0,0"+"Z"}var t=uu,e=au,r=ou,i=cu;return n.innerRadius=function(e){return arguments.length?(t=lt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=lt(t),n):e},n.startAngle=function(t){return arguments.length?(r=lt(t),n):r},n.endAngle=function(t){return arguments.length?(i=lt(t),n):i},n.centroid=function(){var n=(t.apply(this,arguments
)+e.apply(this,arguments))/2,u=(r.apply(this,arguments)+i.apply(this,arguments))/2+nc;return[Math.cos(u)*n,Math.sin(u)*n]},n};var nc=-Da/2,tc=2*Da-1e-6;ua.svg.line.radial=function(){var n=De(lu);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},Pe.reverse=Re,Re.reverse=Pe,ua.svg.area=function(){return fu(ft)},ua.svg.area.radial=function(){var n=fu(lu);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},ua.svg.chord=function(){function n(n,o){var c=t(this,u,n,o),l=t(this,a,n,o);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,l)?i(c.r,c.p1,c.r,c.p0):i(c.r,c.p1,l.r,l.p0)+r(l.r,l.p1,l.a1-l.a0)+i(l.r,l.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var i=t.call(n,e,r),u=o.call(n,i,r),a=c.call(n,i,r)+nc,f=l.call(n,i,r)+nc;return{r:u,a0:a,a1:f,p0:[u*Math.cos(a),u*Math.sin(a)],p1:[u*Math.cos(f),u*Math.sin(f)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n
,t,e){return"A"+n+","+n+" 0 "+ +(e>Da)+",1 "+t}function i(n,t,e,r){return"Q 0,0 "+r}var u=se,a=he,o=su,c=ou,l=cu;return n.radius=function(t){return arguments.length?(o=lt(t),n):o},n.source=function(t){return arguments.length?(u=lt(t),n):u},n.target=function(t){return arguments.length?(a=lt(t),n):a},n.startAngle=function(t){return arguments.length?(c=lt(t),n):c},n.endAngle=function(t){return arguments.length?(l=lt(t),n):l},n},ua.svg.diagonal=function(){function n(n,i){var u=t.call(this,n,i),a=e.call(this,n,i),o=(u.y+a.y)/2,c=[u,{x:u.x,y:o},{x:a.x,y:o},a];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=se,e=he,r=hu;return n.source=function(e){return arguments.length?(t=lt(e),n):t},n.target=function(t){return arguments.length?(e=lt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},ua.svg.diagonal.radial=function(){var n=ua.svg.diagonal(),t=hu,e=n.projection;return n.projection=function(n){return arguments.length?e(gu(t=n)):t},n},ua.svg.symbol=f
unction(){function n(n,r){return(ec.get(t.call(this,n,r))||mu)(e.call(this,n,r))}var t=du,e=pu;return n.type=function(e){return arguments.length?(t=lt(e),n):t},n.size=function(t){return arguments.length?(e=lt(t),n):e},n};var ec=ua.map({circle:mu,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*uc)),e=t*uc;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/ic),e=t*ic/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/ic),e=t*ic/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});ua.svg.symbolTypes=ec.keys();var rc,ic=Math.sqrt(3),uc=Math.tan(30*La),ac=[],oc=0,cc={ease:kr,delay:0,duration:250};ac.call=wa.call,ac.empty=wa.empty,ac.node=wa.node,ua.transition=
function(n){return arguments.length?rc?n.transition():n:Na.transition()},ua.transition.prototype=ac,ac.select=function(n){var t,e,r,i=this.id,u=[];"function"!=typeof n&&(n=v(n));for(var a=-1,o=this.length;++a<o;){u.push(t=[]);for(var c=this[a],l=-1,f=c.length;++l<f;)(r=c[l])&&(e=n.call(r,r.__data__,l))?("__data__"in r&&(e.__data__=r.__data__),xu(e,l,i,r.__transition__[i]),t.push(e)):t.push(null)}return vu(u,i)},ac.selectAll=function(n){var t,e,r,i,u,a=this.id,o=[];"function"!=typeof n&&(n=y(n));for(var c=-1,l=this.length;++c<l;)for(var f=this[c],s=-1,h=f.length;++s<h;)if(r=f[s]){u=r.__transition__[a],e=n.call(r,r.__data__,s),o.push(t=[]);for(var g=-1,p=e.length;++g<p;)xu(i=e[g],g,a,u),t.push(i)}return vu(o,a)},ac.filter=function(n){var t,e,r,i=[];"function"!=typeof n&&(n=A(n));for(var u=0,a=this.length;a>u;u++){i.push(t=[]);for(var e=this[u],o=0,c=e.length;c>o;o++)(r=e[o])&&n.call(r,r.__data__,o)&&t.push(r)}return vu(i,this.id,this.time).ease(this.ease())},ac.tween=function(
n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):D(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},ac.attr=function(n,t){function e(){this.removeAttribute(o)}function r(){this.removeAttributeNS(o.space,o.local)}function i(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(o);return e!==n&&(t=a(e,n),function(n){this.setAttribute(o,t(n))})})}function u(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(o.space,o.local);return e!==n&&(t=a(e,n),function(n){this.setAttributeNS(o.space,o.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var a=Mr(n),o=ua.ns.qualify(n);return yu(this,"attr."+n,t,o.local?u:i)},ac.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(i));return r&&function(n){this.setAttribute(i,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(i.space,i.local));return
r&&function(n){this.setAttributeNS(i.space,i.local,r(n))}}var i=ua.ns.qualify(n);return this.tween("attr."+n,i.local?r:e)},ac.style=function(n,t,e){function r(){this.style.removeProperty(n)}function i(t){return null==t?r:(t+="",function(){var r,i=oa.getComputedStyle(this,null).getPropertyValue(n);return i!==t&&(r=a(i,t),function(t){this.style.setProperty(n,r(t),e)})})}var u=arguments.length;if(3>u){if("string"!=typeof n){2>u&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}var a=Mr(n);return yu(this,"style."+n,t,i)},ac.styleTween=function(n,t,e){function r(r,i){var u=t.call(this,r,i,oa.getComputedStyle(this,null).getPropertyValue(n));return u&&function(t){this.style.setProperty(n,u(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},ac.text=function(n){return yu(this,"text",n,Mu)},ac.remove=function(){return this.each("end.transition",function(){var n;!this.__transition__&&(n=this.parentNode)&&n.removeChild(this)})},ac.ease=function(n){var t=this.id;re
turn arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=ua.ease.apply(ua,arguments)),D(this,function(e){e.__transition__[t].ease=n}))},ac.delay=function(n){var t=this.id;return D(this,"function"==typeof n?function(e,r,i){e.__transition__[t].delay=n.call(e,e.__data__,r,i)|0}:(n|=0,function(e){e.__transition__[t].delay=n}))},ac.duration=function(n){var t=this.id;return D(this,"function"==typeof n?function(e,r,i){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,i)|0)}:(n=Math.max(1,0|n),function(e){e.__transition__[t].duration=n}))},ac.each=function(n,t){var e=this.id;if(arguments.length<2){var r=cc,i=rc;rc=e,D(this,function(t,r,i){cc=t.__transition__[e],n.call(t,t.__data__,r,i)}),cc=r,rc=i}else D(this,function(r){r.__transition__[e].event.on(n,t)});return this},ac.transition=function(){for(var n,t,e,r,i=this.id,u=++oc,a=[],o=0,c=this.length;c>o;o++){a.push(n=[]);for(var t=this[o],l=0,f=t.length;f>l;l++)(e=t[l])&&(r=Object.create(e.__tr
ansition__[i]),r.delay+=r.duration,xu(e,l,u,r)),n.push(e)}return vu(a,u)},ua.svg.axis=function(){function n(n){n.each(function(){var n,s=ua.select(this),h=null==l?e.ticks?e.ticks.apply(e,c):e.domain():l,g=null==t?e.tickFormat?e.tickFormat.apply(e,c):String:t,p=wu(e,h,f),d=s.selectAll(".tick.minor").data(p,String),m=d.enter().insert("line",".tick").attr("class","tick minor").style("opacity",1e-6),v=ua.transition(d.exit()).style("opacity",1e-6).remove(),y=ua.transition(d).style("opacity",1),M=s.selectAll(".tick.major").data(h,String),x=M.enter().insert("g","path").attr("class","tick major").style("opacity",1e-6),b=ua.transition(M.exit()).style("opacity",1e-6).remove(),_=ua.transition(M).style("opacity",1),w=Hi(e),S=s.selectAll(".domain").data([0]),E=(S.enter().append("path").attr("class","domain"),ua.transition(S)),k=e.copy(),A=this.__chart__||k;this.__chart__=k,x.append("line"),x.append("text");var N=x.select("line"),q=_.select("line"),T=M.select("text").text(g),C=x.select("t
ext"),z=_.select("text");switch(r){case"bottom":n=bu,m.attr("y2",u),y.attr("x2",0).attr("y2",u),N.attr("y2",i),C.attr("y",Math.max(i,0)+o),q.attr("x2",0).attr("y2",i),z.attr("x",0).attr("y",Math.max(i,0)+o),T.attr("dy",".71em").style("text-anchor","middle"),E.attr("d","M"+w[0]+","+a+"V0H"+w[1]+"V"+a);break;case"top":n=bu,m.attr("y2",-u),y.attr("x2",0).attr("y2",-u),N.attr("y2",-i),C.attr("y",-(Math.max(i,0)+o)),q.attr("x2",0).attr("y2",-i),z.attr("x",0).attr("y",-(Math.max(i,0)+o)),T.attr("dy","0em").style("text-anchor","middle"),E.attr("d","M"+w[0]+","+-a+"V0H"+w[1]+"V"+-a);break;case"left":n=_u,m.attr("x2",-u),y.attr("x2",-u).attr("y2",0),N.attr("x2",-i),C.attr("x",-(Math.max(i,0)+o)),q.attr("x2",-i).attr("y2",0),z.attr("x",-(Math.max(i,0)+o)).attr("y",0),T.attr("dy",".32em").style("text-anchor","end"),E.attr("d","M"+-a+","+w[0]+"H0V"+w[1]+"H"+-a);break;case"right":n=_u,m.attr("x2",u),y.attr("x2",u).attr("y2",0),N.attr("x2",i),C.attr("x",Math.max(i,0)+o),q.attr("x2",i).att
r("y2",0),z.attr("x",Math.max(i,0)+o).attr("y",0),T.attr("dy",".32em").style("text-anchor","start"),E.attr("d","M"+a+","+w[0]+"H0V"+w[1]+"H"+a)}if(e.ticks)x.call(n,A),_.call(n,k),b.call(n,k),m.call(n,A),y.call(n,k),v.call(n,k);else{var D=k.rangeBand()/2,j=function(n){return k(n)+D};x.call(n,j),_.call(n,j)}})}var t,e=ua.scale.linear(),r=lc,i=6,u=6,a=6,o=3,c=[10],l=null,f=0;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in fc?t+"":lc,n):r},n.ticks=function(){return arguments.length?(c=arguments,n):c},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t,e){if(!arguments.length)return i;var r=arguments.length-1;return i=+t,u=r>1?+e:i,a=r>0?+arguments[r]:i,n},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(t){return arguments.length?(f=+t,n):f},n};var lc="bottom",fc={top:1,right:1,bottom:1,
left:1};ua.svg.brush=function(){function n(u){u.each(function(){var u,a=ua.select(this),l=a.selectAll(".background").data([0]),s=a.selectAll(".extent").data([0]),h=a.selectAll(".resize").data(f,String);a.style("pointer-events","all").on("mousedown.brush",i).on("touchstart.brush",i),l.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),s.enter().append("rect").attr("class","extent").style("cursor","move"),h.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return sc[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),h.style("display",n.empty()?"none":null),h.exit().remove(),o&&(u=Hi(o),l.attr("x",u[0]).attr("width",u[1]-u[0]),e(a)),c&&(u=Hi(c),l.attr("y",u[0]).attr("height",u[1]-u[0]),r(a)),t(a)})}function t(n){n.selectAll(".resize").attr("transf
orm",function(n){return"translate("+s[+/e$/.test(n)][0]+","+s[+/^s/.test(n)][1]+")"})}function e(n){n.select(".extent").attr("x",s[0][0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1][0]-s[0][0])}function r(n){n.select(".extent").attr("y",s[0][1]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",s[1][1]-s[0][1])}function i(){function i(){var n=ua.event.changedTouches;
+return n?ua.touches(y,n)[0]:ua.mouse(y)}function f(){ua.event.keyCode==32&&(E||(m=null,k[0]-=s[1][0],k[1]-=s[1][1],E=2),l())}function h(){ua.event.keyCode==32&&2==E&&(k[0]+=s[1][0],k[1]+=s[1][1],E=0,l())}function g(){var n=i(),u=!1;v&&(n[0]+=v[0],n[1]+=v[1]),E||(ua.event.altKey?(m||(m=[(s[0][0]+s[1][0])/2,(s[0][1]+s[1][1])/2]),k[0]=s[+(n[0]<m[0])][0],k[1]=s[+(n[1]<m[1])][1]):m=null),w&&p(n,o,0)&&(e(b),u=!0),S&&p(n,c,1)&&(r(b),u=!0),u&&(t(b),x({type:"brush",mode:E?"move":"resize"}))}function p(n,t,e){var r,i,a=Hi(t),o=a[0],c=a[1],l=k[e],f=s[1][e]-s[0][e];return E&&(o-=l,c-=f+l),r=Math.max(o,Math.min(c,n[e])),E?i=(r+=l)+f:(m&&(l=Math.max(o,Math.min(c,2*m[e]-r))),r>l?(i=r,r=l):i=l),s[0][e]!==r||s[1][e]!==i?(u=null,s[0][e]=r,s[1][e]=i,!0):void 0}function d(){g(),b.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),ua.select("body").style("cursor",null),A.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touc
hend.brush",null).on("keydown.brush",null).on("keyup.brush",null),x({type:"brushend"}),l()}var m,v,y=this,M=ua.select(ua.event.target),x=a.of(y,arguments),b=ua.select(y),_=M.datum(),w=!/^(n|s)$/.test(_)&&o,S=!/^(e|w)$/.test(_)&&c,E=M.classed("extent"),k=i(),A=ua.select(oa).on("mousemove.brush",g).on("mouseup.brush",d).on("touchmove.brush",g).on("touchend.brush",d).on("keydown.brush",f).on("keyup.brush",h);if(E)k[0]=s[0][0]-k[0],k[1]=s[0][1]-k[1];else if(_){var N=+/w$/.test(_),q=+/^n/.test(_);v=[s[1-N][0]-k[0],s[1-q][1]-k[1]],k[0]=s[N][0],k[1]=s[q][1]}else ua.event.altKey&&(m=k.slice());b.style("pointer-events","none").selectAll(".resize").style("display",null),ua.select("body").style("cursor",M.style("cursor")),x({type:"brushstart"}),g(),l()}var u,a=h(n,"brushstart","brush","brushend"),o=null,c=null,f=hc[0],s=[[0,0],[0,0]];return n.x=function(t){return arguments.length?(o=t,f=hc[!o<<1|!c],n):o},n.y=function(t){return arguments.length?(c=t,f=hc[!o<<1|!c],n):c},n.extent=functi
on(t){var e,r,i,a,l;return arguments.length?(u=[[0,0],[0,0]],o&&(e=t[0],r=t[1],c&&(e=e[0],r=r[0]),u[0][0]=e,u[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),s[0][0]=0|e,s[1][0]=0|r),c&&(i=t[0],a=t[1],o&&(i=i[1],a=a[1]),u[0][1]=i,u[1][1]=a,c.invert&&(i=c(i),a=c(a)),i>a&&(l=i,i=a,a=l),s[0][1]=0|i,s[1][1]=0|a),n):(t=u||s,o&&(e=t[0][0],r=t[1][0],u||(e=s[0][0],r=s[1][0],o.invert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(i=t[0][1],a=t[1][1],u||(i=s[0][1],a=s[1][1],c.invert&&(i=c.invert(i),a=c.invert(a)),i>a&&(l=i,i=a,a=l))),o&&c?[[e,i],[r,a]]:o?[e,r]:c&&[i,a])},n.clear=function(){return u=null,s[0][0]=s[0][1]=s[1][0]=s[1][1]=0,n},n.empty=function(){return o&&s[0][0]===s[1][0]||c&&s[0][1]===s[1][1]},ua.rebind(n,a,"on")};var sc={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},hc=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];ua.time={};var gc=Date,pc=["Sunday","Monday","T
uesday","Wednesday","Thursday","Friday","Saturday"];Su.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){dc.setUTCDate.apply(this._,arguments)},setDay:function(){dc.setUTCDay.apply(this._,arguments)},setFullYear:function(){dc.setUTCFullYear.apply(this._,arguments)},setHours:function(){dc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){dc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){dc.setUTCMinutes.apply(this._,arguments)},setM
onth:function(){dc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){dc.setUTCSeconds.apply(this._,arguments)},setTime:function(){dc.setTime.apply(this._,arguments)}};var dc=Date.prototype,mc="%a %b %e %X %Y",vc="%m/%d/%Y",yc="%H:%M:%S",Mc=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],xc=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],bc=["January","February","March","April","May","June","July","August","September","October","November","December"],_c=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];ua.time.year=Eu(function(n){return n=ua.time.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ua.time.years=ua.time.year.range,ua.time.years.utc=ua.time.year.utc.range,ua.time.day=Eu(function(n){var t=new gc(1970,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ua.time.d
ays=ua.time.day.range,ua.time.days.utc=ua.time.day.utc.range,ua.time.dayOfYear=function(n){var t=ua.time.year(n);return Math.floor((n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*6e4)/864e5)},pc.forEach(function(n,t){n=n.toLowerCase(),t=7-t;var e=ua.time[n]=Eu(function(n){return(n=ua.time.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+Math.floor(t)*7)},function(n){var e=ua.time.year(n).getDay();return Math.floor((ua.time.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ua.time[n+"s"]=e.range,ua.time[n+"s"].utc=e.utc.range,ua.time[n+"OfYear"]=function(n){var e=ua.time.year(n).getDay();return Math.floor((ua.time.dayOfYear(n)+(e+t)%7)/7)}}),ua.time.week=ua.time.sunday,ua.time.weeks=ua.time.sunday.range,ua.time.weeks.utc=ua.time.sunday.utc.range,ua.time.weekOfYear=ua.time.sundayOfYear,ua.time.format=function(n){function t(t){for(var r,i,u,a=[],o=-1,c=0;++o<e;)n.charCodeAt(o)===37&&(a.push(n.substring(c,o)),(i=qc[r=n.charAt(++o)])!=null&&(r=n.charAt(++o
)),(u=Tc[r])&&(r=u(t,null==i?"e"===r?" ":"0":i)),a.push(r),c=o+1);return a.push(n.substring(c,o)),a.join("")}var e=n.length;return t.parse=function(t){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Au(e,n,t,0);if(r!=t.length)return null;"p"in e&&(e.H=e.H%12+e.p*12);var i=new gc;return i.setFullYear(e.y,e.m,e.d),i.setHours(e.H,e.M,e.S,e.L),i},t.toString=function(){return n},t};var wc=Nu(Mc),Sc=Nu(xc),Ec=Nu(bc),kc=qu(bc),Ac=Nu(_c),Nc=qu(_c),qc={"-":"",_:" ",0:"0"},Tc={a:function(n){return xc[n.getDay()]},A:function(n){return Mc[n.getDay()]},b:function(n){return _c[n.getMonth()]},B:function(n){return bc[n.getMonth()]},c:ua.time.format(mc),d:function(n,t){return Tu(n.getDate(),t,2)},e:function(n,t){return Tu(n.getDate(),t,2)},H:function(n,t){return Tu(n.getHours(),t,2)},I:function(n,t){return Tu(n.getHours()%12||12,t,2)},j:function(n,t){return Tu(1+ua.time.dayOfYear(n),t,3)},L:function(n,t){return Tu(n.getMilliseconds(),t,3)},m:function(n,t){return Tu(n.getMonth()+1,t,2)},M:function(n
,t){return Tu(n.getMinutes(),t,2)},p:function(n){return n.getHours()>=12?"PM":"AM"},S:function(n,t){return Tu(n.getSeconds(),t,2)},U:function(n,t){return Tu(ua.time.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Tu(ua.time.mondayOfYear(n),t,2)},x:ua.time.format(vc),X:ua.time.format(yc),y:function(n,t){return Tu(n.getFullYear()%100,t,2)},Y:function(n,t){return Tu(n.getFullYear()%1e4,t,4)},Z:$u,"%":function(){return"%"}},Cc={a:Cu,A:zu,b:Du,B:ju,c:Lu,d:Uu,e:Uu,H:Iu,I:Iu,L:Zu,m:Yu,M:Vu,p:Bu,S:Xu,x:Fu,X:Hu,y:Ru,Y:Pu},zc=/^\s*\d+/,Dc=ua.map({am:0,pm:1});ua.time.format.utc=function(n){function t(n){try{gc=Su;var t=new gc;return t._=n,e(t)}finally{gc=Date}}var e=ua.time.format(n);return t.parse=function(n){try{gc=Su;var t=e.parse(n);return t&&t._}finally{gc=Date}},t.toString=e.toString,t};var jc=ua.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");ua.time.format.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ju:jc,Ju.parse=function(n){var
t=new Date(n);return isNaN(t)?null:t},Ju.toString=jc.toString,ua.time.second=Eu(function(n){return new gc(Math.floor(n/1e3)*1e3)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*1e3)},function(n){return n.getSeconds()}),ua.time.seconds=ua.time.second.range,ua.time.seconds.utc=ua.time.second.utc.range,ua.time.minute=Eu(function(n){return new gc(Math.floor(n/6e4)*6e4)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*6e4)},function(n){return n.getMinutes()}),ua.time.minutes=ua.time.minute.range,ua.time.minutes.utc=ua.time.minute.utc.range,ua.time.hour=Eu(function(n){var t=n.getTimezoneOffset()/60;return new gc((Math.floor(n/36e5-t)+t)*36e5)},function(n,t){n.setTime(n.getTime()+Math.floor(t)*36e5)},function(n){return n.getHours()}),ua.time.hours=ua.time.hour.range,ua.time.hours.utc=ua.time.hour.utc.range,ua.time.month=Eu(function(n){return n=ua.time.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ua.time.months=ua.time.mont
h.range,ua.time.months.utc=ua.time.month.utc.range;var Lc=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Fc=[[ua.time.second,1],[ua.time.second,5],[ua.time.second,15],[ua.time.second,30],[ua.time.minute,1],[ua.time.minute,5],[ua.time.minute,15],[ua.time.minute,30],[ua.time.hour,1],[ua.time.hour,3],[ua.time.hour,6],[ua.time.hour,12],[ua.time.day,1],[ua.time.day,2],[ua.time.week,1],[ua.time.month,1],[ua.time.month,3],[ua.time.year,1]],Hc=[[ua.time.format("%Y"),Ht],[ua.time.format("%B"),function(n){return n.getMonth()}],[ua.time.format("%b %d"),function(n){return n.getDate()!=1}],[ua.time.format("%a %d"),function(n){return n.getDay()&&n.getDate()!=1}],[ua.time.format("%I %p"),function(n){return n.getHours()}],[ua.time.format("%I:%M"),function(n){return n.getMinutes()}],[ua.time.format(":%S"),function(n){return n.getSeconds()}],[ua.time.format(".%L"),function(n){return n.getMilliseconds()}]],Pc=ua.scale.linear(),Rc=Wu(Hc);Fc.
year=function(n,t){return Pc.domain(n.map(na)).ticks(t).map(Qu)},ua.time.scale=function(){return Gu(ua.scale.linear(),Fc,Rc)};var Oc=Fc.map(function(n){return[n[0].utc,n[1]]}),Yc=[[ua.time.format.utc("%Y"),Ht],[ua.time.format.utc("%B"),function(n){return n.getUTCMonth()}],[ua.time.format.utc("%b %d"),function(n){return n.getUTCDate()!=1}],[ua.time.format.utc("%a %d"),function(n){return n.getUTCDay()&&n.getUTCDate()!=1}],[ua.time.format.utc("%I %p"),function(n){return n.getUTCHours()}],[ua.time.format.utc("%I:%M"),function(n){return n.getUTCMinutes()}],[ua.time.format.utc(":%S"),function(n){return n.getUTCSeconds()}],[ua.time.format.utc(".%L"),function(n){return n.getUTCMilliseconds()}]],Uc=Wu(Yc);return Oc.year=function(n,t){return Pc.domain(n.map(ea)).ticks(t).map(ta)},ua.time.scale.utc=function(){return Gu(ua.scale.linear(),Oc,Uc)},ua.text=st(function(n){return n.responseText}),ua.json=function(n,t){return ht(n,"application/json",ra,t)},ua.html=function(n,t){return ht(n,"t
ext/html",ia,t)},ua.xml=st(function(n){return n.responseXML}),ua}();
\ No newline at end of file
commit 40067107470e7402e599ed2e81f03ae8a1d21fac
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 09:55:15 2013 -0700
Fix chart size on detail summary graphs as new chart is a bit larger with new date nav controls.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index b876c74..31b1667 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -634,7 +634,7 @@ public abstract class AbstractActivityView extends EnhancedVLayout implements Re
setIsModal(true);
setShowModalMask(true);
setWidth(950);
- setHeight(370);
+ setHeight(390);
setShowResizer(true);
setCanDragResize(true);
centerInPage();
commit 971dc50de43a893aa7424a3a17dbfb5d53f2d721
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 30 09:53:32 2013 -0700
d3 Brush handle modification to represent a physical handle.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
index 364e1d8..21e4774 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java
@@ -540,9 +540,23 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
}
function createBrush(){
-
- // here is all the brush related stuff
- var brush = $wnd.d3.svg.brush()
+ // slightly modified but originally from crossfilter (http://square.github.com/crossfilter/)
+ var resizePath = function (d) {
+ var e1 = +(d === "e"),
+ e = e1 ? 1 : 0 ,
+ x = e ? 1 : -1,
+ y = height / 3;
+ return "M" + (.5 * x) + "," + y
+ + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
+ + "V" + (2 * y - 6)
+ + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
+ + "Z"
+ + "M" + (2.5 * x) + "," + (y + 8)
+ + "V" + (2 * y - 8)
+ + "M" + (4.5 * x) + "," + (y + 8)
+ + "V" + (2 * y - 8);
+ },
+ brush = $wnd.d3.svg.brush()
.x(timeScale)
.extent($wnd.d3.extent(chartData, function (d) {
return d.x;
@@ -555,13 +569,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
.call(brush);
brushg.selectAll(".resize").append("path")
- .attr("transform", "translate(0," + height / 2 + ")")
- .attr("opacity", ".3")
- .attr("fill", "#49F9FE")
.attr("d", resizePath);
brushg.selectAll("rect")
- .attr("height", 135);
+ .attr("height", height);
brushstart();
brushmove();
@@ -572,7 +583,6 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
function brushmove() {
var s = brush.extent();
- //circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
updateDateRangeDisplay($wnd.moment(s[0]), $wnd.moment(s[1]));
}
@@ -588,21 +598,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
$wnd.jQuery('#dateRange').text(formattedDateRange);
}
- // Taken from crossfilter (http://square.github.com/crossfilter/)
- function resizePath(d) {
- var e = +(d == 'e'),
- x = e ? 1 : -1,
- y = height / 3;
- return 'M' + (.5 * x) + ',' + y
- + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
- + 'V' + (2 * y - 6)
- + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
- + 'Z'
- + 'M' + (2.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8)
- + 'M' + (4.5 * x) + ',' + (y + 8)
- + 'V' + (2 * y - 8);
- }
+
}
function formatHovers(chartContext, d) {
10 years, 11 months
[rhq] modules/common
by snegrea
modules/common/cassandra-schema/pom.xml | 53 ++++++++++++++++++--------------
1 file changed, 30 insertions(+), 23 deletions(-)
New commits:
commit 7c529f50b0355b4b65118b4f5887a3deb8fb88cd
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu May 30 14:57:42 2013 -0500
Move assembly plugin into a separate profile since it is not required for main artifact, only when testing with the main runner.
diff --git a/modules/common/cassandra-schema/pom.xml b/modules/common/cassandra-schema/pom.xml
index 59a8ac5..a694421 100644
--- a/modules/common/cassandra-schema/pom.xml
+++ b/modules/common/cassandra-schema/pom.xml
@@ -60,29 +60,6 @@
<classpathScope>compile</classpathScope>
</configuration>
</plugin>
-
- <plugin>
- <artifactId>maven-assembly-plugin</artifactId>
- <configuration>
- <archive>
- <manifest>
- <mainClass>org.rhq.cassandra.schema.SchemaManager</mainClass>
- </manifest>
- </archive>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id> <!-- this is used for inheritance merges -->
- <phase>package</phase> <!-- bind to the packaging phase -->
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
@@ -136,6 +113,36 @@
</plugins>
</build>
</profile>
+
+ <profile>
+ <id>standalone</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.rhq.cassandra.schema.SchemaManager</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id> <!-- this is used for inheritance merges -->
+ <phase>package</phase> <!-- bind to the packaging phase -->
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
</project>
10 years, 11 months
[rhq] Branch 'refs/tags/RHQ_4_7_0_JONCI' - 105 commits - .classpath .gitignore .mailmap etc/rhq-ircBot etc/samples modules/common modules/core modules/enterprise modules/integration-tests modules/plugins pom.xml
by rhqci
.classpath | 4
.gitignore | 2
.mailmap | 1
etc/rhq-ircBot/pom.xml | 15
etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java | 270
etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java | 375 +
etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks |binary
etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties | 2
etc/samples/embedded-ext-plugin/pom.xml | 72
etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java | 58
etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml | 21
etc/samples/skeleton-plugin/pom.xml | 99
etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java | 47
etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java | 61
etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml | 20
etc/samples/skinny-platform/pom.xml | 60
etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java | 39
etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java | 67
etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml | 18
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java | 50
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java | 4
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java | 140
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java | 78
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java | 9
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java | 9
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java | 113
modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java | 27
modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java | 40
modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java | 5
modules/core/domain/src/main/resources/META-INF/persistence.xml | 8
modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java | 92
modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java | 275
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java | 2
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java | 63
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java | 40
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java | 32
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java | 33
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java | 212
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java | 6
modules/enterprise/agent/src/main/resources/agent-configuration.xml | 15
modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java | 153
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java | 9
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java | 42
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java | 72
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java | 31
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java | 32
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java | 214
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java | 203
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 31
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java | 358 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java | 383 +
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java | 34
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java | 340 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java | 39
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java | 137
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java | 35
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java | 44
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java | 146
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java | 303 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java | 34
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java | 159
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java | 137
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java | 23
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java | 49
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java | 16
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml | 3
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java | 9
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java | 7
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml | 14
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 89
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 5
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 18
modules/enterprise/gui/coregui/src/main/webapp/css/charts.css | 7
modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css | 128
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png |binary
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png |binary
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png |binary
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js | 2855 ++++++++--
modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js | 32
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java | 15
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java | 15
modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml | 2
modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml | 4
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml | 2
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml | 4
modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js | 2
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java | 16
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh | 3
modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf | 9
modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh | 2
modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc | 6
modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml | 31
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java | 66
modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java | 4
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java | 30
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java | 17
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java | 86
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java | 323 -
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java | 4
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java | 33
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java | 4
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java | 9
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java | 5
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java | 23
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java | 54
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java | 52
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java | 30
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java | 39
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java | 209
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java | 12
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java | 231
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java | 124
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java | 41
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java | 26
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java | 75
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java | 210
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java | 102
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java | 7
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java | 57
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java | 24
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java | 97
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java | 30
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java | 432 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java | 120
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java | 21
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 6
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java | 756 ++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java | 22
modules/enterprise/server/plugins/alert-snmp/pom.xml | 32
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java | 59
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java | 32
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java | 38
modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml | 36
modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java | 106
modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java | 378 +
modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml | 32
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java | 4
modules/integration-tests/jndi-access/jndi-access-test/pom.xml | 47
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml | 2
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java | 9
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java | 106
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java | 94
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java | 129
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java | 44
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java | 188
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java | 269
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java | 2
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java | 4
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java | 21
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java | 9
modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java | 186
modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml | 19
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java | 50
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java | 2
modules/plugins/jboss-as-7/pom.xml | 12
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java | 13
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java | 25
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 86
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java | 39
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java | 43
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 10
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java | 8
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java | 19
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 50
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java | 33
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java | 14
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java | 17
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java | 19
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java | 74
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java | 239
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java | 24
modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java | 2
pom.xml | 7
233 files changed, 10757 insertions(+), 4522 deletions(-)
New commits:
commit 45c43c4848b6672ccf9ffc7784ba671c6b840ae4
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:32:46 2013 -0400
Moving pom versions back to 4.7.0.JON for ALPHA build.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index dbb487d..4aae357 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index efe6d1f..434edad 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 138e9ca..86baa5a 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 5afdead..0faef44 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 0beb20b..5949978 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index b8c1682..cbb58f3 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index 6dac77b..7ce384f 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 088e268..da1d138 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index fe5f377..f4b2afa 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 258d050..33e48b1 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 67b02a8..66df7dd 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index 231ab67..bbe0954 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index 4ed7bca..b560968 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index 7adcd3b..c5184a1 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 1fb2161..62028e4 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index cc040f8..b30f82e 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 776459d..8c36237 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index dc21aad..52e1956 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 46fe305..86a3e7e 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index 8060a89..adf5bd4 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 9c801de..2ed4c26 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 3c070a9..e03ac78 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 18fa318..97ed3ab 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index 0374729..b2c1184 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index 99c875d..0820f4b 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index 426d298..ecdde93 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c41a8f4..9765a55 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index cdc3b9b..2bd8b52 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index 2d7093d..c832b41 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 67ed9a8..329f7fb 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index d5b7643..91ab077 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index 8148262..9ade65f 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index a140a9c..539cff8 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index cb7dd3a..3dea516 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 018a802..57c01e8 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index d2998cc..8b742ff 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 638bccd..0dae4ac 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index c9aa075..0cd7bf7 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 33e330e..10a7cd8 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 3fad441..0e5c315 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index dec19d0..40ed02c 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index cba50db..49e0186 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index 6db40f2..a087cb1 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 7bf574e..bbd87da 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index 268af3a..b584947 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index acc09aa..c376943 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index a58f1ca..4c47992 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index dc69d9e..385978a 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index f186d70..d6e97a0 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 3e69ded..560de86 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 867ebe1..dd10dec 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 23d8e94..9ee8e93 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 5e4e076..460342b 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 84e34c4..c0a0bae 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index ea9bd42..1bd8378 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index a2102a3..5252acc 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index bd5f656..ee5adda 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index 934cb7e..8c7670d 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index 28d1d56..80d32e7 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 4338526..6438e21 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 21ec5f7..b2ecdbe 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index a6c054a..cb37a34 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index f84398b..12ac31b 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index d4d2564..3e43ea6 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 648b451..7784473 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 6f56e82..5c79143 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index 21bb689..dde366f 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 7111543..6429931 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index 6ab0964..b36fcbb 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 32ffc76..6285905 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index 2a75e07..de6f9c4 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index dc862db..7e75407 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index bb1740d..19bc8b1 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 06da613..32d9a39 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index 6f8ac10..c97e216 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 9c60e30..48fd5ea 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index b2b741e..ab869f2 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index d4f7715..fc69668 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 014420b..6377787 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 7152fc3..286398c 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 00e558b..2f0d910 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index f2f2455..e63e38e 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index 6f36514..a7ed4cc 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index 8772058..84d6d04 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index ecebf6c..a853c5e 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index c5a4a41..2ef0b85 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index baf0801..0567602 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index bf4ca3d..24f015d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index a9d7296..ca3d81f 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 48808ac..0b0c363 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index 6ded494..5e1f84c 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index d11992a..777f236 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index 7e5f521..ac50627 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index bca2fe4..8debbc4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index 2809e95..d74b6cc 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 75a98a4..780b6e3 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 380f6e6..cead04e 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index ada89b3..d68d451 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 37ffe0e..2e80e03 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index a17a3d8..79f789b 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index 9424397..f37463b 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 3aa5463..cd8f563 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 03349f8..2292a6f 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index 8a5f0e6..7da6b89 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index a1c3353..8a77511 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index d8325e4..1618ff0 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index adee980..d2dc58a 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index f587112..0a159b5 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index d1f3e43..b31fd66 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 93a915f..34e2f82 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index b043e7b..daaa104 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index f2e6f8a..7dc2147 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index d85e7e3..397026c 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index b792d26..155912f 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 837852d..896a15d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 3828a6a..6976d9b 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 864f675..5ac7010 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 094f451..1dee28d 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index 54b9f53..e8fe102 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 572851e..22d5822 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 6b663ff..3b6bd23 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index 68af26a..f479b37 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index ed93d10..a55e980 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 5653d69..4811181 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index f852e8a..8d330c6 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index e28148c..48bd3e1 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 0e27179..8b95b87 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 12ae83c..45c5ae5 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 26d37b3..b2f56ff 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 6bf549f..0805240 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 968a154..5b0231a 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 20e41c4..8eb6a1b 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index d31500b..9cf27a2 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 36ab8be..8eb8486 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index 74d740b..cca0dfb 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index e0a216e..e99a393 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 3891b84..6ccc01b 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index eb97008..2848dbb 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 45c2544..928ab6c 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 63eb6ae..f590ca2 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index de510c5..17d502f 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 8f4cf31..0e18cc9 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index c343deb..3407cad 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index b46ee9e..314c512 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 914ec1e15b09a712f18ce46e4c3124e1a8baa6d4
Merge: 3368ace 2eef3b4
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:31:15 2013 -0400
Merge branch 'master' into nightly/rhq.jon
Conflicts:
modules/plugins/jboss-as-7/pom.xml
commit 3368acebc21e2a43a981379774d319781daabffa
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:27:37 2013 -0400
Temporarily move the pom version to minimize auto commit issues.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index 4aae357..dbb487d 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index 434edad..efe6d1f 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 86baa5a..138e9ca 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 0faef44..5afdead 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 5949978..0beb20b 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index cbb58f3..b8c1682 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index 7ce384f..6dac77b 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index da1d138..088e268 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index f4b2afa..fe5f377 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 33e48b1..258d050 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 66df7dd..67b02a8 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index bbe0954..231ab67 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index b560968..4ed7bca 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index c5184a1..7adcd3b 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 62028e4..1fb2161 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index b30f82e..cc040f8 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 8c36237..776459d 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index 52e1956..dc21aad 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 86a3e7e..46fe305 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index adf5bd4..8060a89 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 2ed4c26..9c801de 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index e03ac78..3c070a9 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 97ed3ab..18fa318 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index b2c1184..0374729 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index 0820f4b..99c875d 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index ecdde93..426d298 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 9765a55..c41a8f4 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index 2bd8b52..cdc3b9b 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index c832b41..2d7093d 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 329f7fb..67ed9a8 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 91ab077..d5b7643 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index 9ade65f..8148262 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 539cff8..a140a9c 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 3dea516..cb7dd3a 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 57c01e8..018a802 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index 8b742ff..d2998cc 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 0dae4ac..638bccd 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index 0cd7bf7..c9aa075 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 10a7cd8..33e330e 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 0e5c315..3fad441 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 40ed02c..dec19d0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index 49e0186..cba50db 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index a087cb1..6db40f2 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index bbd87da..7bf574e 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index b584947..268af3a 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index c376943..acc09aa 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 4c47992..a58f1ca 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 385978a..dc69d9e 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index d6e97a0..f186d70 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 560de86..3e69ded 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index dd10dec..867ebe1 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 9ee8e93..23d8e94 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 460342b..5e4e076 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index c0a0bae..84e34c4 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index 1bd8378..ea9bd42 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index 5252acc..a2102a3 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index ee5adda..bd5f656 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index 8c7670d..934cb7e 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index 80d32e7..28d1d56 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 6438e21..4338526 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index b2ecdbe..21ec5f7 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index cb37a34..a6c054a 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 87a66cc..b933e91 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index 3e43ea6..d4d2564 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 7784473..648b451 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 5c79143..6f56e82 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index dde366f..21bb689 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 6429931..7111543 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index b36fcbb..6ab0964 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 6285905..32ffc76 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index de6f9c4..2a75e07 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 7e75407..dc862db 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 19bc8b1..bb1740d 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 32d9a39..06da613 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index c97e216..6f8ac10 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 48fd5ea..9c60e30 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index ab869f2..b2b741e 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index fc69668..d4f7715 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 6377787..014420b 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 286398c..7152fc3 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 2f0d910..00e558b 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index e63e38e..f2f2455 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index a7ed4cc..6f36514 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index 84d6d04..8772058 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index a853c5e..ecebf6c 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index 2ef0b85..c5a4a41 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index 0567602..baf0801 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index 24f015d..bf4ca3d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index ca3d81f..a9d7296 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 59becbb..7ae77d3 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index 5e1f84c..6ded494 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index 777f236..d11992a 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index ac50627..7e5f521 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index 8debbc4..bca2fe4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index d74b6cc..2809e95 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 780b6e3..75a98a4 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index cead04e..380f6e6 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index d68d451..ada89b3 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 2e80e03..37ffe0e 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index 79f789b..a17a3d8 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index f37463b..9424397 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index cd8f563..3aa5463 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 2292a6f..03349f8 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index 7da6b89..8a5f0e6 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 8a77511..a1c3353 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index 1618ff0..d8325e4 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index d2dc58a..adee980 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 0a159b5..f587112 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index b31fd66..d1f3e43 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 34e2f82..93a915f 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index daaa104..b043e7b 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 7dc2147..f2e6f8a 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 75e7b74..0b36f29 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index 155912f..b792d26 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 896a15d..837852d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 6976d9b..3828a6a 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 5ac7010..864f675 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 1dee28d..094f451 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index e8fe102..54b9f53 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 22d5822..572851e 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 3b6bd23..6b663ff 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index f479b37..68af26a 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index a55e980..ed93d10 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 4811181..5653d69 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 8d330c6..f852e8a 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index 48bd3e1..e28148c 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 8b95b87..0e27179 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 45c5ae5..12ae83c 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index b2f56ff..26d37b3 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 0805240..6bf549f 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 5b0231a..968a154 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 8eb6a1b..20e41c4 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 9cf27a2..d31500b 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 8eb8486..36ab8be 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index cca0dfb..74d740b 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index e99a393..e0a216e 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 6ccc01b..3891b84 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index 2848dbb..eb97008 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 928ab6c..45c2544 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index f590ca2..63eb6ae 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index 17d502f..de510c5 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 0e18cc9..8f4cf31 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index 3407cad..c343deb 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index 9b29fab..a5588bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 2eef3b4fcd05fc1b248ab3c95fbc115e3758079d
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed May 29 13:48:05 2013 +0200
[BZ 967542] - UI shows confusing units when editing Availability Duration alert condition type
Now if user iserts e.g. 90 mins and reopens the dialog, it won't display
1.5 hours anymore, but 90 mins as expected.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
index 104b84c..6c41897 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
@@ -38,6 +38,7 @@ import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
@@ -238,26 +239,17 @@ public class DurationItem extends CanvasItem {
this.form.setValue(FIELD_VALUE, formattedOutput);
setValue(formattedOutput);
} else {
- String valueWithUnits = MeasurementConverterClient.format((double) longValue,
- MeasurementUnits.MILLISECONDS, true);
- String[] chunks = valueWithUnits.split(" ");
- String value = chunks[0];
- if (value.endsWith(".0")) {
- value = value.substring(0, value.indexOf(".0"));
+ MeasurementNumericValueAndUnits valueWithUnits;
+ if (longValue % HOUR_IN_MILLIS == 0) {
+ valueWithUnits = MeasurementConverterClient.fit((double) longValue, MeasurementUnits.MILLISECONDS,
+ MeasurementUnits.HOURS, MeasurementUnits.HOURS);
+ } else {
+ valueWithUnits = MeasurementConverterClient.fit((double) longValue, MeasurementUnits.MILLISECONDS,
+ MeasurementUnits.MINUTES, MeasurementUnits.MINUTES);
}
- this.form.setValue(FIELD_VALUE, value);
- String units = chunks[1];
SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
- if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.SECONDS).equals(units)) {
- unitsItem.setValue(TimeUnit.SECONDS.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.MINUTES)
- .equals(units)) {
- unitsItem.setValue(TimeUnit.MINUTES.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.HOURS).equals(units)) {
- unitsItem.setValue(TimeUnit.HOURS.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.DAYS).equals(units)) {
- unitsItem.setValue(TimeUnit.DAYS.name().toLowerCase());
- }
+ this.form.setValue(FIELD_VALUE, valueWithUnits.getValue().intValue());
+ unitsItem.setValue(valueWithUnits.getUnits().name().toLowerCase());
}
}
commit 2e3f2b2e2f8db3894fea0777508e79e4bf3817cd
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue May 28 14:32:14 2013 -0400
BZ 967990 the installer now turns off the admin console
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 8cef6e1..eaf6f66 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -40,12 +40,33 @@ public class CoreJBossASClient extends JBossASClient {
public static final String SCANNER = "scanner";
public static final String EXTENSION = "extension";
public static final String MODULE = "module";
+ public static final String CORE_SERVICE_MGMT = "management";
+ public static final String MGMT_INTERFACE = "management-interface";
+ public static final String MGMT_INTERFACE_HTTP = "http-interface";
public CoreJBossASClient(ModelControllerClient client) {
super(client);
}
/**
+ * Allows the caller to turn on or off complete access for the app server's admin console.
+ *
+ * @param enableFlag true if the admin console enabled and visible; false if you want to prohibit all access to the admin console
+ * @throws Exception
+ */
+ public void setEnableAdminConsole(boolean enableFlag) throws Exception {
+ // /core-service=management/management-interface=http-interface/:write-attribute(name=console-enabled,value=false)
+ final Address address = Address.root()
+ .add(CORE_SERVICE, CORE_SERVICE_MGMT, MGMT_INTERFACE, MGMT_INTERFACE_HTTP);
+ final ModelNode req = createWriteAttributeRequest("console-enabled", Boolean.toString(enableFlag), address);
+ final ModelNode response = execute(req);
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return;
+ }
+
+ /**
* Given a string with possible ${x} expressions in it, this will resolve that expression
* using system property values that are set within the AS JVM itself. If the string
* to resolve has no expressions, or has no expressions that are resolveable, the expression
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 0b9c078..bb42d4a 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -1034,6 +1034,9 @@ public class InstallerServiceImpl implements InstallerService {
// we don't want to the JBossAS welcome screen; turn it off
new WebJBossASClient(mcc).setEnableWelcomeRoot(false);
+ // we don't want users to access the admin console
+ new CoreJBossASClient(mcc).setEnableAdminConsole(false);
+
} catch (Exception e) {
log("deployServices failed", e);
throw new Exception("Failed to deploy services: " + ThrowableUtil.getAllMessages(e));
commit 57333dd7c4a683fe39bfcf68ea706cbfa6feded9
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue May 28 18:40:38 2013 +0200
[BZ 967542] - UI shows confusing units when editing Availability Duration alert condition type
I improved the DurationItem component to use internally the SelectItem
instead of ComboBoxItem. When using ComboBoxItem, it was possible to
write to the combobox and this is something that shouldn't happen in
this component because the unit types should be fixed. The DurationItem
is also used from the operation tab view, but no reggression was
introduced by this commit in this view.
Modifying also the DurationItem.setAndFormatValue() to populate the time correctly when
!isReadOnly.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
index 8fe6d4b..0a2627c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
@@ -65,7 +65,6 @@ import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
import org.rhq.enterprise.gui.coregui.client.components.form.NumberWithUnitsValidator;
import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
import org.rhq.enterprise.gui.coregui.client.components.form.TimeUnit;
-import org.rhq.enterprise.gui.coregui.client.components.form.UnitType;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.enterprise.gui.coregui.client.util.measurement.MeasurementParser;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -959,7 +958,7 @@ public class ConditionEditor extends EnhancedVLayout {
durationValue.setTooltip(MSG.view_alert_definition_condition_editor_availabilityDuration_tooltip_duration());
durationValue.setHoverWidth(200);
if (editMode) {
- durationValue.setValue(Integer.parseInt(existingCondition.getOption()), UnitType.TIME);
+ durationValue.setAndFormatValue(Integer.parseInt(existingCondition.getOption()) * 1000L);
}
durationValue.setShowIfCondition(ifFunc);
formItems.add(durationValue);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index 25742f5..e24d1b4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -211,6 +211,8 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
public void execute(Boolean value) {
if (value) {
save();
+ } else {
+ unregisterHandler();
}
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
index 633188a..104b84c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
@@ -29,17 +29,19 @@ import java.util.TreeSet;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.IntegerItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
+import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
import org.rhq.enterprise.gui.coregui.client.util.TypeConversionUtility;
/**
@@ -142,7 +144,7 @@ public class DurationItem extends CanvasItem {
}
});
- ComboBoxItem unitsItem = new ComboBoxItem(FIELD_UNITS);
+ SelectItem unitsItem = new SelectItem(FIELD_UNITS);
unitsItem.setShowTitle(false);
LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
@@ -230,10 +232,33 @@ public class DurationItem extends CanvasItem {
if (longValue < 0) {
throw new IllegalArgumentException("negative time period " + longValue);
}
- String formattedOutput = formatMilliseconds(longValue);
- this.unitType = UnitType.TIME;
- this.form.setValue(FIELD_VALUE, formattedOutput);
- setValue(formattedOutput);
+ if (isReadOnly) {
+ String formattedOutput = formatMilliseconds(longValue);
+ this.unitType = UnitType.TIME;
+ this.form.setValue(FIELD_VALUE, formattedOutput);
+ setValue(formattedOutput);
+ } else {
+ String valueWithUnits = MeasurementConverterClient.format((double) longValue,
+ MeasurementUnits.MILLISECONDS, true);
+ String[] chunks = valueWithUnits.split(" ");
+ String value = chunks[0];
+ if (value.endsWith(".0")) {
+ value = value.substring(0, value.indexOf(".0"));
+ }
+ this.form.setValue(FIELD_VALUE, value);
+ String units = chunks[1];
+ SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
+ if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.SECONDS).equals(units)) {
+ unitsItem.setValue(TimeUnit.SECONDS.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.MINUTES)
+ .equals(units)) {
+ unitsItem.setValue(TimeUnit.MINUTES.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.HOURS).equals(units)) {
+ unitsItem.setValue(TimeUnit.HOURS.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.DAYS).equals(units)) {
+ unitsItem.setValue(TimeUnit.DAYS.name().toLowerCase());
+ }
+ }
}
/**
@@ -474,7 +499,7 @@ public class DurationItem extends CanvasItem {
}
private TimeUnit getInputTimeUnit() {
- ComboBoxItem unitsItem = (ComboBoxItem) this.form.getItem(FIELD_UNITS);
+ SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
String unitString = unitsItem.getValueAsString(); // this will always be non-null
TimeUnit unit;
try {
commit ecb57a4e3e147e18b000388a2baec312c31c7bf2
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue May 28 12:36:26 2013 -0400
Make sure sub-queries used for updates do not include implicit
paging/sorting.
Also, make a small change to test cleanup in related test class.
Note: Fix by lkrejci
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
index 9febeb8..24bcc84 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
@@ -342,10 +342,15 @@ public class MeasurementScheduleManagerTest extends AbstractMeasurementScheduleM
try {
if (null != em) {
em.flush();
- getTransactionManager().commit();
}
} catch (Throwable t) {
-
+ // best effort
+ }
+ try {
+ getTransactionManager().commit();
+ } catch (Throwable t) {
+ // best effort
}
}
+
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
index 2e4eeda..d53a037 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
@@ -820,6 +820,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
*/
private void markResources(EntityContext context, int agentId) {
ResourceCriteria criteria = new ResourceCriteria();
+ criteria.clearPaging(); //important to avoid setting the ordering in the generated query
if (context.type == EntityContext.Type.Resource) {
criteria.addFilterId(context.resourceId);
} else if (context.type == EntityContext.Type.ResourceGroup) {
@@ -832,7 +833,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
try {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(criteria);
- ;
+
generator.alterProjection("resource.id");
String resourceSubQuery = generator.getParameterReplacedQuery(false);
@@ -848,7 +849,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
markResourceQuery.setParameter("now", System.currentTimeMillis());
int affectedRows = markResourceQuery.executeUpdate();
if (log.isDebugEnabled()) {
- log.debug("Marked " + affectedRows + " for future measurement scheudle update");
+ log.debug("Marked " + affectedRows + " for future measurement schedule update");
}
} catch (Throwable t) {
log.error("Could not notify agents of updates", t);
@@ -877,6 +878,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
}
MeasurementScheduleCriteria criteria = new MeasurementScheduleCriteria();
+ criteria.clearPaging(); //important to avoid setting the ordering in the generated query
if (context.type == EntityContext.Type.Resource) {
criteria.addFilterResourceId(context.resourceId);
} else if (context.type == EntityContext.Type.ResourceGroup) {
@@ -1607,4 +1609,4 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
// }
// }
-}
+}
\ No newline at end of file
commit 2f15379bb357495c558b05fb271e247fa1681d01
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue May 28 17:36:13 2013 +0200
Bug 885686 - Tomcat web application configuration form allows save without Config File required field
It's not a Tomcat specific issue. We had a problem in *EditView classes: the check to enable/disable the save button was only based on the invalid properties set having been changed. Now it also looks at the set being empty or not.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
index c7604c4..a428a22 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.drift;
@@ -190,8 +190,10 @@ public class DriftDefinitionEditView extends EnhancedVLayout implements Property
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
index dd69993..0ccc445 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.drift;
@@ -178,8 +178,10 @@ public class DriftDefinitionTemplateEditView extends EnhancedVLayout implements
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index 55ac8fd..d0c440f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration;
@@ -261,8 +261,10 @@ public class GroupResourceConfigurationEditView extends EnhancedVLayout implemen
Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
index b6e892f..8680cc4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.inventory;
@@ -256,8 +256,10 @@ public class GroupPluginConfigurationEditView extends EnhancedVLayout implements
Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index ae7fde1..e3b119c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configuration;
@@ -222,8 +222,10 @@ public class ResourceConfigurationEditView extends EnhancedVLayout implements Pr
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
index fd374eb..63245a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory;
@@ -171,8 +171,10 @@ public class PluginConfigurationEditView extends EnhancedVLayout implements Prop
Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
index 128a540..bdbe026 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010-2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.test.configuration;
@@ -111,8 +110,10 @@ public class TestConfigurationView extends EnhancedVLayout implements PropertyVa
EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
index 483e71c..00da718 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.test.configuration;
@@ -112,8 +111,10 @@ public class TestGroupConfigurationView extends EnhancedVLayout implements Prope
EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
commit eeffaed93e68612eb6a88226479702d4f373e510
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue May 28 03:11:56 2013 +0200
[BZ 967622 - Server CLI script can't require modules from rhq://downloads]
This was primarily caused by a new permission required by EAP 6.1 we've
switched to. To access the ModelControllerClient, the code now needs a
RuntimePermission("canAccessModelController").
We need the ModelControllerClient when determining the EAR installation
dir, which we in turn need when determining where to locate the scripts
in the "rhq://downloads" location. This is done while running a script,
which is done in a restricted access control context which does not and
should not have that permission.
The minimal fix is to wrap the getting of the ModelControllerClient in a
privileged action but some more "defensive" code was added in the
RhqDownloadScriptSourceProvider, too, to guard against different times it
might get instantiated during the script execution.
Javadocs were updated to warn about the security considerations when
writing a script source provider available on the server side.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
index 4c6756f..87241ef 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
@@ -55,8 +55,11 @@ public abstract class BaseRhqSchemeScriptSourceProvider implements ScriptSourceP
* The base implementation of the {@link #getScriptSource(URI)} method
* only checks that the scheme of the URI is "rhq" and that the scheme
* specific part starts with "//".
- *
- * @param scriptUri
+ * <p/>
+ * Please follow the general suggestions mentioned in {@link ScriptSourceProvider#getScriptSource(java.net.URI)}
+ * docs.
+ *
+ * @param scriptUri the URI to load the script from
* @return the reader of the script or null if the script could not be
* found using the URI
*
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index e65f793..fb0f606 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -29,14 +29,26 @@ import java.net.URI;
* <p>
* Implementations of this interface can be located using the {@link ScriptSourceProviderFactory}
* if they are registered in META-INF/services.
- *
+ * <p/>
+ * Note that instances of this class can be created and called in an access control context with limited privileges.
+ * If you need to make safe calls that require privileges not granted to a script run in the RHQ server (by default this
+ * is determined by the {@code org.rhq.bindings.StandardScriptPermissions} class), make sure to call such actions with
+ * elevated permissions through
+ * {@link java.security.AccessController#doPrivileged(java.security.PrivilegedExceptionAction)} or any of its
+ * derivatives.
+ * <p/>
+ * For example JNDI look-ups are not allowed by default for the scripts, so if your provider needs to perform some
+ * JNDI lookups to locate the script to include, you need to wrap any code that does a JNDI look-up as above.
+ *
* @author Lukas Krejci
*/
public interface ScriptSourceProvider {
/**
* Returns the reader of the source of the script specified by given location.
- *
+ * <p/>
+ * Review the class description for the security considerations.
+ *
* @param location the location of the script
* @return the reader of the script source or null if it could not be found
*/
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
index 1cbbe39..23e8fb5 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
@@ -26,6 +26,11 @@ import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.Callable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -45,20 +50,67 @@ public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceP
private CoreServerMBean coreServer;
+ /**
+ * A bunch of methods optionally enclosed in privileged actions to ensure that we can access the information
+ * inside RHQ server even though it might not be accessible in the access control context the scripts run in
+ * in the RHQ server.
+ */
+ private static class SecurityActions {
+ private SecurityActions() {
+
+ }
+
+ private static CoreServerMBean lookupCoreServer() {
+ if (System.getSecurityManager() == null) {
+ return LookupUtil.getCoreServer();
+ } else {
+ return AccessController.doPrivileged(new PrivilegedAction<CoreServerMBean>() {
+ @Override
+ public CoreServerMBean run() {
+ return LookupUtil.getCoreServer();
+ }
+ });
+ }
+ }
+
+ private static File getDownloadDir(final CoreServerMBean coreServer) {
+ File earDeployDir;
+ if (System.getSecurityManager() == null) {
+ earDeployDir = coreServer.getEarDeploymentDir();
+ } else {
+ earDeployDir = AccessController.doPrivileged(new PrivilegedAction<File>() {
+ @Override
+ public File run() {
+ return coreServer.getEarDeploymentDir();
+ }
+ });
+ }
+ File downloadDir = new File(earDeployDir, "rhq-downloads");
+ return downloadDir;
+ }
+ }
+
public RhqDownloadsScriptSourceProvider() {
- this(LookupUtil.getCoreServer());
+ //we need to do a safe JNDI lookup, but we may run in unprivileged context...
+ this(SecurityActions.lookupCoreServer());
}
-
+
+ /**
+ * This is meant only for testing purposes.
+ *
+ * @param coreServerMBean the CoreServer MBean to use
+ */
public RhqDownloadsScriptSourceProvider(CoreServerMBean coreServerMBean) {
super(AUTHORITY);
this.coreServer = coreServerMBean;
}
-
+
@Override
protected Reader doGetScriptSource(URI scriptUri) {
String path = scriptUri.getPath().substring(1); //remove the leading /
- File downloadsDir = getDownloadHomeDir();
+ //We're going to be doing an MBean call here which the scripts don't have privs for by default
+ File downloadsDir = SecurityActions.getDownloadDir(coreServer);
File scriptDownloads = new File(downloadsDir, "script-modules");
File file = new File(scriptDownloads, path);
@@ -69,10 +121,4 @@ public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceP
return null;
}
}
-
- private File getDownloadHomeDir() {
- File earDeployDir = this.coreServer.getEarDeploymentDir();
- File downloadDir = new File(earDeployDir, "rhq-downloads");
- return downloadDir;
- }
}
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
index e62dd32..1b366ba 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
@@ -85,8 +85,8 @@ public class RhqDownloadsScriptSourceProviderTest {
try {
String contents = StreamUtil.slurp(rdr);
assertEquals(contents, EXPECTED_CONTENTS, "Unexpected script loaded");
- } finally {
- rdr.close();
+ } finally {
+ StreamUtil.safeClose(rdr);
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
index 9a60f12..b74b704 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
@@ -22,6 +22,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
@@ -69,6 +71,24 @@ public class CoreServer implements CoreServerMBean {
*/
private static final String PROP_BUILD_DATE = "Build-Date";
+ private static class SecurityActions {
+ private SecurityActions() {
+
+ }
+
+ private static ModelControllerClient getModelControllerClient() {
+ if (System.getSecurityManager() == null) {
+ return ManagementService.getClient();
+ } else {
+ return AccessController.doPrivileged(new PrivilegedAction<ModelControllerClient>() {
+ @Override
+ public ModelControllerClient run() {
+ return ManagementService.getClient();
+ }
+ });
+ }
+ }
+ }
private Properties buildProps;
private Date bootTime;
@@ -136,7 +156,10 @@ public class CoreServer implements CoreServerMBean {
@Override
public File getEarDeploymentDir() {
- ModelControllerClient mcc = ManagementService.getClient();
+ //Getting model controller client requires privs our callers might not have, but we want to provide this
+ //function even to them.
+ ModelControllerClient mcc = SecurityActions.getModelControllerClient();
+
try {
DeploymentJBossASClient client = new DeploymentJBossASClient(mcc);
String earPath = client.getDeploymentPath(RHQConstants.EAR_FILE_NAME);
@@ -229,4 +252,4 @@ public class CoreServer implements CoreServerMBean {
return buildProps;
}
-}
\ No newline at end of file
+}
commit ff37cd971a73a9fefc4024f5022aff85b7b90b90
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 23:29:46 2013 -0400
remove use of method not supported by GWT
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index d8552de..f398020 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -179,7 +179,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.sortId = sortId;
} else {
- throw new UnsupportedOperationException("ID sort is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("ID sort is not supported by supported by this class");
}
}
@@ -188,7 +188,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.filterId = filterId;
} else {
- throw new UnsupportedOperationException("ID filter is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("ID filter is not supported by this class");
}
}
@@ -197,7 +197,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
} else {
- throw new UnsupportedOperationException("IDS filter is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("IDS filter is not supported by this class");
}
}
commit 471b8a20f984f79d448acf58c01ec8c38cee8e67
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 19:45:41 2013 -0400
Bug 966665
- Criteria queries with paging and sorting on non unique fields may return same item on different pages
All paged criteria queries now apply ID as the least significant
ordering field (see exceptions below). Since ID is unique, this ensures
that queries for pages always return the same ordering of rows.
ID will not be automatically appended as an ordering field if:
- the paging is unlimited (i.e. no pagesize, all rows returned)
- the Criteria class does not support an ID sort
- the caller has set the Criteria class instance to not support the ID sort
- ID is already specified as an ordering field
- the max number of ordering fields has already been set (3)
Note that CriteriaQuery has had its support for implicit ID sorting removed,
as the new mechanism, which moves support to the CriteriaQueryGenerator,
replaces it.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index 2dde3a4..d8552de 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -109,6 +109,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
private List<Permission> requiredPermissions;
private boolean strict;
private Restriction restriction = null;
+ private boolean supportsAddSortId = true;
protected Map<String, String> filterOverrides;
protected Map<String, String> sortOverrides;
@@ -173,16 +174,54 @@ public abstract class Criteria implements Serializable, BaseCriteria {
}
public void addSortId(PageOrdering sortId) {
- addSortField("id");
- this.sortId = sortId;
+ if (isSupportsAddSortId()) {
+ addSortField("id");
+ this.sortId = sortId;
+
+ } else {
+ throw new UnsupportedOperationException("ID sort is not supported by " + this.getClass().getSimpleName());
+ }
}
public void addFilterId(Integer filterId) {
- this.filterId = filterId;
+ if (isSupportsAddFilterId()) {
+ this.filterId = filterId;
+
+ } else {
+ throw new UnsupportedOperationException("ID filter is not supported by " + this.getClass().getSimpleName());
+ }
}
public void addFilterIds(Integer... filterIds) {
- this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
+ if (isSupportsAddFilterIds()) {
+ this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
+
+ } else {
+ throw new UnsupportedOperationException("IDS filter is not supported by " + this.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * By default all Criteria support sort on ID. And this sort is applied implicitly to criteria
+ * queries involving paging, to ensure consistent ordering of query results. If for some unlikely reason
+ * the caller needs to disable the implicit ID sort then call this, setting the value to false.
+ *
+ * @param supportsAddSortId
+ */
+ public void setSupportsAddSortId(boolean supportsAddSortId) {
+ this.supportsAddSortId = supportsAddSortId;
+ }
+
+ public boolean isSupportsAddSortId() {
+ return supportsAddSortId;
+ }
+
+ public boolean isSupportsAddFilterId() {
+ return true;
+ }
+
+ public boolean isSupportsAddFilterIds() {
+ return true;
}
protected void addSortField(String fieldName) {
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
index af888ea..2b03228 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
@@ -292,13 +292,12 @@ public class JPADriftChangeSetCriteria extends Criteria implements DriftChangeSe
}
@Override
- public void addSortId(PageOrdering pageOrdering) {
- throw new UnsupportedOperationException("The sort is not supported by DriftChangeSetCriteria.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The filter is not supported by DriftChangeSetCriteria.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
-
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
index 56f0ddf..b13ca90 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
@@ -245,13 +245,12 @@ public class JPADriftCriteria extends Criteria implements DriftCriteria {
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The filter is not supported by DriftCriteria.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addSortId(PageOrdering pageOrdering) {
- throw new UnsupportedOperationException("The sort is not supported by DriftCriteria.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
-
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
index a27e58d..3a2a2c1 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
@@ -135,17 +135,17 @@ public class MeasurementDataTraitCriteria extends Criteria {
}
@Override
- public void addSortId(PageOrdering sortId) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addFilterId(Integer filterId) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddFilterId() {
+ return false;
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
index f87a814..888c821 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
@@ -82,14 +82,22 @@ public class PageControl implements Serializable, Cloneable {
return new PageControl(0, 1);
}
+ /**
+ * Equivalent to initDefaultOrderingField(defaultField, PageOrdering.ASC).
+ *
+ * @param defaultField
+ * @see #initDefaultOrderingField(String, PageOrdering)
+ */
public void initDefaultOrderingField(String defaultField) {
initDefaultOrderingField(defaultField, PageOrdering.ASC);
}
- public void addDefaultOrderingField(String defaultField) {
- addDefaultOrderingField(defaultField, PageOrdering.ASC);
- }
-
+ /**
+ * Sets initial sort. If sorting is already defined this call will have no effect.
+ *
+ * @param defaultField
+ * @param defaultPageOrdering
+ */
public void initDefaultOrderingField(String defaultField, PageOrdering defaultPageOrdering) {
if (orderingFields.size() > 0) {
return;
@@ -98,6 +106,24 @@ public class PageControl implements Serializable, Cloneable {
addDefaultOrderingField(defaultField, defaultPageOrdering);
}
+ /**
+ * Equivalent to addDefaultOrderingField(defaultField, PageOrdering.ASC).
+ *
+ * @param defaultField
+ * @see #addDefaultOrderingField(String, PageOrdering)
+ */
+ public void addDefaultOrderingField(String defaultField) {
+ addDefaultOrderingField(defaultField, PageOrdering.ASC);
+ }
+
+ /**
+ * Add a default ordering field. If the maximum number of sort fields (currently 3) are already
+ * defined this call will have no effect. If the field is already a sort field this call will have no
+ * effect. Otherwise, the ordering field will be appended to the existing ordering fields.
+ *
+ * @param defaultField
+ * @param defaultPageOrdering
+ */
public void addDefaultOrderingField(String defaultField, PageOrdering defaultPageOrdering) {
if (orderingFields.size() >= MAX_ORDERING_FIELD_COUNT) {
return; // only need to add defaults if there are less than 3 sort orders
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
index 2d40388..a2bbfee 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
@@ -27,7 +27,6 @@ import java.util.NoSuchElementException;
import org.rhq.core.domain.criteria.BaseCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
-import org.rhq.core.domain.util.PageOrdering;
/** This class provides a way to make PageList results easily iterable with 'for each','while',etc. loops
* and importantly automatically handles iteration through all PageControl results. This
@@ -62,17 +61,6 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
public CriteriaQuery(C criteria, CriteriaQueryExecutor<T, C> queryExecutor) {
this.criteria = criteria;
this.queryExecutor = queryExecutor;
-
- // make sure we have at least a default sort, otherwise chunking doesn't work
- PageControl pageControlOverrides = this.criteria.getPageControlOverrides();
- if (null != pageControlOverrides) {
- if (pageControlOverrides.getOrderingFields().isEmpty()) {
- pageControlOverrides.addDefaultOrderingField("id");
- }
-
- } else if (this.criteria.getOrderingFieldNames().isEmpty()) {
- this.criteria.addSortId(PageOrdering.ASC);
- }
}
/** Returns iterator for a single page of results as defined by
@@ -110,7 +98,8 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
public QueryResultsIterator(PageList<T> firstPage) {
currentPage = firstPage;
iterator = currentPage.iterator();
- count = firstPage == null || firstPage.getPageControl() == null ? 0 : firstPage.getPageControl().getStartRow();
+ count = firstPage == null || firstPage.getPageControl() == null ? 0 : firstPage.getPageControl()
+ .getStartRow();
}
@Override
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index d1d2f73..574fe73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -951,6 +951,7 @@ public final class CriteriaQueryGenerator {
} else {
pc = new PageControl(criteria.getPageNumber(), criteria.getPageSize());
}
+
for (String fieldName : criteria.getOrderingFieldNames()) {
for (Field sortField : getFields(criteria, Criteria.Type.SORT)) {
if (sortField.getName().equals(fieldName) == false) {
@@ -969,6 +970,15 @@ public final class CriteriaQueryGenerator {
}
}
}
+
+ // Unless paging is unlimited or it's not supported, add a sort on ID. This ensures that when paging
+ // we always have a consistent ordering. In other words, if the data set is unchanged between pages, there
+ // will no overlap/repetition of rows. Note that this applies even if other sort fields have been
+ // set, because they may still not have unique values. See https://bugzilla.redhat.com/show_bug.cgi?id=966665.
+ if (!pc.isUnlimited() && criteria.isSupportsAddSortId()) {
+ pc.addDefaultOrderingField("id");
+ }
+
return pc;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
index 2e1c897..b1f5272 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
@@ -24,11 +24,15 @@ import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
+import org.testng.AssertJUnit;
import org.testng.annotations.Test;
import org.rhq.core.domain.criteria.Criteria;
+import org.rhq.core.domain.criteria.JPADriftCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
public class CriteriaQueryTest {
@@ -229,4 +233,22 @@ public class CriteriaQueryTest {
assert e.getMessage().contains("NonUniqueResultException");
}
}
+
+ @Test
+ public void testAddSort() {
+ try {
+ JPADriftCriteria c = new JPADriftCriteria();
+ c.addSortId(PageOrdering.ASC);
+ AssertJUnit.fail("Should have thrown exception");
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+
+ ResourceCriteria c = new ResourceCriteria();
+ c.addSortName(PageOrdering.ASC);
+
+ assertEquals(2, CriteriaQueryGenerator.getPageControl(c).getOrderingFields().size());
+ assertEquals("name", CriteriaQueryGenerator.getPageControl(c).getOrderingFields().get(0).getField());
+ assertEquals("id", CriteriaQueryGenerator.getPageControl(c).getOrderingFields().get(1).getField());
+ }
}
commit 6613ba3db6f3c57c2d2ecac4823e368269a07152
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 15:40:51 2013 -0400
Use only apache logger and not the jboss logger from the base class.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
index d89c04b..b83a037 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
@@ -84,7 +84,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
- debugEnabled = log.isDebugEnabled();
+ debugEnabled = LOG.isDebugEnabled();
super.initialize(subject, callbackHandler, sharedState, options);
@@ -101,14 +101,14 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
}
if (debugEnabled) {
- log.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
+ LOG.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
}
// Now create the context for later use
try {
loginContext = new LoginContext(delegateTo, new DelegateCallbackHandler());
} catch (LoginException e) {
- log.warn("Initialize failed : " + e.getMessage());
+ LOG.warn("Initialize failed : " + e.getMessage());
}
}
@@ -123,7 +123,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
@Override
public boolean login() throws LoginException {
try {
- // Get the username / password the user entred and save if for later use
+ // Get the username / password the user entered and save if for later use
usernamePassword = super.getUsernameAndPassword();
// Try to log in via the delegate
@@ -141,7 +141,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
loginOk = true;
if (debugEnabled) {
- log.debug("Login ok for " + usernamePassword[0]);
+ LOG.debug("Login ok for " + usernamePassword[0]);
}
return true;
commit dfa94acdf6e92526bf35f08ebd2199c3c4c4db87
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 24 23:56:54 2013 +0200
Bug 920214 - [as7] add async avail check support to AS7 plugin
Only applies to server level resource (Standalone, Domain and Managed servers)
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 5f538b7..d85e7e3 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -617,6 +617,7 @@
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
</includes>
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index b80a39a..5d540fd 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -16,6 +16,7 @@
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
@@ -40,6 +41,8 @@ import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.availability.AvailabilityCollectorRunnable;
+import org.rhq.core.pluginapi.availability.AvailabilityFacet;
import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -81,7 +84,8 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
private LogFileEventResourceComponentHelper logFileEventDelegate;
private StartScriptConfiguration startScriptConfig;
private ServerPluginConfiguration serverPluginConfig;
- private AvailabilityType lastAvail;
+ private AvailabilityType previousAvailabilityType;
+ private AvailabilityCollectorRunnable availabilityCollector;
@Override
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
@@ -89,38 +93,69 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
serverPluginConfig = new ServerPluginConfiguration(pluginConfiguration);
connection = ASConnection.newInstanceForServerPluginConfiguration(serverPluginConfig);
+ // The availabilityCollector is still null at this point. So this call will always perform a real availability
+ // check and throw InvalidPluginConfigurationException as needed.
getAvailability();
logFileEventDelegate = new LogFileEventResourceComponentHelper(context);
logFileEventDelegate.startLogFileEventPollers();
startScriptConfig = new StartScriptConfiguration(pluginConfiguration);
+
+ Integer availabilityCheckPeriod = null;
+ try {
+ availabilityCheckPeriod = serverPluginConfig.getAvailabilityCheckPeriod();
+ } catch (NumberFormatException e) {
+ log.error("Avail check period config prop was not a valid number. Cause: " + e);
+ }
+ if (availabilityCheckPeriod != null) {
+ long availCheckMillis = availabilityCheckPeriod * 1000L;
+ this.availabilityCollector = resourceContext.getAvailabilityContext().createAvailabilityCollectorRunnable(
+ new AvailabilityFacet() {
+ public AvailabilityType getAvailability() {
+ return getAvailabilityNow();
+ }
+ }, availCheckMillis);
+ this.availabilityCollector.start();
+ }
}
@Override
public void stop() {
logFileEventDelegate.stopLogFileEventPollers();
- lastAvail = null;
+ previousAvailabilityType = null;
+ if (this.availabilityCollector != null) {
+ this.availabilityCollector.stop();
+ this.availabilityCollector = null;
+ }
}
@Override
public AvailabilityType getAvailability() {
- AvailabilityType avail;
+ if (this.availabilityCollector != null) {
+ return this.availabilityCollector.getLastKnownAvailability();
+ } else {
+ return getAvailabilityNow();
+ }
+ }
+
+ private AvailabilityType getAvailabilityNow() {
+ AvailabilityType availabilityType;
try {
readAttribute("launch-type");
- avail = AvailabilityType.UP;
+ availabilityType = AvailabilityType.UP;
} catch (Exception e) {
- avail = AvailabilityType.DOWN;
+ availabilityType = AvailabilityType.DOWN;
}
try {
- if ((avail == AvailabilityType.UP) && (lastAvail != AvailabilityType.UP)) {
+ if ((availabilityType == AvailabilityType.UP) && (previousAvailabilityType != AvailabilityType.UP)) {
validateServerAttributes();
log.info(getResourceDescription() + " has just come UP.");
}
} finally {
- lastAvail = avail;
+ previousAvailabilityType = availabilityType;
}
- return avail;
+ return availabilityType;
}
private void validateServerAttributes() throws InvalidPluginConfigurationException {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
index e7fcd5b..4f0ea36 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.AVAIL_CHECK_PERIOD_CONFIG_PROP;
+
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
@@ -30,6 +33,8 @@ import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.availability.AvailabilityCollectorRunnable;
+import org.rhq.core.pluginapi.availability.AvailabilityFacet;
import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -51,6 +56,7 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
private static final String MANAGED_SERVER_TYPE_NAME = "Managed Server";
private LogFileEventResourceComponentHelper logFileEventDelegate;
+ private AvailabilityCollectorRunnable availabilityCollector;
@Override
public void start(ResourceContext<HostControllerComponent<?>> hostControllerComponentResourceContext)
@@ -59,13 +65,34 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
logFileEventDelegate = new LogFileEventResourceComponentHelper(context);
logFileEventDelegate.startLogFileEventPollers();
+
+ Integer availabilityCheckPeriod = null;
+ try {
+ availabilityCheckPeriod = pluginConfiguration.getSimple(AVAIL_CHECK_PERIOD_CONFIG_PROP).getIntegerValue();
+ } catch (NumberFormatException e) {
+ log.error("Avail check period config prop was not a valid number. Cause: " + e);
+ }
+ if (availabilityCheckPeriod != null) {
+ long availCheckMillis = availabilityCheckPeriod * 1000L;
+ this.availabilityCollector = hostControllerComponentResourceContext.getAvailabilityContext()
+ .createAvailabilityCollectorRunnable(new AvailabilityFacet() {
+ public AvailabilityType getAvailability() {
+ return getAvailabilityNow();
+ }
+ }, availCheckMillis);
+ this.availabilityCollector.start();
+ }
+
}
@Override
public void stop() {
super.stop();
-
logFileEventDelegate.stopLogFileEventPollers();
+ if (this.availabilityCollector != null) {
+ this.availabilityCollector.stop();
+ this.availabilityCollector = null;
+ }
}
/**
@@ -76,6 +103,14 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
*/
@Override
public AvailabilityType getAvailability() {
+ if (this.availabilityCollector != null) {
+ return this.availabilityCollector.getLastKnownAvailability();
+ } else {
+ return getAvailabilityNow();
+ }
+ }
+
+ private AvailabilityType getAvailabilityNow() {
if (context.getResourceType().getName().equals(MANAGED_SERVER_TYPE_NAME)) {
Address theAddress = new Address();
String host = pluginConfiguration.getSimpleValue("domainHost", "local");
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
index 1433c17..3832ed2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,14 +13,16 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.helper;
import java.io.File;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.modules.plugins.jbossas7.JBossProductType;
/**
@@ -43,6 +45,7 @@ public class ServerPluginConfiguration {
public static final String LOG_DIR = "logDir";
public static final String PRODUCT_TYPE = "productType";
public static final String HOST_CONFIG_FILE = "hostConfigFile";
+ public static final String AVAIL_CHECK_PERIOD_CONFIG_PROP = "availabilityCheckPeriod";
}
private Configuration pluginConfig;
@@ -143,4 +146,14 @@ public class ServerPluginConfiguration {
hostConfigFile.toString() : null);
}
+ public Integer getAvailabilityCheckPeriod() {
+ PropertySimple propertySimple = this.pluginConfig.getSimple(Property.AVAIL_CHECK_PERIOD_CONFIG_PROP);
+ return propertySimple == null ? null : propertySimple.getIntegerValue();
+ }
+
+ public void setAvailabilityCheckPeriod(Integer availabilityCheckPeriod) {
+ this.pluginConfig.setSimpleValue(Property.AVAIL_CHECK_PERIOD_CONFIG_PROP,
+ availabilityCheckPeriod == null ? null : availabilityCheckPeriod.toString());
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index ad22370..7213acd 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -82,6 +82,17 @@
</c:list-property>
</c:group>
'>
+
+ <!ENTITY availabilityCheckPeriod '
+ <c:simple-property name="availabilityCheckPeriod"
+ description="The amount of time, in seconds, that must elapse between availability checks to see if the server is up. If set, the availability checks will be performed asynchronously thus allowing slow-responding servers to avoid being falsely reported as down. Minimum value is 60 seconds."
+ units="seconds" required="false" type="integer">
+ <c:constraint>
+ <c:integer-constraint minimum="60"/>
+ </c:constraint>
+ </c:simple-property>
+'>
+
<!ENTITY serverKindMetrics '
<metric property="_skm:release-codename" dataType="trait" displayName="Server Code Name"/>
<metric property="_skm:release-version" dataType="trait" displayName="Server Version"/>
@@ -862,6 +873,10 @@
&startScriptPluginConfigGroup;
&logSources;
+
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<process-scan name="HostController" query="process|basename|match=^java.*,arg|org.jboss.as.host-controller|match=.*"/>
@@ -1173,6 +1188,10 @@
&startScriptPluginConfigGroup;
&logSources;
+
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<process-scan name="StandaloneAS" query="process|basename|match=^java.*,arg|org.jboss.as.standalone|match=.*"/>
@@ -1621,6 +1640,9 @@
<plugin-configuration>
<c:simple-property name="path" readOnly="true"/>
&logSources;
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<operation name="start" description="Start this server instance." displayName="Start">
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
index 43e6e06..8c61c8e 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.itest;
+import static org.rhq.core.domain.measurement.AvailabilityType.UP;
+import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.Set;
@@ -31,8 +34,10 @@ import org.rhq.core.domain.util.ResourceFilter;
import org.rhq.core.domain.util.ResourceUtility;
import org.rhq.core.domain.util.TypeAndKeyResourceFilter;
import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.plugin.testutil.AbstractAgentPluginTest;
import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration;
import org.rhq.modules.plugins.jbossas7.itest.domain.DomainServerComponentTest;
import org.rhq.modules.plugins.jbossas7.itest.standalone.StandaloneServerComponentTest;
import org.rhq.test.arquillian.AfterDiscovery;
@@ -152,4 +157,26 @@ public abstract class AbstractJBossAS7PluginTest extends AbstractAgentPluginTest
return serverResource;
}
+ protected void testAsynchronousAvailabilityCheck(Resource resource) throws Exception {
+ // Activate asynchronous availability checking
+ ServerPluginConfiguration serverPluginConfig = new ServerPluginConfiguration(resource.getPluginConfiguration());
+ int availabilityCheckPeriod = 65;
+ serverPluginConfig.setAvailabilityCheckPeriod(availabilityCheckPeriod);
+ restartResourceComponent(resource);
+
+ Thread.sleep((3 * availabilityCheckPeriod * 1000L) / 2);
+ assertEquals(getAvailability(resource), UP);
+
+ // Deactivate asynchronous availability checking as subsequent tests may rely on immediate availabilty checking
+ serverPluginConfig.setAvailabilityCheckPeriod(null);
+ restartResourceComponent(resource);
+ }
+
+ private void restartResourceComponent(Resource resource) throws PluginContainerException {
+ InventoryManager inventoryManager = this.pluginContainer.getInventoryManager();
+ inventoryManager.deactivateResource(resource);
+ ResourceContainer serverContainer = inventoryManager.getResourceContainer(resource);
+ inventoryManager.activateResource(resource, serverContainer, true);
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
index 4effd50..91ece92 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,9 +13,10 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.itest.domain;
import java.io.File;
@@ -76,14 +77,20 @@ public class DomainServerComponentTest extends AbstractServerComponentTest {
testServerAttributeValidation();
}
+ @Test(priority = 1002)
+ public void testDomainServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getServerResource());
+ }
+
+
// ******************************* METRICS ******************************* //
- @Test(priority = 1002, enabled = true)
+ @Test(priority = 1003, enabled = true)
public void testDomainReleaseVersionTrait() throws Exception {
super.testReleaseVersionTrait();
}
// ******************************* OPERATIONS ******************************* //
- @Test(priority = 1003, enabled = true)
+ @Test(priority = 1004, enabled = true)
public void testDomainServerShutdownAndStartOperations() throws Exception {
super.testShutdownAndStartOperations();
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
index 3f9f101..42bab08 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest.domain;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.PluginContainerException;
@@ -32,9 +35,6 @@ import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
import org.rhq.test.arquillian.RunDiscovery;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
/**
* Test dealing with managed servers
* @author Heiko W. Rupp
@@ -45,7 +45,7 @@ public class ManagedServerTest extends AbstractJBossAS7PluginTest {
public static final ResourceType RESOURCE_TYPE = new ResourceType("Managed Server", PLUGIN_NAME, ResourceCategory.SERVER, null);
private static final String RESOURCE_KEY = "master/server-one";
- @Test(priority = 1020, groups = "discovery", enabled = false)
+ @Test(priority = 1020, groups = "discovery", enabled = true)
@RunDiscovery(discoverServices = true, discoverServers = true)
public void runDiscovery() throws Exception {
Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
@@ -93,6 +93,11 @@ public class ManagedServerTest extends AbstractJBossAS7PluginTest {
assertEquals(avail, AvailabilityType.UP);
}
+ @Test(priority = 1022)
+ public void testManagedServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getResource());
+ }
+
private Resource getResource() {
InventoryManager im = pluginContainer.getInventoryManager();
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
index 9845b03..8446345 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest.standalone;
+import static org.rhq.core.domain.measurement.AvailabilityType.UP;
+import static org.testng.Assert.assertEquals;
+
import java.io.File;
import java.util.Arrays;
import java.util.List;
@@ -38,8 +41,6 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.modules.plugins.jbossas7.itest.AbstractServerComponentTest;
import org.rhq.test.arquillian.RunDiscovery;
-import static org.testng.Assert.assertEquals;
-
/**
* Test discovery and facets of the "JBossAS7 Standalone Server" Resource type.
*
@@ -105,20 +106,20 @@ public class StandaloneServerComponentTest extends AbstractServerComponentTest {
}
// TODO: Re-enable once fixed.
- @Test(priority = 5, dependsOnMethods = "testStandaloneServerShutdownAndStartOperations", enabled = false)
+ @Test(priority = 6, dependsOnMethods = "testStandaloneServerShutdownAndStartOperations", enabled = false)
public void testRestartOperation() throws Exception {
// First make sure the server is up.
AvailabilityType avail = getAvailability(getServerResource());
- assertEquals(avail, AvailabilityType.UP);
+ assertEquals(avail, UP);
// Make sure the server is back up.
// TODO (ips): Check that the server is a different process now.
invokeOperationAndAssertSuccess(getServerResource(), RESTART_OPERATION_NAME, null);
avail = getAvailability(getServerResource());
- assertEquals(avail, AvailabilityType.UP);
+ assertEquals(avail, UP);
}
- @Test(priority = 6, enabled = true)
+ @Test(priority = 7, enabled = true)
public void testSystemPropertiesSettings() throws Exception {
Configuration config = loadResourceConfiguration(getServerResource());
@@ -152,6 +153,11 @@ public class StandaloneServerComponentTest extends AbstractServerComponentTest {
}
+ @Test(priority = 8)
+ public void testStandaloneServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getServerResource());
+ }
+
protected String getExpectedStartScriptFileName() {
return (File.separatorChar == '/') ? "standalone.sh" : "standalone.bat";
}
commit 64c225a14337769a1f6ce1df40a9e025ee3258e0
Merge: 078a2da e87ea03
Author: Jirka Kremser <jiri.kremser(a)gmail.com>
Date: Fri May 24 14:40:00 2013 -0700
Merge pull request #1 from lzoubek/master
Merging the rhq bot improvements
commit 078a2da4e488645284359940e3df7a61a0299109
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri May 24 16:43:50 2013 +0200
[BZ 965833 - Potential bug in join/fetch/avoidance code]
It is now possible to lazily fetch fields defined in super classes.
The avoidance of the join-fetch with limits exposed a missing feature that
was present in the code from the day one. It would be failing if the
criteria query was used to fetch a custom object (i.e. not the primary
persistent class of the criteria object) using an "altered projection" and
a fetch would be set on a field defined in a super class of the persistent
class of the criteria object. Only by chance this has never happened
before, because we don't use the altered projections on the criteria
queries that often.
Now that we lazily fetch fields much more often (to avoid join fetch
with limits) this is a problem even in cases without an altered projection.
The fix is fortunately very simple - we need to also search the
superclasses of the criteria's persistent class when looking for a field
to lazily fetch.
The possibility of fields being present in super-classes was taken into
account on other places in the CriteriaQueryGenerator class, too.
Documentation on the getJoinFetchFields() and alterProjection() was
enhanced to hopefully better explain the conditions underwhich you can
combine fetching and altered projection together.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index 867ea16..d1d2f73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -343,7 +343,7 @@ public final class CriteriaQueryGenerator {
} else {
if (this.projection == null) {
/*
- * if not altering the projection, join fetching can be using
+ * if not altering the projection, join fetching can be used
* to retrieve the associated instance in the same SELECT
*
* We further avoid a JOIN FETCH when executing queries with limits.
@@ -664,14 +664,9 @@ public final class CriteriaQueryGenerator {
}
private boolean isPersistentBag(String fieldName) {
- try {
- Class<?> persistentClass = criteria.getPersistentClass();
- Field field = persistentClass.getDeclaredField(fieldName);
+ Field field = findField(fieldName);
- return isAList(field) && !field.isAnnotationPresent(IndexColumn.class);
- } catch (NoSuchFieldException e) {
- return false;
- }
+ return field != null && isAList(field) && !field.isAnnotationPresent(IndexColumn.class);
}
private boolean isAList(Field field) {
@@ -690,23 +685,40 @@ public final class CriteriaQueryGenerator {
}
private void addPersistentBag(String fieldName) {
- try {
- Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
- persistentBagFields.add(field);
- } catch (NoSuchFieldException e) {
- LOG.warn("Failed to add persistent bag collection on class [" + criteria.getPersistentClass().getName() +"]: ", e);
+ Field f = findField(fieldName);
+ if (f == null) {
+ LOG.warn(
+ "Failed to add persistent bag collection [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() +
+ "]. There doesn't seem to be a field of that name on the class or any of its superclasses.");
+ } else {
+ persistentBagFields.add(f);
}
}
private void addJoinFetch(String fieldName) {
- try {
- Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
- joinFetchFields.add(field);
- } catch (NoSuchFieldException e) {
- LOG.warn("Failed to add join fetch field on class [" + criteria.getPersistentClass().getName() + "]: ", e);
+ Field f = findField(fieldName);
+ if (f == null) {
+ LOG.warn(
+ "Failed to add join fetch field [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() +
+ "]. There doesn't seem to be a field of that name on the class or any of its superclasses.");
+ } else {
+ joinFetchFields.add(f);
}
}
+ private Field findField(String fieldName) {
+ Class<?> cls = criteria.getPersistentClass();
+ while (cls != null) {
+ try {
+ return cls.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ cls = cls.getSuperclass();
+ }
+ }
+
+ return null;
+ }
+
/**
* <strong>Note:</strong> This method should only be called after {@link #getQueryString(boolean)}} because it is
* that method where the persistentBagFields property is initialized.
@@ -718,6 +730,21 @@ public final class CriteriaQueryGenerator {
return persistentBagFields;
}
+ /**
+ * <strong>Note:</strong> This method should only be called after {@link #getQueryString(boolean)}} because it is
+ * that method where the persistentBagFields property is initialized.
+ * <p/>
+ * The elements of the returned list are a (sub)set of the fields that the criteria object specified to be fetched
+ * (using the fetchXXX() methods). If the {@link CriteriaQueryRunner} is not set to automatically fetch all the
+ * fields, you need to manually initialize these fields by for example using
+ * {@link CriteriaQueryRunner#initFetchFields(Object)} method on each of the results.
+ *
+ * @see #alterProjection(String) <code>alterProjection(String)</code> for special attention you need to make when
+ * mixing fetching fields and altered projection.
+ *
+ * @return Returns a list of fields from the persistent class to which the criteria class corresponds. The fields in
+ * the list are fields specified by the criteria to be fetched (using the fetchXXX() methods).
+ */
public List<Field> getJoinFetchFields() {
return joinFetchFields;
}
@@ -728,8 +755,11 @@ public final class CriteriaQueryGenerator {
* only affect the ResultSet for the data query, not the count query.
* <p/>
* If you are projecting a composite object that does not directly extend the entity your Criteria object
- * represents, then you will need to manually initialize the persistent bags using the methods exposed on
- * {@link CriteriaQueryRunner}
+ * represents, then you will need to manually initialize the persistent bags and fetch fields using the
+ * {@link CriteriaQueryRunner#initFetchFields(Object)} method for each object in the results (for which you need
+ * to instantiate the {@link CriteriaQueryRunner} with automatic fetching switched OFF). <b>Note</b> that this will
+ * NOT work on the composite object itself. You need to pass an instance of the entity class to the
+ *{@link CriteriaQueryRunner#initFetchFields(Object)} method.
*/
public void alterProjection(String projection) {
this.projection = projection;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
index a788fb0..73292be 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
@@ -129,9 +129,7 @@ public class CriteriaQueryRunner<T> {
public void initFetchFields(Object entity) {
initPersistentBags(entity);
- if (queryGenerator.isProjectionAltered()) {
- initJoinFetchFields(entity);
- }
+ initJoinFetchFields(entity);
}
private void initPersistentBags(Object entity) {
commit e87ea0381518ffda4a42be7a119ce0ab764cd551
Author: Libor Zoubek <lzoubek(a)jezzovo.net>
Date: Fri May 24 16:45:08 2013 +0200
rhq-Bot: only devs can send private echo command to bot
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index 1960f1d..a7b3e78 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -209,8 +209,12 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
String message = privateMessageEvent.getMessage();
Matcher echoMatcher = ECHO_PATTERN.matcher(message);
if (echoMatcher.matches()) {
- String echoMessage = echoMatcher.group(1);
- bot.sendMessage(this.channel, echoMessage);
+ if (!JON_DEVS.contains(privateMessageEvent.getUser().getNick())) {
+ privateMessageEvent.respond("You're not my master, I am your master, go away");
+ } else {
+ String echoMessage = echoMatcher.group(1);
+ bot.sendMessage(this.channel, echoMessage);
+ }
} else if (message.equalsIgnoreCase(Command.PREFIX + "listrenames")) {
//Generate a list of renames in the form of old1 changed to new1, old2 changed to new2, etc
StringBuilder users = new StringBuilder();
commit 66c47dde1721632eca6990d389195708e8deeefe
Author: Libor Zoubek <lzoubek(a)jezzovo.net>
Date: Fri May 24 16:40:57 2013 +0200
ircBot: improved recognition of commands
Bot now recognizes commands only when in the beginning of message or if you
highlight bot's nick and command is the very first word (like rhq-bot:
!help)
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index cd6d43a..1960f1d 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -61,7 +61,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
SUPPORT,
WIKI("Our wiki is available from https://docs.jboss.org/author/display/RHQ/Home", true);
- public static final char PREFIX = '!';
+ public static final String PREFIX = "!";
private final String staticRespond;
private final boolean includeInHelp;
@@ -106,7 +106,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
this.channel = channel;
isRedHatChannel = "irc.devel.redhat.com".equals(channel);
StringBuilder commandRegExp = new StringBuilder();
- commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
+ commandRegExp.append("^(?i)[ ]*").append(Command.PREFIX).append("(");
for (Command command : Command.values()) {
commandRegExp.append(command.name()).append('|');
}
@@ -173,6 +173,11 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
}
+ if (message.startsWith(event.getBot().getNick())) {
+ // someone asked bot directly, we have to remove that from message
+ message = message.substring(event.getBot().getNick().length());
+ message = message.replaceFirst("[^ ]*", "");
+ }
// react to commands included in the messages
Matcher commandMatcher = commandPattern.matcher(message);
while (commandMatcher.find()) {
commit adac13e48ddd26aa55b6a6cbc6f3c3bcff5f802e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 24 11:14:44 2013 +0200
Add some translations
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 057785a..d158243 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -10,25 +10,25 @@
#
###################################
##avail_chart_down_label = DOWN
-##avail_chart_title_label = Availability
+avail_chart_title_label = Verfügbarkeit
##avail_chart_up_label = UP
-##chart_date_label = Date
+chart_date_label = Datum
##chart_down_label = Down
##chart_time_label = Start
-##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
-##chart_title_avg_label = Avg
-##chart_title_min_label = Min
-##chart_title_peak_label = Max
-##chart_hover_availability_label = Availability
-##chart_hover_availability_type_warn = MIXED
-##chart_hover_date_format = %m/%d/%y
+chart_unknown_label = Unbekannt
+chart_no_data_label = Keine Daten vorhanden
+chart_title_avg_label = Durchschn.
+chart_title_min_label = Min
+chart_title_peak_label = Max
+chart_hover_availability_label = Verfügbarkeit
+chart_hover_availability_type_warn = Gemischt
+chart_hover_date_format = %d.%m.%y
##chart_hover_time_format = %I:%M:%S %p
-##chart_ie_not_supported = Charting is not available for this browser.
-##chart_hover_start_label = Start
-##chart_hover_end_label = End
+chart_ie_not_supported = Charting ist bei diesem Browser nicht unterstützt
+chart_hover_start_label = Start
+chart_hover_end_label = Ende
##chart_hover_period_label = Period
-##chart_hover_bar_label = Duration
+chart_hover_bar_label = Dauer
common_alert_high = HOCH
common_alert_low = NIEDRIG
common_alert_medium = MITTEL
@@ -68,7 +68,7 @@ common_button_schedule = Planen
common_button_search = Suchen
common_button_set = Setzen
common_button_showDetails = Details anzeigen...
-##common_button_unignore = Unignore
+common_button_unignore = Ignorieren aufheben
common_button_uninventory = Aus dem Inventar löschen
common_calendar_april_short = Apr
common_calendar_august_short = Aug
@@ -91,7 +91,7 @@ common_label_filters = Filter
common_label_hour = Stunde
common_label_item = Eintrag
common_label_items = Einträge
-##common_label_link = Link
+common_label_link = Link
common_label_month = Monat
common_label_none = keine
common_label_none2 = keines
@@ -128,7 +128,7 @@ common_status_nochange = Keine Änderung
common_status_partial = partiell
common_status_success = Erfolg
common_status_unknown = Unbekannt
-##common_title_acknowledged = Acknowledged
+common_title_acknowledged = Bestätigt
common_title_add_column = Spalte hinzufügen
common_title_add_portlet = Portlet hinzufügen
common_title_address = Adresse
@@ -418,7 +418,7 @@ favorites_recentlyViewed = Kürzlich angesehen
favorites_resources = Gemerkte Ressourcen
filter_from_date = Von
filter_to_date = Bis
-##group_tree_groupOfResourceType = Group of [{0}]
+group_tree_groupOfResourceType = Gruppe von [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
util_errorHandler_nullException = Exception war null
@@ -441,8 +441,8 @@ view_adminConfig_agentPlugins = Agent Plugins
view_adminConfig_alertDefTemplates = Vorlagen für Alarmdefinitionen
view_adminConfig_downloads = Downloads
view_adminConfig_driftDefTemplates = Vorlagen für Dritf-Definitionen
-##view_adminConfig_ignoreResourceTypes = Ignored Resource Types
-##view_adminConfig_ignoreResourceTypes_changeTitle = Change?
+view_adminConfig_ignoreResourceTypes = Ignorierte Ressource Typen
+view_adminConfig_ignoreResourceTypes_changeTitle = Ändern?
##view_adminConfig_ignoreResourceTypes_confirmIgnore = Are you sure you want to ignore the resource type [{0}]? You will no longer be able to import resources of this type and any resources of this type that are already in inventory will be uninventoried and you can no longer manage them.
##view_adminConfig_ignoreResourceTypes_confirmUnignore = Are you sure you want to unignore the resource type [{0}]? Any resources of this type that exist in your managed environment will be able to be discovered and inventoried.
##view_adminConfig_ignoreResourceTypes_failure = Failed to set the ignore flag on the selected resource type.
@@ -456,7 +456,7 @@ view_adminConfig_systemSettings = Systemeinstellungen
view_adminContent_contentSources = Quellen für Inhalte
view_adminRoles_assignedGroups = Zugewiesene Ressourcen-Gruppen
view_adminRoles_assignedSubjects = Zugewisene Benutzer
-##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name.
+view_adminRoles_failCreateRoleWithExistingName = Konnte die Rolle mit dem existierenden Namen [{0}] nicht anlegen. Bitte wählen Sie einen anderen Namen.
view_adminRoles_failLdap = Konnte nicht ermitteln, ob LDAP konfiguriert ist - gehe von keiner LDAP-Konfiguration aus.
view_adminRoles_failLdapGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt.
view_adminRoles_failLdapGroupsRole = Konnte die LDAP-Gruppen für die Rolle nicht laden.
@@ -526,23 +526,23 @@ view_adminTemplates_pluginTemplates = Vorlagen für Plugins Plugins
view_adminTemplates_servers = Server
view_adminTemplates_userTemplates = Nutzers-spezifische Vorlagen
view_adminTopology_affinityGroups = Affinitätsgruppen
-##view_adminTopology_affinityGroups_agentCount = Agent Count
-##view_adminTopology_affinityGroups_agentsInThisGroup = Agents in This Group
+view_adminTopology_affinityGroups_agentCount = Anzahl Agenten
+view_adminTopology_affinityGroups_agentsInThisGroup = Agenten in dieser Gruppe
##view_adminTopology_affinityGroups_agentsNotPartOfAnAffinityGroup = Agents not Part of an Affinity Group
##view_adminTopology_affinityGroups_agetnMembers = Agent Members
-##view_adminTopology_affinityGroups_createNew = Create New
+view_adminTopology_affinityGroups_createNew = Neu anlegen
##view_adminTopology_affinityGroups_details = Affinity Group Details
-##view_adminTopology_affinityGroups_removeSelected = Remove Selected
-##view_adminTopology_affinityGroups_serverCount = Server Count
+view_adminTopology_affinityGroups_removeSelected = Ausgewählte entfernen
+view_adminTopology_affinityGroups_serverCount = Anzahl Server
##view_adminTopology_affinityGroups_serverMembers = Server Members
-##view_adminTopology_agentDetail_address = Address
+view_adminTopology_agentDetail_address = Adresse
##view_adminTopology_agentDetail_agentFailoverList = Agent Failover List
-##view_adminTopology_agentDetail_currentServer = Current Server
+view_adminTopology_agentDetail_currentServer = Aktueller Server
##view_adminTopology_agentDetail_token = Token
##view_adminTopology_agent_agentBindAddress = Agent Bind Address
##view_adminTopology_agent_agentBindPort = Agent Bind Port
-##view_adminTopology_agent_agentName = Agent Name
-##view_adminTopology_agent_connectedServer = Connected Server
+view_adminTopology_agent_agentName = Name des Agenten
+view_adminTopology_agent_connectedServer = Verbundener Server
##view_adminTopology_agent_delete_confirm = This will deregister the selected agents and uninventory their corresponding platforms and all other resources associated with them. There is no way to undo this action. Are you sure you want to do this?
##view_adminTopology_agent_lastAvailabilityPing = Last Availability Ping
##view_adminTopology_agent_lastAvailabilityReport = Last Availability Report
@@ -592,7 +592,7 @@ view_adminTopology_partitionEvents = Partitionierungs-Ereignisse
##view_adminTopology_partitionEventsDetail_eventDetails = Event Details
##view_adminTopology_partitionEventsDetail_eventExecutionTime = Event Execution Time
##view_adminTopology_partitionEventsDetail_eventType = Event Type
-##view_adminTopology_partitionEvents_details = Details
+view_adminTopology_partitionEvents_details = Details
##view_adminTopology_partitionEvents_detailsFilter = Details Filter
##view_adminTopology_partitionEvents_execStatusFilter = Execution Status Filter
##view_adminTopology_partitionEvents_execTime = Execution Time
@@ -600,7 +600,7 @@ view_adminTopology_partitionEvents = Partitionierungs-Ereignisse
##view_adminTopology_partitionEvents_forceRepartition = Force Repartition
##view_adminTopology_partitionEvents_initiatedBy = Initiated By
##view_adminTopology_partitionEvents_purgeAll = Purge All
-##view_adminTopology_partitionEvents_type = Type
+view_adminTopology_partitionEvents_type = Typ
##view_adminTopology_partitionEvents_typeFilter = Type Filter
view_adminTopology_remoteAgentInstall = Installation entfernter Agenten
##view_adminTopology_serverDetail_connectedAgents = Connected Agents
@@ -610,7 +610,7 @@ view_adminTopology_remoteAgentInstall = Installation entfernter Agenten
##view_adminTopology_server_agentCount = Agent Count
##view_adminTopology_server_endpointAddress = Endpoint Address
##view_adminTopology_server_lastUpdateTime = Last Update Time
-##view_adminTopology_server_mode = Mode
+view_adminTopology_server_mode = Modus
##view_adminTopology_server_nonSecurePort = Nonsecure Port
##view_adminTopology_server_removeSelected = Remove Selected
##view_adminTopology_server_securePort = Secure Port
@@ -728,15 +728,15 @@ view_admin_systemSettings_serverDetails_dbUrl = URL der Datenbankverbindung
view_admin_systemSettings_serverDetails_dbVersion = Produktversion der Datenbank
view_admin_systemSettings_serverDetails_installDir = Installationsverzeichnis des Servers
view_admin_systemSettings_serverDetails_nextRotation = Nächste Rotation der Metrik-Tabellen
-##view_admin_systemSettings_serverDetails_productName = Product Name
-##view_admin_systemSettings_serverDetails_serverName = Server Name
+view_admin_systemSettings_serverDetails_productName = Produktname
+view_admin_systemSettings_serverDetails_serverName = Servername
view_admin_systemSettings_serverDetails_time = Lokale Zeit des Servers
view_admin_systemSettings_serverDetails_tz = Zeitzone des Servers
view_admin_topology = Topologie
view_alert_common_tab_conditions = Bedingungen
view_alert_common_tab_conditions_expression = Alarm auslösen wenn
##view_alert_common_tab_conditions_expression_tooltip = Determines if ANY or ALL of the conditions must evaluate to true in order for the entire condition set to be considered true.
-##view_alert_common_tab_conditions_modalEdit_title = Edit Condition
+view_alert_common_tab_conditions_modalEdit_title = Bedingungen ändern
view_alert_common_tab_conditions_modal_title = Bedingung hinzufügen
view_alert_common_tab_conditions_recovery_disabled = Dieser Alarm hat seine Definition deaktiviert.
view_alert_common_tab_conditions_recovery_enabled = Ausgelöst, dass ''{0}'' wieder aktiviert wurde
@@ -883,7 +883,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Änderung de
view_alert_definition_condition_editor_option_operation = Ausführung der Operation
view_alert_definition_condition_editor_option_resource_configuration = Änderung der Konfiguration der Ressource
##view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
-##view_alert_definition_editCondition = Edit Condition
+view_alert_definition_editCondition = Bedingungen ändern
view_alert_definition_for_group = Gruppendefinition ansehen
view_alert_definition_for_type = Vorlage ansehen
view_alert_definition_notification_cliScript_editor_anotherUser = Anderer Benutzer
@@ -892,7 +892,7 @@ view_alert_definition_notification_cliScript_editor_script = Skript
view_alert_definition_notification_cliScript_editor_thisUser = Aktueller Benutzer
view_alert_definition_notification_editor_delete_confirm = Sind Sie sicher, dass sie die ausgewählten Alarm-Benachrichtigungen löschen wollen?
view_alert_definition_notification_editor_field_configuration = Konfiguration
-##view_alert_definition_notification_editor_field_configuration_loadFailed = Failed to get notification configuration preview
+view_alert_definition_notification_editor_field_configuration_loadFailed = Konte die Vorschau der Benachrichtigung nicht laden
view_alert_definition_notification_editor_field_configuration_not_loaded = Unbekannt
view_alert_definition_notification_editor_field_sender = Sender
view_alert_definition_notification_editor_loadFailed = Kann die Alarm-Sender nicht laden
@@ -946,7 +946,7 @@ view_alert_definitions_disable_success = Es wurden {0} Alarm-Definitionen erfolg
view_alert_definitions_enable_confirm = Die ausgewählten Alarm-Definitionen aktivieren?
view_alert_definitions_enable_failure = Konnte die ausgewählten Alarm-Definitionen nicht aktivieren
view_alert_definitions_enable_success = Es wurden {0} Alarm-Definitionen erfolgreich aktiviert
-##view_alert_definitions_leaveUnsaved = Do you want to save the modified alert definition?
+view_alert_definitions_leaveUnsaved = Möchten Sie die geänderte Alarm-Definition speichern?
view_alert_definitions_loadFailed = Konnte die Daten für die Alarm-Definitionen nicht laden
view_alert_definitions_loadFailed_single = Konnte die Daten für die Alarm-Definition mit der id {0}
view_alert_definitions_table_title_group = Alarm-Definitionen für Gruppen
@@ -1184,7 +1184,7 @@ view_bundle_version_backToBundle = Zurück zum Bundle
##view_bundle_version_deleteSuccessful = You successfully deleted the bundle version [{0}]
##view_bundle_version_loadFailure = Failed to load bundle version
view_bundle_versions = Versionen
-##view_charts_time_axis_label = Time
+view_charts_time_axis_label = Zeit
view_configCompare_comparingConfigs = Konfigurationen vergleichen
##view_configCompare_configCompare = Configuration Comparison
view_configEdit_addItem = Eintrag zur Liste hinzufügen
@@ -1483,13 +1483,13 @@ view_inventory_groups_children = Kinder
##view_inventory_groups_deleteSuccessful = You have successfully deleted the selected resource groups
##view_inventory_groups_descendants = Descendants
##view_inventory_groups_loadFailed = Failed to load group composite data
-##view_inventory_ignoredResources = Ignored Resources
+view_inventory_ignoredResources = Ignorierte Ressourcen
view_inventory_mixed = gemischt
view_inventory_platforms = Platformen
view_inventory_problemGroups = Gruppen mit Problemen
##view_inventory_resource_loadFailed = Resource with id [{0}] does not exist or is not accessible
-##view_inventory_resources_deleteConfirm = Are you sure you want to delete the selected resources?
-##view_inventory_resources_deleteFailed = Failed to delete the selected resources
+view_inventory_resources_deleteConfirm = Sind Sie sicher, dass Sie die ausgewählten Ressourcen löschen wollen?
+view_inventory_resources_deleteFailed = Löschen der ausgewählten Ressourcen ist fehlgeschlagen
##view_inventory_resources_deleteSuccessful = A request to perform the resource deletion has been submitted successfully to the agent(s).
##view_inventory_resources_disableSuccessful = You have successfully disabled the selected resources and their children, [{0}] resources.
##view_inventory_resources_ignoreConfirm = Are you sure you want the selected resources to be ignored? They will no longer show up in inventory.
commit 0d6dcd43a16699348430e81a241ae38da6d431af
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu May 23 17:14:50 2013 -0400
Fix test that started failing after the change to remove JOIN FETCH
from Criteria calls that include paging and optional data. It seems the
new approach changes slightly the way the data is returned.
loadDefinition() returns hibernate proxied data. It is not safe to pass
proxies into equals() impls because these typically access fields directly,
not through getters, and therefore bypass the proxied data.
Note that this change in behavior due to the JOIN FETCH fix would only
affect non-client code (like test code or intra-slsb calls) because return
values to client code would already be cleansed of the proxies. The test
is fixed in the same way, by using HibernateDetachUtility to scrub the
proxies before attempting the assertEquals().
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
index 18c7093..4202d6a 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
@@ -57,6 +57,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.test.AssertUtils;
@@ -91,7 +92,7 @@ public class ManageDriftDefinitionsTest extends AbstractDriftServerTest {
deleteEntity(ResourceType.class, DRIFT_NOT_SUPPORTED_TYPE);
}
- public void createDefinitionFromUnpinnedTemplate() {
+ public void createDefinitionFromUnpinnedTemplate() throws Exception {
// first create a template
final DriftDefinition templateDef = new DriftDefinition(new Configuration());
templateDef.setName(NAME_PREFIX + "createUnpinnedDefinition");
@@ -114,6 +115,7 @@ public class ManageDriftDefinitionsTest extends AbstractDriftServerTest {
DriftDefinitionComparator comparator = new DriftDefinitionComparator(
BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS);
+ HibernateDetachUtility.nullOutUninitializedFields(newDef, SerializationType.SERIALIZATION);
assertEquals("The drift definition was not persisted correctly", 0, comparator.compare(definition, newDef));
assertEquals("The template association was not set on the definition", template, newDef.getTemplate());
}
commit 301a28ce97530f69416677a8b8b470e3f157d9bd
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 22:38:18 2013 +0200
Bit of cleanup and testing of alert->ack and alert->purge
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 92d2499..224ab3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -25,12 +25,9 @@ package org.rhq.enterprise.server.rest;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -251,89 +248,8 @@ public class AbstractRestBean {
return result;
}
- protected void putResourceToCache(Resource res) {
- putToCache(res.getId(), Resource.class, res);
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- try {
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
-
- if (null == visibleResources) {
- visibleResources = new HashSet<Integer>();
- }
-
- visibleResources.add(res.getId());
- cache.put(callerKey, visibleResources);
-
- Map<Integer, Integer> childParentMap = (Map<Integer, Integer>) cache.get(META_KEY);
-
- if (null == childParentMap) {
- childParentMap = new HashMap<Integer, Integer>();
- }
- int pid = res.getParentResource() == null ? 0 : res.getParentResource().getId();
- childParentMap.put(res.getId(), pid);
- cache.put(META_KEY, childParentMap);
-
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
- }
-
- protected List<Resource> getResourcesFromCacheByParentId(int pid) {
- List<Integer> candidateIds = new ArrayList<Integer>();
- List<Resource> ret = new ArrayList<Resource>();
-
- // First determine candidate children
- Map<Integer, Integer> childParentMap = (Map<Integer, Integer>) cache.get(META_KEY);
-
- if (null != childParentMap) {
- try {
- for (Map.Entry<Integer, Integer> entry : childParentMap.entrySet()) {
- if (entry.getValue() == pid)
- candidateIds.add(entry.getKey());
- }
- // then see if the current user can see them
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
- Iterator<Integer> iter = candidateIds.iterator();
- while (iter.hasNext()) {
- Integer resId = iter.next();
- if (!visibleResources.contains(resId)) {
- iter.remove();
- }
- }
-
- // Last but not least, get the resources and return them
- for (Integer resId : candidateIds) {
- ret.add(getFromCache(resId, Resource.class));
- }
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
-
- }
- return ret;
- }
-
- protected Resource getResourceFromCache(int resourceid) {
-
- Resource res = null;
- // check if the current user can see the resource
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
- if (null != visibleResources) {
- try {
- if (visibleResources.contains(resourceid)) {
- res = getFromCache(resourceid, Resource.class);
- }
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
- }
-
- return res;
- }
/**
* Remove an item from the cache
@@ -393,6 +309,7 @@ public class AbstractRestBean {
uriBuilder.path("/resource/{id}/children");
uri = uriBuilder.build(res.getId());
link = new Link("children", uri.toString());
+ rwt.addLink(link);
uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/resource/{id}/alerts");
uri = uriBuilder.build(res.getId());
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index acbb492..355adcd 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -1434,6 +1434,8 @@ public class AlertTest extends AbstractBase {
int definitionId = createEmptyAlertDefinition(true);
+ int alertId;
+
// Now add a condition
try {
@@ -1481,7 +1483,7 @@ public class AlertTest extends AbstractBase {
// wait a little
Thread.sleep(5000);
- int alertId =
+ alertId =
given()
.header(acceptJson)
.queryParam("definitionId",definitionId)
@@ -1543,9 +1545,32 @@ public class AlertTest extends AbstractBase {
.when()
.get("/resource/{resourceId}/alerts");
+ if (alertId>0) {
+ // Acknowledge the alert
+ given()
+ .header(acceptWrappedJson)
+ .pathParam("id", alertId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .put("/alert/{id}");
+
+ Thread.sleep(500);
+
+ // purge the alert
+ given()
+ .header(acceptJson)
+ .pathParam("id", alertId)
+ .expect()
+ .statusCode(204)
+ .log().ifError()
+ .when()
+ .delete("/alert/{id}");
+ }
}
-
finally {
+
// delete the definition again
cleanupDefinition(definitionId);
}
commit e290b1316861f301f25cdef2e537751eb5eed689
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu May 23 22:21:32 2013 +0200
rhq irc bot: disabling the !pto and !support commands on Freenode channel
diff --git a/etc/rhq-ircBot/pom.xml b/etc/rhq-ircBot/pom.xml
index 6e66187..a6ab873 100644
--- a/etc/rhq-ircBot/pom.xml
+++ b/etc/rhq-ircBot/pom.xml
@@ -8,7 +8,7 @@
<groupId>org.rhq.etc</groupId>
<artifactId>rhq-ircbot</artifactId>
- <version>1.0</version>
+ <version>1.1</version>
<packaging>jar</packaging>
<name>RHQ IRC Bot</name>
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index 8a7e578..cd6d43a 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -93,6 +93,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
private final String server;
private final String channel;
+ private final boolean isRedHatChannel;
private String docspaceLogin;
private String docspacePassword;
private BugzillaConnector bzConnector = new BugzillaConnector();
@@ -103,6 +104,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
public RhqIrcBotListener(String server, String channel) {
this.server = server;
this.channel = channel;
+ isRedHatChannel = "irc.devel.redhat.com".equals(channel);
StringBuilder commandRegExp = new StringBuilder();
commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
for (Command command : Command.values()) {
@@ -176,7 +178,9 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
while (commandMatcher.find()) {
Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
String response = prepareResponseForCommand(command);
- bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ if (response != null) {
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
}
// ping JON devs
@@ -215,9 +219,12 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
// react to commands included in the messages
Matcher commandMatcher = commandPattern.matcher(message);
while (commandMatcher.find()) {
+ isCommand = true;
Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
String response = prepareResponseForCommand(command);
- bot.sendMessage(privateMessageEvent.getUser(), response);
+ if (response != null) {
+ bot.sendMessage(privateMessageEvent.getUser(), response);
+ }
}
if (!isCommand) {
bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".\n"
@@ -271,8 +278,10 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
}
switch (command) {
case SUPPORT:
+ if (isRedHatChannel)
return whoIsOnSupport(SUPPORT_LINK);
case PTO:
+ if (isRedHatChannel)
return whoIsOnPto(PTO_LINK);
default:
System.err.println("Unknown command:" + command);
commit b33564602373317e5e73adbc71e0521929e0762e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 23 15:04:09 2013 -0400
BZ 962841 962845 fix the resource type admin pages to support types with multiple parents (i.e. types with <runs-inside>)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
index 9b4027e..4f790a1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
@@ -197,14 +197,19 @@ public class AlertDefinitionTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_ENABLED_TEMPLATES, composite.getEnabledAlertCount());
setAttribute(ATTR_DISABLED_TEMPLATES, composite.getDisabledAlertCount());
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED_TEMPLATES, this.getAttributeAsLong(ATTR_ENABLED_TEMPLATES));
+ dup.setAttribute(ATTR_DISABLED_TEMPLATES, this.getAttributeAsLong(ATTR_DISABLED_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
index 143c475..ebb2d9d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
@@ -211,11 +211,8 @@ public class DriftDefinitionTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_PLUGIN_TEMPLATES, composite.getPluginDriftTemplates());
setAttribute(ATTR_USER_TEMPLATES, composite.getUserDriftTemplates());
// If the type has no plugin templates then drift monitoring is not enabled for the type
@@ -223,6 +220,14 @@ public class DriftDefinitionTemplateTypeView extends ResourceTypeTreeView {
setAttribute(ATTRIB_EDIT, ImageManager.getEditDisabledIcon());
}
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_PLUGIN_TEMPLATES, this.getAttributeAsLong(ATTR_PLUGIN_TEMPLATES));
+ dup.setAttribute(ATTR_USER_TEMPLATES, this.getAttributeAsLong(ATTR_USER_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
index 246a71e..91a4ca2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
@@ -182,6 +182,13 @@ public class IgnoreResourceTypesView extends ResourceTypeTreeView {
super(composite, plugin);
setAttribute(ATTR_ENABLED, ImageManager.getAvailabilityIcon(!composite.getType().isIgnored()));
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED, this.getAttribute(ATTR_ENABLED));
+ return dup;
+ }
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
index 19c53d2..e4aa4fe 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
@@ -170,11 +170,8 @@ public class MetricTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_ENABLED_TEMPLATES, composite.getEnabledMetricCount());
setAttribute(ATTR_DISABLED_TEMPLATES, composite.getDisabledMetricCount());
// If the type has no metrics then metric templates are enabled for the type
@@ -182,6 +179,14 @@ public class MetricTemplateTypeView extends ResourceTypeTreeView {
setAttribute(ATTRIB_EDIT, ImageManager.getEditDisabledIcon());
}
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED_TEMPLATES, this.getAttributeAsLong(ATTR_ENABLED_TEMPLATES));
+ dup.setAttribute(ATTR_DISABLED_TEMPLATES, this.getAttributeAsLong(ATTR_DISABLED_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
index 72563c2..e90f398 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
@@ -18,11 +18,14 @@
*/
package org.rhq.enterprise.gui.coregui.client.admin.templates;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.TreeModelType;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.tree.Tree;
@@ -48,7 +51,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
static private final Messages MSG = CoreGUI.getMessages();
public static final String ATTRIB_ID = "id";
- public static final String ATTRIB_PARENT_ID = "parentId";
+ public static final String ATTRIB_CHILDREN = "children";
public static final String ATTRIB_NAME = "name";
public static final String ATTRIB_PLUGIN = "plugin";
public static final String ATTRIB_CATEGORY = "category";
@@ -67,13 +70,18 @@ public abstract class ResourceTypeTreeNodeBuilder {
@Override
public void onSuccess(Map<Integer, ResourceTypeTemplateCountComposite> result) {
+ // result contains all of our resource types, including the parent hierarchy
HashSet<ResourceTypeListGridRecord> platformsRecords;
HashSet<ResourceTypeListGridRecord> platformServicesRecords;
- HashSet<ResourceTypeTreeNode> treeNodes;
+ HashMap<Integer, ResourceTypeTreeNode> serversNodes; // all server nodes (top level and below)
+ HashSet<Integer> topServers; // those servers that are at the root of the tree
+ HashMap<Integer, ArrayList<Integer>> childrenGraph; // defines the children of all server nodes
platformsRecords = new HashSet<ResourceTypeListGridRecord>();
platformServicesRecords = new HashSet<ResourceTypeListGridRecord>();
- treeNodes = new HashSet<ResourceTypeTreeNode>();
+ serversNodes = new HashMap<Integer, ResourceTypeTreeNode>();
+ topServers = new HashSet<Integer>();
+ childrenGraph = new HashMap<Integer, ArrayList<Integer>>();
for (ResourceTypeTemplateCountComposite composite : result.values()) {
ResourceType type = composite.getType();
@@ -84,7 +92,9 @@ public abstract class ResourceTypeTreeNodeBuilder {
platformsRecords.add(getGridRecordInstance(composite));
} else {
// no parents but not a platform - these are our top-level servers
- treeNodes.add(getTreeNodeInstance(composite, type.getPlugin()));
+ ResourceTypeTreeNode node = getTreeNodeInstance(composite, type.getPlugin());
+ topServers.add(node.getResourceTypeId());
+ serversNodes.put(node.getResourceTypeId(), node);
}
} else {
// has parents; if all the direct parents are top level platforms
@@ -106,22 +116,37 @@ public abstract class ResourceTypeTreeNodeBuilder {
if (isPlatformService) {
platformServicesRecords.add(getGridRecordInstance(composite));
-
} else {
- // in some cases, a top level server is limited to which platforms it can run on.
- // therefore, the parents will not be null/empty (as would be the case if the top level
+ // In some cases, a top level server is limited to which platforms it can run on.
+ // Therefore, the parents will not be null/empty (as would be the case if the top level
// server can run on ALL platforms), but instead it will have the subset of platforms
- // the type is valid on. But its the same type - so we only want to show it once. Therefore,
- // once we see a parent that is a top level platform, we don't add the type again for other
- // top level platforms. That's what gotPlatform boolean tracks.
+ // the type is valid on. But its the same type - so we only want to show it once.
+ // This is what gotPlatform tracks - whether we saw a parent platform or not.
+ //
+ // But we also have the case where a server type can run inside multiple parent server types.
+ // We want to show these under all their parents to make it easier for the user to find them.
boolean gotPlatform = false;
for (ResourceType parentType : type.getParentResourceTypes()) {
- boolean isPlatform = (parentType.getCategory() == ResourceCategory.PLATFORM && isEmpty(parentType
+ boolean isParentAPlatform = (parentType.getCategory() == ResourceCategory.PLATFORM && isEmpty(parentType
.getParentResourceTypes()));
- if (!isPlatform || !gotPlatform) {
- treeNodes.add(getTreeNodeInstance(composite, String.valueOf(parentType.getId())));
+ if (!isParentAPlatform || !gotPlatform) {
+ int parentId = parentType.getId();
+ String parentIdString = String.valueOf(parentId);
+ ResourceTypeTreeNode node = getTreeNodeInstance(composite, parentIdString);
+ serversNodes.put(node.getResourceTypeId(), node);
+ if (isParentAPlatform) {
+ topServers.add(node.getResourceTypeId());
+ } else {
+ // we are a child to other type, add it to the list of children
+ ArrayList<Integer> childList = childrenGraph.get(parentId);
+ if (childList == null) {
+ childList = new ArrayList<Integer>();
+ childrenGraph.put(parentId, childList);
+ }
+ childList.add(node.getResourceTypeId());
+ }
}
- if (isPlatform) {
+ if (isParentAPlatform) {
gotPlatform = true;
}
}
@@ -129,14 +154,50 @@ public abstract class ResourceTypeTreeNodeBuilder {
}
}
+ // now set up our UI components to show the data
+ platformsGrid.setSortField(ATTRIB_NAME);
+ platformServicesGrid.setSortField(ATTRIB_NAME);
+ serversGrid.setSortField(ATTRIB_NAME);
+
platformsGrid.setData(platformsRecords.toArray(new ListGridRecord[platformsRecords.size()]));
platformServicesGrid.setData(platformServicesRecords
.toArray(new ListGridRecord[platformServicesRecords.size()]));
- Tree tree = serversGrid.getTree();
- if (tree != null) {
- TreeNode[] treeNodeArray = treeNodes.toArray(new TreeNode[treeNodes.size()]);
- tree.linkNodes(treeNodeArray);
+ Tree tree = new Tree();
+ tree.setModelType(TreeModelType.CHILDREN);
+ tree.setChildrenProperty(ATTRIB_CHILDREN);
+ TreeNode rootNode = new TreeNode("0");
+ tree.setRoot(rootNode);
+
+ for (Integer topServerId : topServers) {
+ ResourceTypeTreeNode topServerNode = serversNodes.get(topServerId);
+ topServerNode = topServerNode.copy();
+ fillHierarchy(topServerNode, serversNodes, childrenGraph);
+ tree.add(topServerNode, rootNode);
}
+ serversGrid.setData(tree);
+ }
+
+ private void fillHierarchy(ResourceTypeTreeNode node,
+ HashMap<Integer, ResourceTypeTreeNode> serversNodes,
+ HashMap<Integer, ArrayList<Integer>> childrenGraph) {
+
+ if (node.getChildren().length > 0) {
+ return; // we've already populated this node's children before; nothing to do
+ }
+
+ ArrayList<Integer> childrenIds = childrenGraph.get(node.getResourceTypeId());
+ if (childrenIds != null) {
+ for (Integer childrenId : childrenIds) {
+ ResourceTypeTreeNode childNode = serversNodes.get(childrenId);
+ if (childNode != null) { // this should never be null, but this let's us continue if we have a bug
+ childNode = childNode.copy();
+ fillHierarchy(childNode, serversNodes, childrenGraph);
+ node.addChild(childNode);
+ }
+ }
+ }
+
+ return;
}
@Override
@@ -184,25 +245,63 @@ public abstract class ResourceTypeTreeNodeBuilder {
public static class ResourceTypeTreeNode extends TreeNode {
- private String id;
+ private int id;
private String parentId;
+ private TreeNode[] children;
+
+ private ResourceTypeTreeNode() {
+ // for use by copy() method
+ }
protected ResourceTypeTreeNode(ResourceTypeTemplateCountComposite composite, String parentId) {
ResourceType resourceType = composite.getType();
- String id = String.valueOf(resourceType.getId());
- setID(id);
- this.id = id;
-
- setParentID(parentId);
+ this.id = resourceType.getId();
this.parentId = parentId;
setAttribute(ATTRIB_ID, id);
- setAttribute(ATTRIB_PARENT_ID, parentId);
setAttribute(ATTRIB_NAME, resourceType.getName());
setAttribute(ATTRIB_PLUGIN, resourceType.getPlugin());
setAttribute(ATTRIB_CATEGORY, resourceType.getCategory().name());
setAttribute(ATTRIB_EDIT, ImageManager.getEditIcon());
+ setChildren(new TreeNode[0]);
+ }
+
+ public int getResourceTypeId() {
+ return this.id;
+ }
+
+ public TreeNode[] getChildren() {
+ return this.children;
+ }
+
+ @Override
+ public void setChildren(TreeNode[] children) {
+ this.children = children;
+ super.setChildren(children);
+ }
+
+ public void addChild(TreeNode newChild) {
+ TreeNode[] newChildren = new TreeNode[this.children.length + 1];
+ System.arraycopy(this.children, 0, newChildren, 0, this.children.length);
+ newChildren[this.children.length] = newChild;
+ setChildren(newChildren);
+ }
+
+ // clone this object and return it - subclasses should override this to copy their own attributes
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = new ResourceTypeTreeNode();
+ dup.id = this.id;
+ dup.parentId = this.parentId;
+ dup.children = this.children;
+
+ dup.setAttribute(ATTRIB_ID, this.getAttributeAsInt(ATTRIB_ID));
+ dup.setAttribute(ATTRIB_NAME, this.getAttribute(ATTRIB_NAME));
+ dup.setAttribute(ATTRIB_PLUGIN, this.getAttribute(ATTRIB_PLUGIN));
+ dup.setAttribute(ATTRIB_CATEGORY, this.getAttribute(ATTRIB_CATEGORY));
+ dup.setAttribute(ATTRIB_EDIT, this.getAttribute(ATTRIB_EDIT));
+
+ return dup;
}
@Override
@@ -216,7 +315,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
ResourceTypeTreeNode that = (ResourceTypeTreeNode) o;
- if (!this.id.equals(that.id)) {
+ if (this.id != that.id) {
return false;
}
if (this.parentId == null) {
@@ -228,7 +327,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
@Override
public int hashCode() {
int result = 31;
- result = result * id.hashCode();
+ result = result * id;
result = result + (parentId != null ? parentId.hashCode() : 0);
return result;
}
commit 6d5e400decd1b55624daedda9a8e0a6814155eda
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 20:40:21 2013 +0200
BZ use explicit paging fields, as there is no default. In the specific case, the 'name' field was not unique and thus 'random within the resources with the same name'
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 4ceae82..305d867 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -79,6 +79,7 @@ import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
@@ -148,11 +149,11 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
public Response listAlertDefinitions(
@ApiParam(value = "Page number") @QueryParam("page") Integer page,
@ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
- @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
+ criteria.addSortId(PageOrdering.ASC);
if (page!=null) {
criteria.setPaging(page,pageSize);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index fd8a835..4f4d6b4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -62,6 +62,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.rest.domain.EventDefinitionRest;
@@ -243,6 +244,7 @@ public class EventHandlerBean extends AbstractRestBean {
EventSource source = findEventSourceById(sourceId);
EventCriteria criteria = new EventCriteria();
+ criteria.addSortId(PageOrdering.ASC);
criteria.addFilterSourceId(source.getId());
if (startTime>0) {
criteria.addFilterStartTime(startTime);
@@ -291,6 +293,8 @@ public class EventHandlerBean extends AbstractRestBean {
}
EventCriteria criteria = new EventCriteria();
+ criteria.addSortId(PageOrdering.ASC);
+
criteria.addFilterResourceId(resourceId);
if (startTime>0) {
criteria.addFilterStartTime(startTime);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index d65a850..006c8a0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -27,8 +27,6 @@ import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
@@ -67,6 +65,7 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupDefinition;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
@@ -105,9 +104,6 @@ public class GroupHandlerBean extends AbstractRestBean {
@EJB
GroupDefinitionManagerLocal definitionManager;
- @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
- EntityManager em;
-
@GZIP
@GET
@@ -119,6 +115,8 @@ public class GroupHandlerBean extends AbstractRestBean {
@Context HttpHeaders headers, @Context UriInfo uriInfo) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
+ criteria.addSortId(PageOrdering.ASC);
+
if (q!=null) {
criteria.addFilterName(q);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 81d490b..d46850c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -401,12 +401,12 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
+ criteria.addSortStartTime(PageOrdering.ASC);
if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
}
if (page!=null) {
criteria.setPaging(page,pageSize);
- criteria.addSortStartTime(PageOrdering.ASC);
}
criteria.addSortEndTime(PageOrdering.DESC);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 0c3a7cd..332dfbc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -188,6 +188,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
@Context UriInfo uriInfo) {
ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addSortName(PageOrdering.ASC);
+ criteria.addSortId(PageOrdering.ASC);
if (!status.toLowerCase().equals("all")) {
try {
criteria.addFilterInventoryStatus(InventoryStatus.valueOf(status.toUpperCase()));
@@ -206,7 +208,6 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
if (page!=null) {
criteria.setPaging(page,pageSize);
- criteria.addSortName(PageOrdering.ASC);
}
PageList<Resource> ret = resMgr.findResourcesByCriteria(caller,criteria);
@@ -232,6 +233,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
else {
pc = PageControl.getUnlimitedInstance();
}
+ pc.setPrimarySort("id",PageOrdering.ASC);
PageList<Resource> ret = resMgr.findResourcesByCategory(caller, ResourceCategory.PLATFORM,
InventoryStatus.COMMITTED, pc);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index cd103ca..900ab10 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -24,11 +24,16 @@ package org.rhq.modules.integrationTests.restApi;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.element.Node;
import com.jayway.restassured.response.Response;
+import com.jayway.restassured.response.ResponseBody;
import org.apache.http.HttpStatus;
import org.junit.Test;
@@ -73,8 +78,8 @@ public class ResourcesTest extends AbstractBase {
.contentType(ContentType.JSON)
.log().everything()
.body("links.self", notNullValue())
- .body("resourceId",is(_platformId))
- .body("typeId",is(_platformTypeId))
+ .body("resourceId", is(_platformId))
+ .body("typeId", is(_platformTypeId))
.body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -94,8 +99,8 @@ public class ResourcesTest extends AbstractBase {
.contentType(WRAPPED_JSON)
.log().everything()
.body("links.self", notNullValue())
- .body("resourceId",is(_platformId))
- .body("typeId",is(_platformTypeId))
+ .body("resourceId", is(_platformId))
+ .body("typeId", is(_platformTypeId))
.body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -277,13 +282,50 @@ public class ResourcesTest extends AbstractBase {
.statusCode(200)
.log().everything()
// .header("Link", allOf(containsString("page=2"), containsString("current")))
- .header("Link",not(containsString("prev")))
+ .header("Link", not(containsString("prev")))
.body("links.self", notNullValue())
.when()
.get("/resource");
}
@Test
+ public void testGetResourcesWithPagingAndUniquenessCheck() throws Exception {
+
+ int currentPage = 0;
+ Set<Integer> seen = new HashSet<Integer>();
+
+ for(;;) {
+ JsonPath path =
+ given()
+ .header("Accept", "application/vnd.rhq.wrapped+json")
+ .with()
+ .queryParam("page", currentPage)
+ .queryParam("ps", 5) // Unusually small to provoke having more than 1 page
+ .queryParam("status","COMMITTED")
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .get("/resource")
+ .jsonPath();
+
+ List<Integer> ids = path.getList("data.resourceId");
+
+ for (Integer id : ids ) {
+ assert !seen.contains(id);
+ seen.add(id);
+ }
+
+ currentPage++;
+ if (currentPage > path.getInt("lastPage")) {
+ break;
+ }
+ System.out.print("+");
+ }
+ System.out.println();
+ }
+
+ @Test
public void testGetResourcesWithPagingAndWrapping() throws Exception {
given()
@@ -314,7 +356,7 @@ public class ResourcesTest extends AbstractBase {
.log().ifError()
.body("links.self", notNullValue())
.header("Link", not(containsString("prev=")))
- .header("Link", anyOf(containsString("current"),containsString("last")))
+ .header("Link", anyOf(containsString("current"), containsString("last")))
.when().get("/resource/platforms");
}
commit c09b8f16d4a4375a01241f2a1f042f59a9130735
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 15:14:23 2013 +0200
Support paging in the body with the appropriate media type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 5652f9f..92d2499 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -448,14 +448,14 @@ public class AbstractRestBean {
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",nextPage);
- builder.header("Link",new Link("next",uriBuilder.build().toString()));
+ builder.header("Link",new Link("next",uriBuilder.build().toString()).rfc5988String());
}
if (page>0) {
int prevPage = page -1;
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",prevPage);
- builder.header("Link", new Link("prev",uriBuilder.build().toString()));
+ builder.header("Link", new Link("prev",uriBuilder.build().toString()).rfc5988String());
}
// A link to the last page
@@ -463,12 +463,12 @@ public class AbstractRestBean {
int lastPage = resultList.getTotalSize() / pc.getPageSize();
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",lastPage);
- builder.header("Link", new Link("last",uriBuilder.build().toString()));
+ builder.header("Link", new Link("last",uriBuilder.build().toString()).rfc5988String());
}
// A link to the current page
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- builder.header("Link", new Link("current",uriBuilder.build().toString()));
+ builder.header("Link", new Link("current",uriBuilder.build().toString()).rfc5988String());
// Create a total size header
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
index 129ccfa..6eecf3e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
@@ -59,4 +59,20 @@ public class Link {
href + "; " +
"rel='" + rel + '\'' ;
}
+
+ /**
+ * Return the link in the format of RFC 5988 Web Linking.
+ *
+ * See <a href="http://tools.ietf.org/html/rfc5988#page-7">RFC 5988 Web Linking</a>
+ * @return String that contains the link with href and rel
+ */
+ public String rfc5988String() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("<")
+ .append(href)
+ .append(">; rel=\"")
+ .append(rel)
+ .append("\"");
+ return builder.toString();
+ }
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
index 40ae7b0..75be637 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
@@ -366,13 +366,13 @@ public class EventTest extends AbstractBase {
Headers headers = response.getHeaders();
int found = 0;
for (String link: headers.getValues("Link")) {
- if (link.contains("rel='last'"))
+ if (link.contains("rel=\"last\""))
found++;
- if (link.contains("rel='prev'"))
+ if (link.contains("rel=\"prev\""))
found++;
- if (link.contains("rel='current'"))
+ if (link.contains("rel=\"current\""))
found++;
- assert !link.contains("rel='next");
+ assert !link.contains("rel=\"next\"");
}
assert found == 3;
commit cd1087a1789973d74b85e7bffa99893a32ea603e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 22 22:37:33 2013 +0200
Support paging in the body with the appropriate media type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 8e4a826..5652f9f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -35,7 +36,9 @@ import java.util.Set;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -66,6 +69,7 @@ import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.GroupRest;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
+import org.rhq.enterprise.server.rest.domain.PagingCollection;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
@@ -77,12 +81,16 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
* @author Heiko W. Rupp
* @author Jay Shaughnessy
*/
+(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML,"application/vnd.rhq.wrapped+json"})
@javax.annotation.Resource(name = "ISPN", mappedName = "java:jboss/infinispan/rhq")
@SuppressWarnings("unchecked")
public class AbstractRestBean {
protected Log log = LogFactory.getLog(getClass().getName());
+ protected final MediaType wrappedCollectionJsonType = new MediaType("application","vnd.rhq.wrapped+json");
+ protected final String wrappedCollectionJson = "application/vnd.rhq.wrapped+json";
+
private static final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
@javax.annotation.Resource( name = "ISPN")
@@ -468,6 +476,52 @@ public class AbstractRestBean {
}
/**
+ * Wrap the passed collection #resultList in an object with paging information
+ * @param builder ResonseBuilder to add the entity to
+ * @param uriInfo UriInfo to construct paging links
+ * @param originalList The original list to obtain the paging info from
+ * @param resultList The list of result items
+ */
+ protected void wrapForPaging(Response.ResponseBuilder builder, UriInfo uriInfo, final PageList<?> originalList, final Collection resultList) {
+
+ PagingCollection pColl = new PagingCollection(resultList);
+ pColl.setTotalSize(originalList.getTotalSize());
+ PageControl pageControl = originalList.getPageControl();
+ pColl.setPageSize(pageControl.getPageSize());
+ int page = pageControl.getPageNumber();
+ pColl.setCurrentPage(page);
+ pColl.setLastPage(originalList.getTotalSize()/pageControl.getPageSize());
+
+ UriBuilder uriBuilder;
+ if (originalList.getTotalSize() > (page +1 ) * pageControl.getPageSize()) {
+ int nextPage = page +1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",nextPage);
+ pColl.addLink(new Link("next",uriBuilder.build().toString()));
+ }
+ if (page > 0) {
+ int prevPage = page -1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",prevPage);
+ pColl.addLink(new Link("prev",uriBuilder.build().toString()));
+ }
+
+ // A link to the last page
+ if (!pageControl.isUnlimited()) {
+ int lastPage = originalList.getTotalSize() / pageControl.getPageSize();
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",lastPage);
+ pColl.addLink( new Link("last",uriBuilder.build().toString()));
+ }
+
+ // A link to the current page
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ pColl.addLink(new Link("current",uriBuilder.build().toString()));
+
+ builder.entity(pColl);
+ }
+
+ /**
* Fetch the group with the passed id
*
* @param groupId id of the resource group
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 6ea3d03..4ceae82 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -46,6 +46,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
@@ -98,7 +99,6 @@ import org.rhq.enterprise.server.rest.domain.Link;
* AlertHandlerBean
* @author Heiko W. Rupp
*/
-@Produces({"application/json","application/xml","text/plain"})
@Path("/alert")
@Api(value = "Deal with Alert Definitions",description = "This api deals with alert definitions. Everything " +
" is purely experimental at the moment and can change without notice at any time.")
@@ -149,6 +149,7 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam(value = "Page number") @QueryParam("page") Integer page,
@ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
@ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
+ @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
@@ -163,10 +164,17 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
ret.add(adr);
}
- Response.ResponseBuilder builder = Response.ok(ret);
- createPagingHeader(builder,uriInfo,defs);
+ Response.ResponseBuilder builder = Response.ok();
- // TODO media type etc
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ builder.type(mediaType);
+
+ if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,defs,ret);
+ } else {
+ createPagingHeader(builder,uriInfo,defs);
+ builder.entity(ret); // TODO generic entity for XML
+ }
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 5da3fb9..5c6a06f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -32,7 +32,6 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
@@ -72,7 +71,6 @@ import org.rhq.enterprise.server.rest.domain.*;
* Deal with alert related stuff
* @author Heiko W. Rupp
*/
-@Produces({"application/json","application/xml","text/html"})
@Path("/alert")
@Api(value = "Deal with Alerts",description = "This api deals with alerts that have fired.")
@Stateless
@@ -148,17 +146,22 @@ public class AlertHandlerBean extends AbstractRestBean {
}
MediaType type = headers.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(type);
if (type.equals(MediaType.TEXT_HTML_TYPE)) {
- builder = Response.ok(renderTemplate("listAlerts.ftl",ret),type);
+ builder.entity(renderTemplate("listAlerts.ftl",ret));
} else {
- GenericEntity<List<AlertRest>> entity = new GenericEntity<List<AlertRest>>(ret) {};
- builder = Response.ok(entity);
+ if (type.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,alerts,ret);
+ }
+ else {
+ GenericEntity<List<AlertRest>> entity = new GenericEntity<List<AlertRest>>(ret) {};
+ builder.entity(entity);
+ createPagingHeader(builder,uriInfo,alerts);
+ }
}
- createPagingHeader(builder,uriInfo,alerts);
-
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index 7402550..fd8a835 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -37,13 +37,11 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -76,7 +74,6 @@ import org.rhq.enterprise.server.rest.domain.EventSourceRest;
*/
@Path("/event")
@Api("Api that deals with Events (e.g snmp traps, logfile lines)")
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@Stateless
@Interceptors(SetCallerInterceptor.class)
public class EventHandlerBean extends AbstractRestBean {
@@ -348,17 +345,20 @@ public class EventHandlerBean extends AbstractRestBean {
}
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(mediaType);
if (mediaType.equals(MediaType.APPLICATION_XML_TYPE)) {
GenericEntity<List<EventRest>> list = new GenericEntity<List<EventRest>>(restEvents) {};
- builder = Response.ok(list, mediaType);
+ builder.entity(list);
+ createPagingHeader(builder,uriInfo,eventList);
+ } else if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ builder.entity(restEvents);
+ createPagingHeader(builder,uriInfo,eventList);
}
- else {
- builder = Response.ok(restEvents, mediaType);
+ else {
+ wrapForPaging(builder,uriInfo,eventList,restEvents);
}
- createPagingHeader(builder,uriInfo,eventList);
-
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index be2419b..d65a850 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -37,7 +37,6 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
@@ -93,7 +92,6 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@Interceptors(SetCallerInterceptor.class)
@Path("/group")
@Api(value="Deal with groups and DynaGroups", description = "Api that deals with resource groups and group definitions")
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
public class GroupHandlerBean extends AbstractRestBean {
private final Log log = LogFactory.getLog(GroupHandlerBean.class);
@@ -142,12 +140,15 @@ public class GroupHandlerBean extends AbstractRestBean {
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listGroup", list));
}
+ else if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,groups,list);
+ }
else {
GenericEntity<List<GroupRest>> ret = new GenericEntity<List<GroupRest>>(list) {};
builder.entity(ret);
+ createPagingHeader(builder,uriInfo,groups);
}
- createPagingHeader(builder,uriInfo,groups);
return builder.build();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index e32ea03..81d490b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -420,16 +420,19 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(mediaType);
+
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
- builder = Response.ok(renderTemplate("listOperationHistory.ftl", result));
+ builder.entity(renderTemplate("listOperationHistory.ftl", result));
+ } else if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,histories,result);
} else {
GenericEntity<List<OperationHistoryRest>> res = new GenericEntity<List<OperationHistoryRest>>(result) {};
- builder = Response.ok(res);
+ builder.entity(res);
+ createPagingHeader(builder,uriInfo,histories);
}
- createPagingHeader(builder,uriInfo,histories);
-
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index a783ac8..0c3a7cd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -114,7 +114,6 @@ import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
* Class that deals with getting data about resources
* @author Heiko W. Rupp
*/
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@Path("/resource")
@Api(value="Resource related", description = "This endpoint deals with individual resources, not resource groups")
@Interceptors(SetCallerInterceptor.class)
@@ -263,15 +262,19 @@ public class ResourceHandlerBean extends AbstractRestBean {
Response.ResponseBuilder builder = Response.ok();
builder.type(mediaType);
- createPagingHeader(builder,uriInfo,resources);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listResourceWithType", rwtList));
} else {
- GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList) {
+ if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,resources,rwtList);
+ } else {
+ GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList) {
};
- builder.entity(list);
+ builder.entity(list);
+ createPagingHeader(builder,uriInfo,resources);
+ }
}
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java
new file mode 100644
index 0000000..4a0f892
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java
@@ -0,0 +1,97 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * A wrapper for collections with paging entries
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class PagingCollection<T> {
+
+ Collection<T> data;
+ int pageSize;
+ int currentPage;
+ int lastPage;
+ int totalSize;
+ List<Link> links = new ArrayList<Link>();
+
+ public PagingCollection(Collection<T> data) {
+ this.data = data;
+ }
+
+ public int getCurrentPage() {
+ return currentPage;
+ }
+
+ public void setCurrentPage(int currentPage) {
+ this.currentPage = currentPage;
+ }
+
+ public Collection<T> getData() {
+ return data;
+ }
+
+ public void setData(Collection<T> data) {
+ this.data = data;
+ }
+
+ public int getLastPage() {
+ return lastPage;
+ }
+
+ public void setLastPage(int lastPage) {
+ this.lastPage = lastPage;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public int getTotalSize() {
+ return totalSize;
+ }
+
+ public void setTotalSize(int totalSize) {
+ this.totalSize = totalSize;
+ }
+
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+
+ public void addLink(Link link) {
+ links.add(link);
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 7e20630..3a7e961 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test
+ @Test(enabled = false)
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
index ae4e81d..fd154ef 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
@@ -40,6 +40,7 @@ import static com.jayway.restassured.RestAssured.given;
public abstract class AbstractBase {
static final String APPLICATION_JSON = "application/json";
+ static final String WRAPPED_JSON = "application/vnd.rhq.wrapped+json";
private static final String APPLICATION_XML = "application/xml";
private static final String TEXT_CSV = "text/csv";
private static final String TEXT_HTML = "text/html";
@@ -48,6 +49,7 @@ public abstract class AbstractBase {
static Header acceptXml = new Header("Accept", APPLICATION_XML);
static Header acceptHtml = new Header("Accept", TEXT_HTML);
static Header acceptCsv = new Header("Accept", TEXT_CSV);
+ static Header acceptWrappedJson = new Header("Accept",WRAPPED_JSON);
int _platformId ;
int _platformTypeId;
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index e02a723..acbb492 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -39,6 +39,7 @@ import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.instanceOf;
@@ -116,6 +117,22 @@ public class AlertTest extends AbstractBase {
.get("/alert");
}
+ @Test
+ public void testListAlertsWithPagingAndWrapped() throws Exception {
+
+ given()
+ .header(acceptWrappedJson)
+ .queryParam("ps", 2)
+ .queryParam("page", 0)
+ .expect()
+ .statusCode(200)
+ .header("Link", nullValue())
+ .body("totalSize", notNullValue())
+ .log().ifError()
+ .when()
+ .get("/alert");
+ }
+
@Test
public void testGetAlertCountJson() throws Exception {
@@ -192,6 +209,21 @@ public class AlertTest extends AbstractBase {
}
@Test
+ public void testListAllAlertDefinitionsWithWrapping() throws Exception {
+
+ given()
+ .header(acceptWrappedJson)
+ .log().everything()
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("currentPage", Matchers.notNullValue())
+ .body("totalSize", Matchers.notNullValue())
+ .when()
+ .get("/alert/definitions");
+ }
+
+ @Test
public void testRedirectForDefinition() throws Exception {
given()
.header(acceptJson)
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 3515fac..ebd72c0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -306,13 +306,13 @@ public class ContentTest extends AbstractBase {
.as(List.class);
if (resources!=null && resources.size()>0) {
- int resourceId = resources.get(0).getResourceId();
+ int resourceId = (Integer) ((Map < String,Object>)resources.get(0)).get("resourceId");
given()
.pathParam("id", resourceId)
.queryParam("physical", "true") // Also remove target on the EAP instance
.expect()
- .statusCode(200)
+ .statusCode(204)
.when()
.delete("/resource/{id}");
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
index a4ef048..ef575d1 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
@@ -35,6 +35,8 @@ import org.rhq.modules.integrationTests.restApi.d.GroupDef;
import static com.jayway.restassured.RestAssured.expect;
import static com.jayway.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.iterableWithSize;
@@ -69,17 +71,37 @@ public class GroupTest extends AbstractBase {
@Test
public void testGetGroups() throws Exception {
- expect().statusCode(200)
- .when().get("/group");
+ expect()
+ .statusCode(200)
+ .when()
+ .get("/group");
}
@Test
public void testGetGroupsWithPaging() throws Exception {
given()
+ .header(acceptJson)
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .header("Link", notNullValue())
+ .when()
+ .get("/group");
+ }
+
+ @Test
+ public void testGetGroupsWithPagingWrapped() throws Exception {
+ given()
+ .header(acceptWrappedJson)
.queryParam("page",0)
.queryParam("ps",2)
.expect()
.statusCode(200)
+ .log().ifError()
+ .header("Link",nullValue())
+ .body("pageSize",is(2))
+ .body("currentPage",is(0))
.when()
.get("/group");
}
@@ -87,10 +109,11 @@ public class GroupTest extends AbstractBase {
@Test
public void testGetGroupsQuery() throws Exception {
given()
- .queryParam("q","lala")
+ .queryParam("q", "lala")
.expect()
- .statusCode(200)
- .when().get("/group");
+ .statusCode(200)
+ .when()
+ .get("/group");
}
@Test
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index b66d9b5..cd103ca 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -82,6 +82,27 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testGetPlatformJsonWrapping() {
+
+ // Actually this object should not be wrapped
+ // as it is no list
+ given()
+ .header(acceptWrappedJson)
+ .pathParam("id",_platformId)
+ .expect()
+ .statusCode(200)
+ .contentType(WRAPPED_JSON)
+ .log().everything()
+ .body("links.self", notNullValue())
+ .body("resourceId",is(_platformId))
+ .body("typeId",is(_platformTypeId))
+ .body("parentId",is(0))
+ .when()
+ .get("/resource/{id}");
+
+ }
+
+ @Test
public void testGetPlatformAndTypeJson() {
Integer typeId =
@@ -258,7 +279,26 @@ public class ResourcesTest extends AbstractBase {
// .header("Link", allOf(containsString("page=2"), containsString("current")))
.header("Link",not(containsString("prev")))
.body("links.self", notNullValue())
- .when().get("/resource");
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testGetResourcesWithPagingAndWrapping() throws Exception {
+
+ given()
+ .header("Accept", "application/vnd.rhq.wrapped+json")
+ .with()
+ .queryParam("page", 1)
+ .queryParam("ps", 2) // Unusually small to provoke having more than 1 page
+ .queryParam("category", "service")
+ .expect()
+ .statusCode(200)
+ .log().everything()
+ .body("pageSize",is(2))
+ .body("currentPage",is(1))
+ .when()
+ .get("/resource");
}
@Test
commit e725ed0658bae7bd5f33dbbc4a2b30eb02a6057f
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed May 22 19:36:09 2013 +0200
Improvements to RHQ irc bot. New set of commands is now supported.
diff --git a/etc/rhq-ircBot/pom.xml b/etc/rhq-ircBot/pom.xml
index 40b6952..6e66187 100644
--- a/etc/rhq-ircBot/pom.xml
+++ b/etc/rhq-ircBot/pom.xml
@@ -41,7 +41,7 @@
<dependency>
<groupId>org.pircbotx</groupId>
<artifactId>pircbotx</artifactId>
- <version>1.7</version>
+ <version>1.9</version>
</dependency>
<dependency>
@@ -50,6 +50,17 @@
<version>2.0</version>
</dependency>
+ <dependency>
+ <groupId>org.jsoup</groupId>
+ <artifactId>jsoup</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.4</version>
+ </dependency>
</dependencies>
<build>
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
index ce7535f..7e8f563 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
@@ -1,163 +1,63 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.rhq.etc.ircbot;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.j2bugzilla.base.Bug;
-import com.j2bugzilla.base.BugzillaConnector;
-import com.j2bugzilla.base.BugzillaException;
-import com.j2bugzilla.rpc.GetBug;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Properties;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
-import org.apache.xmlrpc.XmlRpcException;
import org.pircbotx.PircBotX;
-import org.pircbotx.User;
-import org.pircbotx.hooks.Listener;
-import org.pircbotx.hooks.ListenerAdapter;
-import org.pircbotx.hooks.events.DisconnectEvent;
-import org.pircbotx.hooks.events.MessageEvent;
-import org.pircbotx.hooks.events.PrivateMessageEvent;
/**
- * An IRC bot for doing helpful stuff on the Freenode #rhq channel.
+ * @author Jirka Kremser
*
- * @author Ian Springer
*/
-public class RhqIrcBot extends ListenerAdapter {
-
- private static final Pattern BUG_PATTERN = Pattern.compile("(?i)(bz|bug)[ ]*(\\d{6,7})");
- private static final Pattern ECHO_PATTERN = Pattern.compile("(?i)echo[ ]+(.+)");
-
- private static final Set<String> JON_DEVS = new HashSet<String>();
- static {
- JON_DEVS.add("ccrouch");
- JON_DEVS.add("ips");
- JON_DEVS.add("jkremser");
- JON_DEVS.add("jsanda");
- JON_DEVS.add("jshaughn");
- JON_DEVS.add("lkrejci");
- JON_DEVS.add("mazz");
- JON_DEVS.add("mtho11");
- JON_DEVS.add("pilhuhn");
- JON_DEVS.add("spinder");
- JON_DEVS.add("stefan_n");
- }
-
- private String server;
- private String channel;
- private BugzillaConnector bzConnector = new BugzillaConnector();
- private Map<Integer, Long> bugLogTimestamps = new HashMap<Integer, Long>();
-
- public RhqIrcBot(String server, String channel) {
- this.server = server;
- this.channel = channel;
- }
-
- @Override
- public void onMessage(MessageEvent event) throws Exception {
- PircBotX bot = event.getBot();
- if (!bot.getNick().equals(bot.getName())) {
- bot.changeNick(bot.getName());
- }
-
- String message = event.getMessage();
- Matcher bugMatcher = BUG_PATTERN.matcher(message);
- while (bugMatcher.find()) {
- int bugId = Integer.valueOf(bugMatcher.group(2));
- GetBug getBug = new GetBug(bugId);
- try {
- bzConnector.executeMethod(getBug);
- } catch (Exception e) {
- bzConnector = new BugzillaConnector();
- bzConnector.connectTo("https://bugzilla.redhat.com");
- try {
- bzConnector.executeMethod(getBug);
- } catch (BugzillaException e1) {
- //e1.printStackTrace();
- Throwable cause = e1.getCause();
- String details = (cause instanceof XmlRpcException) ? cause.getMessage() : e1.getMessage();
- bot.sendMessage(event.getChannel(), "Failed to access BZ " + bugId + ": " + details);
- continue;
- }
- }
- Bug bug = getBug.getBug();
- if (bug != null) {
- String product = bug.getProduct();
- if (product.equals("RHQ Project")) {
- product = "RHQ";
- } else if (product.equals("JBoss Operations Network")) {
- product = "JON";
- }
- Long timestamp = bugLogTimestamps.get(bugId);
- if ((timestamp == null) || ((System.currentTimeMillis() - timestamp) > (5 * 60 * 1000L))) {
- bot.sendMessage(event.getChannel(), "BZ " + bugId + " [product=" + product
- + ", priority=" + bug.getPriority() + ", status=" + bug.getStatus() + "] "
- + bug.getSummary() + " [ https://bugzilla.redhat.com/" + bugId + " ]");
- }
- bugLogTimestamps.put(bugId, System.currentTimeMillis());
- } else {
- bot.sendMessage(event.getChannel(), "BZ " + bugId + " does not exist.");
- }
- }
-
- if (message.matches(".*\\b(jon-team|jboss-on-team)\\b.*")) {
- Set<User> users = bot.getUsers(event.getChannel());
- StringBuilder presentJonDevs = new StringBuilder();
- for (User user : users) {
- String nick = user.getNick();
- if (JON_DEVS.contains(nick) && !nick.equals(event.getUser().getNick())) {
- presentJonDevs.append(nick).append(' ');
- }
- }
- bot.sendMessage(event.getChannel(), presentJonDevs + ": see message from "
- + event.getUser().getNick() + " above");
- }
+public class RhqIrcBot extends PircBotX {
+
+ private static final String TRUSTSTORE_NAME = "cacerts.jks";
+
+ public RhqIrcBot(RhqIrcBotListener rhqBot) {
+ setName("rhq-bot");
+ setVersion("1.1");
+ setFinger("RHQ IRC bot (source code in RHQ git under etc/rhq-ircBot/)");
+
+ setVerbose(true);
+ setAutoNickChange(true);
+
+ getListenerManager().addListener(rhqBot);
+ setSocketTimeout(1 * 60 * 1000); // 1 minute
}
-
- @Override
- public void onPrivateMessage(PrivateMessageEvent privateMessageEvent) throws Exception {
- PircBotX bot = privateMessageEvent.getBot();
- String message = privateMessageEvent.getMessage();
- Matcher echoMatcher = ECHO_PATTERN.matcher(message);
- if (echoMatcher.matches()) {
- String echoMessage = echoMatcher.group(1);
- bot.sendMessage(this.channel, echoMessage);
- } else {
- bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".");
- }
- // TODO: Implement a HELP command.
- }
-
- @Override
- public void onDisconnect(DisconnectEvent disconnectEvent) throws Exception {
- boolean connected = false;
- while (!connected) {
- Thread.sleep(60 * 1000L); // 1 minute
- try {
- PircBotX newBot = createBot(this);
- newBot.connect(this.server);
- newBot.joinChannel(this.channel);
-
- connected = true;
- } catch (Exception e) {
- System.err.println("Failed to reconnect to " + disconnectEvent.getBot().getServer() + " IRC server: " + e);
- }
- }
-
- // Try to clean up the old bot, so it can release any memory, sockets, etc. it's using.
- PircBotX oldBot = disconnectEvent.getBot();
- Set<Listener> oldListeners = new HashSet<Listener>(oldBot.getListenerManager().getListeners());
- for (Listener oldListener : oldListeners) {
- oldBot.getListenerManager().removeListener(oldListener);
- }
- }
-
+
public static void main(String[] args) throws Exception {
- if (args.length != 2) {
- System.err.println("Usage: RhqIrcBot IRC_SERVER IRC_CHANNEL");
+ if (args.length != 2 && args.length != 3) {
+ System.err.println("Usage: RhqIrcBot IRC_SERVER IRC_CHANNEL [rhq-ircBot.properties]");
System.err.println(" e.g.: RhqIrcBot irc.freenode.net '#rhq'");
System.exit(1);
}
@@ -167,26 +67,62 @@ public class RhqIrcBot extends ListenerAdapter {
channel = '#' + channel;
}
- RhqIrcBot rhqBot = new RhqIrcBot(server, channel);
+ RhqIrcBotListener rhqBotListener = new RhqIrcBotListener(server, channel);
+ if (args.length == 3) {
+ File propertyFile = new File(args[2]);
+ if (!propertyFile.exists()) {
+ System.err.println("Provided property file [" + args[2] + "] does not exist");
+ System.exit(2);
+ }
+ Properties properties = new Properties();
+ FileInputStream fis = new FileInputStream(propertyFile);
+ properties.load(fis);
+ String docspaceLogin = properties.getProperty("docspace_login");
+ String docspacePassword = properties.getProperty("docspace_password");
+ if (docspaceLogin == null || docspaceLogin.isEmpty() || docspacePassword == null || docspacePassword.isEmpty()) {
+ System.err.println("The property format has bad format");
+ System.err.println("It must contain following key-value pairs\n");
+ System.err.println("docspace_login=X");
+ System.err.println("docspace_password=Y");
+ System.exit(3);
+ }
+ fis.close();
+
+ setupTrustStore();
+
+ rhqBotListener.setDocspaceLogin(docspaceLogin);
+ rhqBotListener.setDocspacePassword(docspacePassword);
+ }
- PircBotX bot = createBot(rhqBot);
+ PircBotX bot = new RhqIrcBot(rhqBotListener);
bot.connect(server);
bot.joinChannel(channel);
}
-
- private static PircBotX createBot(RhqIrcBot rhqBot) {
- PircBotX bot = new PircBotX();
-
- bot.setName("rhq-bot");
- bot.setVersion("1.0");
- bot.setFinger("RHQ IRC bot (source code in RHQ git under etc/rhq-ircBot/)");
-
- bot.setVerbose(true);
- bot.setAutoNickChange(true);
-
- bot.getListenerManager().addListener(rhqBot);
- bot.setSocketTimeout(1 * 60 * 1000); // 1 minute
- return bot;
+
+ private static void setupTrustStore() {
+ TrustManagerFactory trustManagerFactory;
+ try {
+ trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore keystore;
+ keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ InputStream keystoreStream = RhqIrcBot.class.getResourceAsStream(TRUSTSTORE_NAME);
+ keystore.load(keystoreStream, "rhqirc".toCharArray());
+ trustManagerFactory.init(keystore);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+ SSLContext ctx = SSLContext.getInstance("SSL");
+ ctx.init(null, trustManagers, null);
+
+ SSLContext.setDefault(ctx);
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (KeyStoreException e) {
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ }
}
-
}
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
new file mode 100644
index 0000000..8a7e578
--- /dev/null
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -0,0 +1,357 @@
+package org.rhq.etc.ircbot;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.rpc.GetBug;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.xmlrpc.XmlRpcException;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.pircbotx.PircBotX;
+import org.pircbotx.User;
+import org.pircbotx.hooks.Listener;
+import org.pircbotx.hooks.ListenerAdapter;
+import org.pircbotx.hooks.events.DisconnectEvent;
+import org.pircbotx.hooks.events.MessageEvent;
+import org.pircbotx.hooks.events.NickChangeEvent;
+import org.pircbotx.hooks.events.PrivateMessageEvent;
+
+/**
+ * An IRC bot for doing helpful stuff on the Freenode #rhq channel.
+ *
+ * @author Ian Springer
+ * @author Jiri Kremser
+ */
+public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
+
+ private static final Pattern BUG_PATTERN = Pattern.compile("(?i)(bz|bug)[ ]*(\\d{6,7})");
+ private static final Pattern COMMIT_PATTERN = Pattern.compile("(?i)(\\!commit|cm)[ ]*([0-9a-f]{3,40})");
+ private static final Pattern ECHO_PATTERN = Pattern.compile("(?i)echo[ ]+(.+)");
+ private static final String SUPPORT_LINK = "https://docspace.corp.redhat.com/docs/DOC-124477";
+ private static final String COMMIT_LINK = "https://git.fedorahosted.org/cgit/rhq/rhq.git/commit/?id=%s";
+ private static final String PTO_LINK = "https://mail.corp.redhat.com/home/ccrouch@redhat.com/JBoss%20ON%20OOO?fmt...";
+ private static final DateFormat monthFormat = new SimpleDateFormat("MMM");
+ private static final DateFormat dayInMonthFormat = new SimpleDateFormat("d");
+
+ private static enum Command {
+
+ FORUM("Our forum is available from https://community.jboss.org/en/rhq?view=discussions", true),
+ HELP("You can use one of the following commands: ", true),
+ LISTS("Feel free to enroll to the user list https://lists.fedorahosted.org/mailman/listinfo/rhq-users"
+ + " or the devel list https://lists.fedorahosted.org/mailman/listinfo/rhq-devel", true),
+ LOGS("IRC logs are available from http://transcripts.jboss.org/channel/irc.freenode.org/%23rhq/index.html", true),
+ PTO,
+ SOURCE("The code could be viewed/cloned on https://github.com/rhq-project or https://git.fedorahosted.org/cgit/rhq/rhq.git/", true),
+ SUPPORT,
+ WIKI("Our wiki is available from https://docs.jboss.org/author/display/RHQ/Home", true);
+
+ public static final char PREFIX = '!';
+ private final String staticRespond;
+ private final boolean includeInHelp;
+
+ Command(String staticRespond, boolean includeInHelp) {
+ this.staticRespond = staticRespond;
+ this.includeInHelp = includeInHelp;
+ }
+
+ Command() {
+ this(null, false);
+ }
+ }
+
+ private static final Set<String> JON_DEVS = new HashSet<String>();
+ static {
+ JON_DEVS.add("ccrouch");
+ JON_DEVS.add("ips");
+ JON_DEVS.add("jkremser");
+ JON_DEVS.add("jsanda");
+ JON_DEVS.add("jshaughn");
+ JON_DEVS.add("lkrejci");
+ JON_DEVS.add("mazz");
+ JON_DEVS.add("mtho11");
+ JON_DEVS.add("pilhuhn");
+ JON_DEVS.add("spinder");
+ JON_DEVS.add("stefan_n");
+ JON_DEVS.add("tsegismont");
+ }
+
+ private final String server;
+ private final String channel;
+ private String docspaceLogin;
+ private String docspacePassword;
+ private BugzillaConnector bzConnector = new BugzillaConnector();
+ private final Map<Integer, Long> bugLogTimestamps = new HashMap<Integer, Long>();
+ private final Map<String, String> names = new HashMap<String, String>();
+ private final Pattern commandPattern;
+
+ public RhqIrcBotListener(String server, String channel) {
+ this.server = server;
+ this.channel = channel;
+ StringBuilder commandRegExp = new StringBuilder();
+ commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
+ for (Command command : Command.values()) {
+ commandRegExp.append(command.name()).append('|');
+ }
+ commandRegExp.deleteCharAt(commandRegExp.length() - 1);
+ commandRegExp.append(')');
+ commandPattern = Pattern.compile(commandRegExp.toString());
+ }
+
+ @Override
+ public void onMessage(MessageEvent<RhqIrcBot> event) throws Exception {
+ PircBotX bot = event.getBot();
+ if (!bot.getNick().equals(bot.getName())) {
+ bot.changeNick(bot.getName());
+ }
+
+ // react to BZs in the messages
+ String message = event.getMessage();
+ Matcher bugMatcher = BUG_PATTERN.matcher(message);
+ while (bugMatcher.find()) {
+ int bugId = Integer.valueOf(bugMatcher.group(2));
+ GetBug getBug = new GetBug(bugId);
+ try {
+ bzConnector.executeMethod(getBug);
+ } catch (Exception e) {
+ bzConnector = new BugzillaConnector();
+ bzConnector.connectTo("https://bugzilla.redhat.com");
+ try {
+ bzConnector.executeMethod(getBug);
+ } catch (BugzillaException e1) {
+ //e1.printStackTrace();
+ Throwable cause = e1.getCause();
+ String details = (cause instanceof XmlRpcException) ? cause.getMessage() : e1.getMessage();
+ bot.sendMessage(event.getChannel(), "Failed to access BZ " + bugId + ": " + details);
+ continue;
+ }
+ }
+ Bug bug = getBug.getBug();
+ if (bug != null) {
+ String product = bug.getProduct();
+ if (product.equals("RHQ Project")) {
+ product = "RHQ";
+ } else if (product.equals("JBoss Operations Network")) {
+ product = "JON";
+ }
+ Long timestamp = bugLogTimestamps.get(bugId);
+ if ((timestamp == null) || ((System.currentTimeMillis() - timestamp) > (5 * 60 * 1000L))) {
+ bot.sendMessage(
+ event.getChannel(),
+ "BZ " + bugId + " [product=" + product + ", priority=" + bug.getPriority() + ", status="
+ + bug.getStatus() + "] " + bug.getSummary() + " [ https://bugzilla.redhat.com/" + bugId
+ + " ]");
+ }
+ bugLogTimestamps.put(bugId, System.currentTimeMillis());
+ } else {
+ bot.sendMessage(event.getChannel(), "BZ " + bugId + " does not exist.");
+ }
+ }
+
+ // react to the commit hashs included in the messages
+ Matcher commitMatcher = COMMIT_PATTERN.matcher(message);
+ while (commitMatcher.find()) {
+ String shaHash = commitMatcher.group(2);
+ String response = String.format(COMMIT_LINK, shaHash);
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
+
+ // react to commands included in the messages
+ Matcher commandMatcher = commandPattern.matcher(message);
+ while (commandMatcher.find()) {
+ Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
+ String response = prepareResponseForCommand(command);
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
+
+ // ping JON devs
+ if (message.matches(".*\\b(jon-team|jboss-on-team)\\b.*")) {
+ Set<User> users = bot.getUsers(event.getChannel());
+ StringBuilder presentJonDevs = new StringBuilder();
+ for (User user : users) {
+ String nick = user.getNick();
+ if (JON_DEVS.contains(nick) && !nick.equals(event.getUser().getNick())) {
+ presentJonDevs.append(nick).append(' ');
+ }
+ }
+ bot.sendMessage(event.getChannel(), presentJonDevs + ": see message from " + event.getUser().getNick()
+ + " above");
+ }
+ }
+
+ @Override
+ public void onPrivateMessage(PrivateMessageEvent<RhqIrcBot> privateMessageEvent) throws Exception {
+ PircBotX bot = privateMessageEvent.getBot();
+ String message = privateMessageEvent.getMessage();
+ Matcher echoMatcher = ECHO_PATTERN.matcher(message);
+ if (echoMatcher.matches()) {
+ String echoMessage = echoMatcher.group(1);
+ bot.sendMessage(this.channel, echoMessage);
+ } else if (message.equalsIgnoreCase(Command.PREFIX + "listrenames")) {
+ //Generate a list of renames in the form of old1 changed to new1, old2 changed to new2, etc
+ StringBuilder users = new StringBuilder();
+ for (Map.Entry<String, String> curUser : names.entrySet()) {
+ users.append(curUser.getKey()).append(" changed to ").append(curUser.getValue()).append(", ");
+ }
+ String usersString = users.substring(0, users.length() - 3);
+ privateMessageEvent.respond("Renamed users: " + usersString);
+ } else {
+ boolean isCommand = false;
+ // react to commands included in the messages
+ Matcher commandMatcher = commandPattern.matcher(message);
+ while (commandMatcher.find()) {
+ Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
+ String response = prepareResponseForCommand(command);
+ bot.sendMessage(privateMessageEvent.getUser(), response);
+ }
+ if (!isCommand) {
+ bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".\n"
+ + prepareResponseForCommand(Command.HELP));
+ }
+ }
+ }
+
+ @Override
+ public void onDisconnect(DisconnectEvent<RhqIrcBot> disconnectEvent) throws Exception {
+ boolean connected = false;
+ while (!connected) {
+ Thread.sleep(60 * 1000L); // 1 minute
+ try {
+ PircBotX newBot = new RhqIrcBot(this);
+ newBot.connect(this.server);
+ newBot.joinChannel(this.channel);
+
+ connected = true;
+ } catch (Exception e) {
+ System.err.println("Failed to reconnect to " + disconnectEvent.getBot().getServer() + " IRC server: "
+ + e);
+ }
+ }
+
+ // Try to clean up the old bot, so it can release any memory, sockets, etc. it's using.
+ PircBotX oldBot = disconnectEvent.getBot();
+ Set<Listener> oldListeners = new HashSet<Listener>(oldBot.getListenerManager().getListeners());
+ for (Listener oldListener : oldListeners) {
+ oldBot.getListenerManager().removeListener(oldListener);
+ }
+ }
+
+ @Override
+ public void onNickChange(NickChangeEvent<RhqIrcBot> event) throws Exception {
+ //Store the result
+ names.put(event.getOldNick(), event.getNewNick());
+ }
+
+ private String prepareResponseForCommand(Command command) {
+ if (command.staticRespond != null) {
+ String response = command.staticRespond;
+ if (command == Command.HELP) {
+ for (Command com : Command.values()) {
+ if (com.includeInHelp) {
+ response += Command.PREFIX + com.toString().toLowerCase() + " ";
+ }
+ }
+ }
+ return response;
+ }
+ switch (command) {
+ case SUPPORT:
+ return whoIsOnSupport(SUPPORT_LINK);
+ case PTO:
+ return whoIsOnPto(PTO_LINK);
+ default:
+ System.err.println("Unknown command:" + command);
+ break;
+ }
+ return null;
+ }
+
+ private String whoIsOnSupport(String link) {
+ if (docspaceLogin == null || docspaceLogin.isEmpty() || docspacePassword == null || docspacePassword.isEmpty()) {
+ return "This command is not supported.";
+ }
+ String month = monthFormat.format(new Date());
+ String dayInMonth = dayInMonthFormat.format(new Date());
+ int dayInMonthInt = Integer.parseInt(dayInMonth);
+ try {
+ boolean monthFound = false;
+ String login = docspaceLogin + ":" + docspacePassword;
+ String base64login = new String(Base64.encodeBase64(login.getBytes()));
+ Document doc = Jsoup.connect(link).header("Authorization", "Basic " + base64login).get();
+ Elements cells = doc.select("tr td");
+ for (Element cell : cells) {
+ String cellText = cell.text().toLowerCase();
+ if (cellText.startsWith(month.toLowerCase())) {
+ monthFound = true;
+ if (cellText.substring(cellText.length() - 1, cellText.length()).equals(dayInMonth)) {
+ return cell.firstElementSibling().text() + " is on support this week";
+ }
+ continue;
+ }
+ if (monthFound && cellText.equals(dayInMonth)) {
+ return cell.firstElementSibling().text() + " is on support this week";
+ } else if (monthFound) {
+ if (cell.equals(cell.firstElementSibling()) || cell.equals(cell.lastElementSibling())) {
+ continue; //the first row with name or the last row with a comment
+ }
+ int day = -1;
+ try {
+ day = Integer.parseInt(cellText);
+ if (day > dayInMonthInt) {
+ return cell.parent().previousElementSibling().child(0).text() + " is on support this week";
+ }
+ } catch (NumberFormatException nfe) {
+ break; // next month
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // fallback solution if SSL is not set correctly
+ String randomDevel = JON_DEVS.toArray(new String[JON_DEVS.size()])[new Random().nextInt(JON_DEVS.size())];
+ return "404 Developer Not Found, selecting randomly " + randomDevel + ". Check the " + SUPPORT_LINK;
+ }
+
+ private static String whoIsOnPto(String link) {
+ String month = monthFormat.format(new Date());
+ String dayInMonth = dayInMonthFormat.format(new Date());
+ try {
+ String onPto = "";
+ Document doc = Jsoup.connect(link).ignoreContentType(true).get();
+ Elements dates = doc.getElementsContainingOwnText(dayInMonth + " " + month);
+ for (Element date : dates) {
+ onPto += date.firstElementSibling().text() + ", ";
+ }
+ if (!onPto.isEmpty()) {
+ return onPto.substring(0, onPto.length() - 2);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "noone is on PTO today";
+ }
+
+ public void setDocspaceLogin(String docspaceLogin) {
+ this.docspaceLogin = docspaceLogin;
+ }
+
+ public void setDocspacePassword(String docspacePassword) {
+ this.docspacePassword = docspacePassword;
+ }
+}
diff --git a/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks
new file mode 100644
index 0000000..3d73cbc
Binary files /dev/null and b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks differ
diff --git a/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties
new file mode 100644
index 0000000..25e325c
--- /dev/null
+++ b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties
@@ -0,0 +1,2 @@
+docspace_login=
+docspace_password=
commit 6742d1fda892047e45a0b5cffe9df42957318a54
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 22 14:12:32 2013 +0200
Enable paging on (some) endpoints that return lists
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 0038099..8e4a826 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -59,6 +59,8 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.GroupRest;
@@ -419,6 +421,53 @@ public class AbstractRestBean {
}
/**
+ * Create the paging headers for collections and attach them to the passed builder. Those are represented as
+ * <i>Link:</i> http headers that carry the URL for the pages and the respective relation.
+ * <br/>In addition a <i>X-total-size</i> header is created that contains the whole collection size.
+ * @param builder The ResponseBuilder that receives the headers
+ * @param uriInfo The uriInfo of the incoming request to build the urls
+ * @param resultList The collection with its paging information
+ */
+ protected void createPagingHeader(final Response.ResponseBuilder builder, final UriInfo uriInfo, final PageList<?> resultList) {
+
+ UriBuilder uriBuilder;
+
+ PageControl pc = resultList.getPageControl();
+ int page = pc.getPageNumber();
+
+ if (resultList.getTotalSize()> (pc.getPageNumber() +1 ) * pc.getPageSize()) {
+ int nextPage = page+1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",nextPage);
+
+ builder.header("Link",new Link("next",uriBuilder.build().toString()));
+ }
+
+ if (page>0) {
+ int prevPage = page -1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",prevPage);
+ builder.header("Link", new Link("prev",uriBuilder.build().toString()));
+ }
+
+ // A link to the last page
+ if (!pc.isUnlimited()) {
+ int lastPage = resultList.getTotalSize() / pc.getPageSize();
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",lastPage);
+ builder.header("Link", new Link("last",uriBuilder.build().toString()));
+ }
+
+ // A link to the current page
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ builder.header("Link", new Link("current",uriBuilder.build().toString()));
+
+
+ // Create a total size header
+ builder.header("X-collection-size",resultList.getTotalSize());
+ }
+
+ /**
* Fetch the group with the passed id
*
* @param groupId id of the resource group
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index d203cd3..6ea3d03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -77,6 +77,7 @@ import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
@@ -143,21 +144,31 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@GZIP
@GET
@Path("/definitions")
- @ApiOperation("List all Alert Definition")
- public List<AlertDefinitionRest> listAlertDefinitions(
- @ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
- @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status,
+ @ApiOperation(value = "List all Alert Definition", responseClass = "AlertDefinitionRest", multiValueResponse = true)
+ public Response listAlertDefinitions(
+ @ApiParam(value = "Page number") @QueryParam("page") Integer page,
+ @ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
+ @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
- criteria.setPaging(page,20); // TODO add link to next page
- List<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller, criteria);
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+
+ PageList<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller, criteria);
List<AlertDefinitionRest> ret = new ArrayList<AlertDefinitionRest>(defs.size());
for (AlertDefinition def : defs) {
AlertDefinitionRest adr = definitionToDomain(def, false, uriInfo);
ret.add(adr);
}
- return ret;
+
+ Response.ResponseBuilder builder = Response.ok(ret);
+ createPagingHeader(builder,uriInfo,defs);
+
+ // TODO media type etc
+
+ return builder.build();
}
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 4c80bd1..5da3fb9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -90,10 +90,10 @@ public class AlertHandlerBean extends AbstractRestBean {
@ApiErrors({
@ApiError(code = 406, reason = "There are 'resourceId' and 'definitionId' passed as query parameters"),
@ApiError(code = 406, reason = "Page size was 0"),
- @ApiError(code = 406, reason = "Page number was < 1")
+ @ApiError(code = 406, reason = "Page number was < 0")
})
public Response listAlerts(
- @ApiParam(value = "Page number") @QueryParam("page") @DefaultValue("1") int page,
+ @ApiParam(value = "Page number") @QueryParam("page") @DefaultValue("0") int page,
@ApiParam(value = "Page size; use -1 for 'unlimited'") @QueryParam("size") @DefaultValue("100")int size,
@ApiParam(value = "Limit to priority", allowableValues = "High, Medium, Low, All") @DefaultValue("All") @QueryParam("prio") String prio,
@ApiParam(value = "Should full resources and definitions be sent") @QueryParam("slim") @DefaultValue("false") boolean slim,
@@ -108,7 +108,7 @@ public class AlertHandlerBean extends AbstractRestBean {
if (size==0) {
throw new BadArgumentException("size","Must not be 0");
}
- if (page<1) {
+ if (page<0) {
throw new BadArgumentException("page","Must be >=1");
}
@@ -120,7 +120,7 @@ public class AlertHandlerBean extends AbstractRestBean {
criteria.setPageControl(pageControl);
}
else {
- criteria.setPaging(page-1, size); // TODO implement linking to next page
+ criteria.setPaging(page, size);
}
if (since!=null) {
@@ -157,6 +157,8 @@ public class AlertHandlerBean extends AbstractRestBean {
builder = Response.ok(entity);
}
+ createPagingHeader(builder,uriInfo,alerts);
+
return builder.build();
}
@@ -306,7 +308,7 @@ public class AlertHandlerBean extends AbstractRestBean {
@DELETE
@Path("/{id}")
- @ApiOperation(value = "Remove the alert from the lit of alerts")
+ @ApiOperation(value = "Remove the alert from the list of alerts")
public void purgeAlert(@ApiParam(value = "Id of the alert to remove") @PathParam("id") int id) {
alertManager.deleteAlerts(caller, new int[]{id});
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index becb680..7402550 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -32,6 +32,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -44,6 +45,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiError;
@@ -61,6 +63,7 @@ import org.rhq.core.domain.event.EventSource;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.rest.domain.EventDefinitionRest;
@@ -227,9 +230,19 @@ public class EventHandlerBean extends AbstractRestBean {
@QueryParam("endTime") long endTime,
@ApiParam(value="Select the severity to display. Default is to show all",
allowableValues = "DEBUG, INFO, WARN, ERROR, FATAL") @QueryParam("severity") String severity,
- @Context Request request,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @Context UriInfo uriInfo,
@Context HttpHeaders headers) {
+ if (severity!=null) {
+ try {
+ EventSeverity.valueOf(severity.toUpperCase());
+ } catch (Exception e) {
+ throw new BadArgumentException("severity",severity + " is bad. Allowed values are DEBUG, INFO, WARN, ERROR, FATAL");
+ }
+ }
+
EventSource source = findEventSourceById(sourceId);
EventCriteria criteria = new EventCriteria();
@@ -240,13 +253,19 @@ public class EventHandlerBean extends AbstractRestBean {
if (endTime>0) {
criteria.addFilterEndTime(endTime);
}
- if (startTime==0 && endTime==0) {
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+ else if (startTime==0 && endTime==0) {
PageControl pageControl = new PageControl();
pageControl.setPageSize(200);
criteria.setPageControl(pageControl);
}
+ if (severity!=null) {
+ criteria.addFilterSeverities(EventSeverity.valueOf(severity.toUpperCase()));
+ }
- Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria);
+ Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria, uriInfo);
return builder.build();
}
@@ -259,10 +278,21 @@ public class EventHandlerBean extends AbstractRestBean {
public Response getEventsForResource(@PathParam("id") int resourceId,
@QueryParam("startTime") long startTime,
@QueryParam("endTime") long endTime,
- @QueryParam("severity") String severity,
- @Context Request request,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @ApiParam(value="Select the severity to display. Default is to show all",
+ allowableValues = "DEBUG, INFO, WARN, ERROR, FATAL") @QueryParam("severity") String severity,
+ @Context UriInfo uriInfo,
@Context HttpHeaders headers) {
+ if (severity!=null) {
+ try {
+ EventSeverity.valueOf(severity.toUpperCase());
+ } catch (Exception e) {
+ throw new BadArgumentException("severity",severity + " is bad. Allowed values are DEBUG, INFO, WARN, ERROR, FATAL");
+ }
+ }
+
EventCriteria criteria = new EventCriteria();
criteria.addFilterResourceId(resourceId);
if (startTime>0) {
@@ -271,13 +301,19 @@ public class EventHandlerBean extends AbstractRestBean {
if (endTime>0) {
criteria.addFilterEndTime(endTime);
}
- if (startTime==0 && endTime==0) {
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+ else if (startTime==0 && endTime==0) {
PageControl pageControl = new PageControl();
pageControl.setPageSize(200);
criteria.setPageControl(pageControl);
}
+ if (severity!=null) {
+ criteria.addFilterSeverities(EventSeverity.valueOf(severity.toUpperCase()));
+ }
- Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria);
+ Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria, uriInfo);
return builder.build();
@@ -304,8 +340,8 @@ public class EventHandlerBean extends AbstractRestBean {
}
- private Response.ResponseBuilder getEventsAsBuilderForCriteria(HttpHeaders headers, EventCriteria criteria) {
- List<Event> eventList = eventManager.findEventsByCriteria(caller, criteria);
+ private Response.ResponseBuilder getEventsAsBuilderForCriteria(HttpHeaders headers, EventCriteria criteria, UriInfo uriInfo) {
+ PageList<Event> eventList = eventManager.findEventsByCriteria(caller, criteria);
List<EventRest> restEvents = new ArrayList<EventRest>(eventList.size());
for (Event event : eventList) {
restEvents.add(convertEvent(event));
@@ -320,6 +356,9 @@ public class EventHandlerBean extends AbstractRestBean {
else {
builder = Response.ok(restEvents, mediaType);
}
+
+ createPagingHeader(builder,uriInfo,eventList);
+
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index 6791bdf..be2419b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -116,12 +116,17 @@ public class GroupHandlerBean extends AbstractRestBean {
@Path("/")
@ApiOperation(value = "List all groups", multiValueResponse = true, responseClass = "GroupRest")
public Response getGroups(@ApiParam("String to search in the group name") @QueryParam("q") String q,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
@Context HttpHeaders headers, @Context UriInfo uriInfo) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
if (q!=null) {
criteria.addFilterName(q);
}
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
PageList<ResourceGroup> groups = resourceGroupManager.findResourceGroupsByCriteria(caller, criteria);
@@ -142,6 +147,8 @@ public class GroupHandlerBean extends AbstractRestBean {
builder.entity(ret);
}
+ createPagingHeader(builder,uriInfo,groups);
+
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 8bc2cb9..e32ea03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -29,6 +29,7 @@ import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -353,7 +354,6 @@ public class OperationsHandlerBean extends AbstractRestBean {
public Response outcome(
@ApiParam("Name of the submitted job.") @PathParam("id") String jobName,
@Context UriInfo uriInfo,
- @Context Request request,
@Context HttpHeaders httpHeaders) {
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
@@ -395,21 +395,26 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
public Response listHistory(
@ApiParam("Id of a resource to limit to") @QueryParam("resourceId") int resourceId,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
@Context UriInfo uriInfo,
- @Context Request request,
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
}
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ criteria.addSortStartTime(PageOrdering.ASC);
+ }
criteria.addSortEndTime(PageOrdering.DESC);
- PageList<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller, criteria);
+ PageList<ResourceOperationHistory> histories = opsManager.findResourceOperationHistoriesByCriteria(caller, criteria);
List<OperationHistoryRest> result = new ArrayList<OperationHistoryRest>();
- for (ResourceOperationHistory roh : list) {
+ for (ResourceOperationHistory roh : histories) {
OperationHistoryRest historyRest = historyToHistoryRest(roh,uriInfo);
result.add(historyRest);
}
@@ -422,6 +427,9 @@ public class OperationsHandlerBean extends AbstractRestBean {
GenericEntity<List<OperationHistoryRest>> res = new GenericEntity<List<OperationHistoryRest>>(result) {};
builder = Response.ok(res);
}
+
+ createPagingHeader(builder,uriInfo,histories);
+
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 70cc588..a783ac8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -211,7 +211,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
PageList<Resource> ret = resMgr.findResourcesByCriteria(caller,criteria);
- Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers,uriInfo,ret, page, pageSize);
+ Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers,uriInfo,ret);
return builder.build();
}
@@ -221,13 +221,22 @@ public class ResourceHandlerBean extends AbstractRestBean {
@Path("/platforms")
@Cache(isPrivate = true,maxAge = 300)
@ApiOperation(value = "List all platforms in the system", multiValueResponse = true, responseClass = "ResourceWithType")
- public Response getPlatforms(@Context HttpHeaders headers,
- @Context UriInfo uriInfo) {
+ public Response getPlatforms(
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ PageControl pc;
+ if (page!=null) {
+ pc = new PageControl(page,pageSize);
+ }
+ else {
+ pc = PageControl.getUnlimitedInstance();
+ }
- PageControl pc = new PageControl();
PageList<Resource> ret = resMgr.findResourcesByCategory(caller, ResourceCategory.PLATFORM,
InventoryStatus.COMMITTED, pc);
- Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers, uriInfo, ret, null, 20);
+ Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers, uriInfo, ret);
return builder.build();
}
@@ -239,13 +248,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
* @param headers HttpHeaders from the request
* @param uriInfo Uri from the request
* @param resources List of resources
- * @param page Page of pageSize. If null, paging is ignored
- * @param pageSize number of elements on a page
* @return An initialized ResponseBuilder
*/
private Response.ResponseBuilder getResponseBuilderForResourceList(HttpHeaders headers, UriInfo uriInfo,
- PageList<Resource> resources, Integer page,
- int pageSize) {
+ PageList<Resource> resources) {
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(resources.size());
for (Resource r : resources) {
putToCache(r.getId(), Resource.class, r);
@@ -256,25 +262,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
Response.ResponseBuilder builder = Response.ok();
builder.type(mediaType);
- UriBuilder uriBuilder;
- if (page!=null) {
- // TODO look a the page control and check if there is a next page at all
- if (resources.getTotalSize()> page*pageSize) {
- int nextPage = page+1;
- uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- uriBuilder.replaceQueryParam("page",nextPage);
-
- builder.header("Link",new Link("next",uriBuilder.build().toString()));
- }
-
- if (page>1) {
- int prevPage = page -1;
- uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- uriBuilder.replaceQueryParam("page",prevPage);
- builder.header("prev",uriBuilder.build().toString());
- }
- }
+ createPagingHeader(builder,uriInfo,resources);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listResourceWithType", rwtList));
@@ -294,7 +283,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
public ResourceWithChildren getHierarchy(@ApiParam("Id of the resource to start with") @PathParam("id")int baseResourceId) {
// TODO optimize to do less recursion
- Resource start = obtainResource(baseResourceId);
+ Resource start = fetchResource(baseResourceId);
return getHierarchy(start);
}
@@ -425,7 +414,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
if (avail.getResourceId() != resourceId)
throw new IllegalArgumentException("Resource Ids do not match");
- Resource resource = obtainResource(resourceId);
+ Resource resource = fetchResource(resourceId);
AvailabilityType at;
at = AvailabilityType.valueOf(avail.getType());
@@ -541,15 +530,6 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
- private Resource obtainResource(int resourceId) {
- Resource resource = resMgr.getResource(caller, resourceId);
- if (resource == null) {
- resource = resMgr.getResource(caller, resourceId);
- if (resource != null)
- putToCache(resourceId, Resource.class, resource);
- }
- return resource;
- }
@GZIP
@AddLinks
@@ -565,7 +545,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
criteria.addFilterResourceIds(resourceId);
- List<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
+ PageList<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
List<Link> links = new ArrayList<Link>(alerts.size());
for (Alert al : alerts) {
Link link = new Link();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 3a7e961..7e20630 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test(enabled = false)
+ @Test
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index fca0f50..e02a723 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -23,6 +23,7 @@ import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.response.Response;
+import org.hamcrest.Matchers;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.AlertCondition;
@@ -34,7 +35,10 @@ import org.rhq.modules.integrationTests.restApi.d.Group;
import static com.jayway.restassured.RestAssured.delete;
import static com.jayway.restassured.RestAssured.expect;
import static com.jayway.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.instanceOf;
@@ -54,6 +58,7 @@ public class AlertTest extends AbstractBase {
.header(acceptJson)
.expect()
.statusCode(200)
+ .log().ifError()
.when()
.get("/alert");
@@ -66,6 +71,7 @@ public class AlertTest extends AbstractBase {
.header(acceptXml)
.expect()
.statusCode(200)
+ .log().ifError()
.when()
.get("/alert");
}
@@ -95,6 +101,23 @@ public class AlertTest extends AbstractBase {
}
@Test
+ public void testListAlertsWithPaging() throws Exception {
+
+ given()
+ .header(acceptJson)
+ .queryParam("ps", 2)
+ .queryParam("page", 0)
+ .expect()
+ .statusCode(200)
+ .header("Link", anyOf(containsString("current"), Matchers.containsString("last")))
+ .header("X-collection-size", notNullValue())
+ .log().ifError()
+ .when()
+ .get("/alert");
+ }
+
+
+ @Test
public void testGetAlertCountJson() throws Exception {
given()
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
index 2e74181..40ae7b0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
@@ -23,13 +23,17 @@ import java.util.List;
import java.util.Map;
import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.response.Headers;
import com.jayway.restassured.response.Response;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.Event;
import org.rhq.modules.integrationTests.restApi.d.EventSource;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
import static com.jayway.restassured.RestAssured.given;
/**
@@ -261,6 +265,131 @@ public class EventTest extends AbstractBase {
}
@Test
+ public void testAddGetEventOnSourceWithPaging() throws Exception {
+
+ EventSource es = new EventSource();
+ es.setResourceId(_platformId);
+ es.setName("Event Log"); // Name of the event definition
+ es.setLocation("-x-test-location");
+
+ Response response =
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .pathParam("id",_platformId)
+ .body(es)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/event/{id}/sources");
+
+ EventSource eventSource = response.as(EventSource.class);
+
+ long now = System.currentTimeMillis();
+ try {
+
+ // Add an event
+ Event event = new Event(eventSource.getId(),now,"Li la lu 1:->");
+ Event event1 = new Event(eventSource.getId(),now,"Li la lu 2:->");
+ Event event2 = new Event(eventSource.getId(),now,"Li la lu 3:->");
+ Event event3 = new Event(eventSource.getId(),now,"Li la lu 4:->");
+ List<Event> events = new ArrayList<Event>(4);
+ events.add(event);
+ events.add(event1);
+ events.add(event2);
+ events.add(event3);
+
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .pathParam("id",eventSource.getId())
+ .body(events)
+ .expect()
+ .statusCode(204) // no content returned
+ .log().ifError()
+ .when()
+ .post("/event/source/{id}/events");
+
+
+ // and retrieve it again from the event source
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", eventSource.getId())
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .when()
+ .get("/event/source/{id}/events");
+ List list = response.as(List.class);
+ assert list.size()>0;
+
+ // Get the list of events from the resource
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", _platformId)
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .header("Link",not(containsString("prev")))
+ .when()
+ .get("/event/{id}/events");
+ list = response.as(List.class);
+ assert list.size()==2;
+
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", _platformId)
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .queryParam("page",1)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .header("Link",not(containsString("next")))
+ .when()
+ .get("/event/{id}/events");
+
+ Headers headers = response.getHeaders();
+ int found = 0;
+ for (String link: headers.getValues("Link")) {
+ if (link.contains("rel='last'"))
+ found++;
+ if (link.contains("rel='prev'"))
+ found++;
+ if (link.contains("rel='current'"))
+ found++;
+ assert !link.contains("rel='next");
+ }
+ assert found == 3;
+
+ }
+ finally {
+
+ // Delete the source again
+ given()
+ .pathParam("id", eventSource.getId())
+ .expect()
+ .statusCode(204)
+ .when()
+ .delete("/event/source/{id}");
+ }
+ }
+
+ @Test
public void testDeleteUnknownSource() throws Exception {
given()
.pathParam("id", 123)
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
index 05bae96..a4ef048 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
@@ -74,6 +74,17 @@ public class GroupTest extends AbstractBase {
}
@Test
+ public void testGetGroupsWithPaging() throws Exception {
+ given()
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .when()
+ .get("/group");
+ }
+
+ @Test
public void testGetGroupsQuery() throws Exception {
given()
.queryParam("q","lala")
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 23480a0..b66d9b5 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -44,6 +44,8 @@ import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.not;
/**
* Test the resources part
@@ -242,7 +244,7 @@ public class ResourcesTest extends AbstractBase {
}
@Test
- public void testPaging() throws Exception {
+ public void testGetResourcesWithPaging() throws Exception {
given()
.header("Accept", "application/json")
@@ -252,12 +254,31 @@ public class ResourcesTest extends AbstractBase {
.queryParam("category", "service")
.expect()
.statusCode(200)
- .header("Link", containsString("page=2"))
+ .log().everything()
+ // .header("Link", allOf(containsString("page=2"), containsString("current")))
+ .header("Link",not(containsString("prev")))
.body("links.self", notNullValue())
.when().get("/resource");
}
@Test
+ public void testGetPlatformsWithPaging() throws Exception {
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("page", 0)
+ .queryParam("ps", 5)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("links.self", notNullValue())
+ .header("Link", not(containsString("prev=")))
+ .header("Link", anyOf(containsString("current"),containsString("last")))
+ .when().get("/resource/platforms");
+ }
+
+ @Test
public void testGetPlatformXml() {
assert _platformId!=0 : "Setup did not run or was no success";
commit e5d22cac1559f8f2dc699d3ebe3f54d0abf74a1a
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue May 21 22:10:26 2013 +0200
BZ 962853 - make getRresourceId return an int instead of a string.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 703e897..8273737 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -25,19 +25,11 @@ package org.rhq.enterprise.server.rest.domain;
import java.util.ArrayList;
import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
import com.wordnik.swagger.annotations.ApiClass;
import com.wordnik.swagger.annotations.ApiProperty;
-import org.jboss.resteasy.spi.touri.URITemplate;
-
/**
* A (partial) resource with some type information
* @author Heiko W. Rupp
@@ -69,7 +61,6 @@ public class ResourceWithType {
}
@ApiProperty("Name of the resource")
- @XmlElement
public String getResourceName() {
return resourceName;
}
@@ -79,17 +70,15 @@ public class ResourceWithType {
}
@ApiProperty("ID of the resource")
- @XmlID
- public String getResourceId() {
- return String.valueOf(resourceId);
+ public int getResourceId() {
+ return resourceId;
}
public void setResourceId(int resourceId) {
this.resourceId = resourceId;
}
- @ApiProperty("Name of the resource type of teh resource")
- @XmlElement
+ @ApiProperty("Name of the resource type of the resource")
public String getTypeName() {
return typeName;
}
@@ -99,7 +88,6 @@ public class ResourceWithType {
}
@ApiProperty("Id of the resource type of the resource")
- @XmlElement
public Integer getTypeId() {
return typeId;
}
@@ -109,7 +97,6 @@ public class ResourceWithType {
}
@ApiProperty("Name of the plugin defining the resource type")
- @XmlElement
public String getPluginName() {
return pluginName;
}
@@ -136,7 +123,6 @@ public class ResourceWithType {
this.status = status;
}
- @XmlElementRef
public List<Link> getLinks() {
return links;
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
index 9f6a02b..ae4e81d 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
@@ -98,8 +98,7 @@ public abstract class AbstractBase {
if (res!=null && res.get(0)!=null) {
- String tmp = ((Map <String,String>)res.get(0)).get("resourceId");
- int pid =Integer.valueOf(tmp);
+ Integer pid = ((Map <String,Integer>)res.get(0)).get("resourceId");
given()
.pathParam("id", pid)
@@ -125,9 +124,9 @@ public abstract class AbstractBase {
assert res != null;
for (Object entry : res) {
if (entry instanceof Map) {
- Map<String,String> map = (Map<String, String>) entry;
+ Map<String,Object> map = (Map<String, Object>) entry;
if (!map.get("resourceName").equals(REST_TEST_DUMMY)) {
- return Integer.valueOf(map.get("resourceId"));
+ return (Integer)map.get("resourceId");
}
}
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 7e3f45a..3515fac 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -30,6 +30,7 @@ import com.jayway.restassured.response.Response;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.CreateCBRRequest;
+import org.rhq.modules.integrationTests.restApi.d.Resource;
import static com.jayway.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
@@ -41,6 +42,8 @@ import static org.hamcrest.Matchers.isOneOf;
*/
public class ContentTest extends AbstractBase {
+ private static final String DEPLOYED_WAR_NAME = "test-simple.war";
+
@Test
public void testUpload() throws Exception {
@@ -144,6 +147,8 @@ public class ContentTest extends AbstractBase {
@Test
public void testCreatePackageBasedResource() throws Exception {
+ wipeWarArchiveIfNecessary();
+
InputStream in =
getClass().getClassLoader().getResourceAsStream("test-simple.war");
@@ -187,7 +192,7 @@ public class ContentTest extends AbstractBase {
assert resources.size()>0;
- int as7Id = Integer.valueOf((String)resources.get(0).get("resourceId"));
+ int as7Id = (Integer)resources.get(0).get("resourceId");
int createdResourceId=-1;
// create child of eap6 as deployment
@@ -203,7 +208,7 @@ public class ContentTest extends AbstractBase {
// set plugin config (path) and deploy config (runtime-name)
resource.getPluginConfig().put("path","deployment");
- resource.getResourceConfig().put("runtimeName","test-simple.war");
+ resource.getResourceConfig().put("runtimeName", DEPLOYED_WAR_NAME);
Response response =
given()
@@ -285,6 +290,34 @@ public class ContentTest extends AbstractBase {
}
+
+ private void wipeWarArchiveIfNecessary() {
+
+ @SuppressWarnings("unchecked")
+ List<Resource> resources =
+ given()
+ .queryParam("q",DEPLOYED_WAR_NAME)
+ .queryParam("category", "SERVICE")
+ .header(acceptJson)
+ .expect()
+ .log().everything()
+ .when()
+ .get("/resource")
+ .as(List.class);
+
+ if (resources!=null && resources.size()>0) {
+ int resourceId = resources.get(0).getResourceId();
+
+ given()
+ .pathParam("id", resourceId)
+ .queryParam("physical", "true") // Also remove target on the EAP instance
+ .expect()
+ .statusCode(200)
+ .when()
+ .delete("/resource/{id}");
+ }
+ }
+
@Test
public void testCreateCBRBadHandle() throws Exception {
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index cc9558b..23480a0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -69,8 +69,11 @@ public class ResourcesTest extends AbstractBase {
.expect()
.statusCode(200)
.contentType(ContentType.JSON)
- .log().ifError()
+ .log().everything()
.body("links.self", notNullValue())
+ .body("resourceId",is(_platformId))
+ .body("typeId",is(_platformTypeId))
+ .body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -101,9 +104,9 @@ public class ResourcesTest extends AbstractBase {
.log().everything()
.expect()
.statusCode(200)
- .body("id",is(typeId))
- .body("name",is("Linux"))
- .body("pluginName",is("Platforms"))
+ .body("id", is(typeId))
+ .body("name", is("Linux"))
+ .body("pluginName", is("Platforms"))
.log().everything()
.when()
.get("/resource/type/{typeId}");
@@ -187,7 +190,7 @@ public class ResourcesTest extends AbstractBase {
given()
.header("Accept", "application/json")
.with()
- .queryParam("status","NeW")
+ .queryParam("status", "NeW")
.expect()
.statusCode(200)
.when()
@@ -203,7 +206,7 @@ public class ResourcesTest extends AbstractBase {
.header("Accept", "application/json")
.with()
.queryParam("q", platformName)
- .queryParam("status","Frobnitz")
+ .queryParam("status", "Frobnitz")
.queryParam("category", "platform")
.expect()
.statusCode(406)
@@ -322,6 +325,26 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testCreatePlatformJson() throws Exception {
+
+ Resource resource = new Resource();
+ resource.setResourceName("dummy-test");
+ resource.setTypeName("Linux");
+
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .body(resource)
+ .expect()
+ .statusCode(201)
+ .log().everything()
+ .body("resourceId",instanceOf(Number.class))
+ .when()
+ .post("/resource/platforms");
+
+ }
+
+ @Test
public void testCreatePlatformWithBadType() throws Exception {
Resource resource = new Resource();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
index ea78d09..e7e1b9e 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
@@ -94,7 +94,7 @@ public class UserTest extends AbstractBase {
.when()
.get("/user/favorites/resource");
JsonPath jp = r.jsonPath();
- assert jp.getList("resourceId").contains(String.valueOf(_platformId));
+ assert jp.getList("resourceId").contains(_platformId);
}
finally {
given()
@@ -131,7 +131,7 @@ public class UserTest extends AbstractBase {
.when()
.get("/user/favorites/resource");
JsonPath jp = r.jsonPath();
- assert jp.getList("resourceId").contains(String.valueOf(_platformId));
+ assert jp.getList("resourceId").contains(_platformId);
}
finally {
given()
commit ec4f0228529bf490d44fc3be5407080f9360ef6c
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue May 21 21:45:23 2013 +0200
Print the failing class along with the failed field.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index d7cc470..867ea16 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -67,8 +67,8 @@ public final class CriteriaQueryGenerator {
private static final Log LOG = LogFactory.getLog(CriteriaQueryGenerator.class);
public enum AuthorizationTokenType {
- RESOURCE, // specifies the resource alias to join on for standard res-group-role-subject authorization checking
- GROUP; // specifies the group alias to join on for standard group-role-subject authorization checking
+ RESOURCE, // specifies the resource alias to join on for standard res-group-role-subject authorization checking
+ GROUP; // specifies the group alias to join on for standard group-role-subject authorization checking
}
private Criteria criteria;
@@ -333,8 +333,8 @@ public final class CriteriaQueryGenerator {
results.append("FROM ").append(className).append(' ').append(alias).append(NL);
if (countQuery == false) {
- /*
- * don't fetch in the count query to avoid: "query specified join fetching,
+ /*
+ * don't fetch in the count query to avoid: "query specified join fetching,
* but the owner of the fetched association was not present in the select list"
*/
for (String fetchField : getFetchFields(criteria)) {
@@ -383,7 +383,7 @@ public final class CriteriaQueryGenerator {
/*
* do not prefix the alias when:
- *
+ *
* 1) if the suffix is numerical, which allows us to sort by column ordinal
* 2) if the user wants full control and has explicitly chosen to disable alias prepending
*/
@@ -655,7 +655,7 @@ public final class CriteriaQueryGenerator {
} catch (RuntimeException re) {
LOG.error("Could not get JPQL translation for '" + searchExpression + "': "
+ ThrowableUtil.getAllMessages(re, true));
- throw re; // don't wrap exceptions that are already RuntimeExceptions in another RuntimeException
+ throw re; // don't wrap exceptions that are already RuntimeExceptions in another RuntimeException
} catch (Exception e) {
LOG.error("Could not get JPQL translation for '" + searchExpression + "': "
+ ThrowableUtil.getAllMessages(e, true));
@@ -694,7 +694,7 @@ public final class CriteriaQueryGenerator {
Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
persistentBagFields.add(field);
} catch (NoSuchFieldException e) {
- LOG.warn("Failed to add persistent bag collection.", e);
+ LOG.warn("Failed to add persistent bag collection on class [" + criteria.getPersistentClass().getName() +"]: ", e);
}
}
@@ -703,7 +703,7 @@ public final class CriteriaQueryGenerator {
Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
joinFetchFields.add(field);
} catch (NoSuchFieldException e) {
- LOG.warn("Failed to add join fetch field.", e);
+ LOG.warn("Failed to add join fetch field on class [" + criteria.getPersistentClass().getName() + "]: ", e);
}
}
@@ -741,7 +741,7 @@ public final class CriteriaQueryGenerator {
/**
* The groupBy clause can be set if and only if the projection is altered. The passed argument should not be
- * prefixed with 'group by'; that part of the query will be auto-generated if the argument is non-null. The
+ * prefixed with 'group by'; that part of the query will be auto-generated if the argument is non-null. The
* new projection must follow standard rules as they apply to statements with groupBy clauses.
*/
public void setGroupByClause(String groupByClause) {
@@ -753,7 +753,7 @@ public final class CriteriaQueryGenerator {
/**
* The having clause can be set if and only if the groupBy clause is set. The passed argument should not be
- * prefixed with 'having'; that part of the query will be auto-generated if the argument is non-null. The
+ * prefixed with 'having'; that part of the query will be auto-generated if the argument is non-null. The
* having clause must follow standard rules as they apply to statements with groupBy clauses.
*/
public void setHavingClause(String havingClause) {
commit 18aa1bc699a26717acfa2ba9af2ac072aafc2ce3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue May 21 15:06:55 2013 -0400
add jboss logging to eclipse classpath
diff --git a/.classpath b/.classpath
index 53037dd..2487128 100644
--- a/.classpath
+++ b/.classpath
@@ -230,6 +230,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/jboss-common-core/2.2.17.GA/jboss-common-core-2.2.17.GA.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/logging/jboss-logging/3.1.2.GA/jboss-logging-3.1.2.GA.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/servlet/jstl/1.1.2/jstl-1.1.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/struts-menu/struts-menu/2.3/struts-menu-2.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/junit/junit/3.8.2/junit-3.8.2.jar"/>
commit 3ef61c1860a590b16b461b81f85b0011b2ee620d
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon May 20 13:36:45 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - New method for creating an alert definitions was added to SLSB, because the UI requires the ids of newly created alert conditions.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
index b90b209..8fe6d4b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
@@ -140,7 +140,7 @@ public class ConditionEditor extends EnhancedVLayout {
private AlertCondition existingCondition;
public ConditionEditor(HashSet<AlertCondition> conditions, Map<Integer, AlertCondition> modifiedConditions,
- SelectItem conditionExpression, ResourceType rtype, Runnable closeFunc, AlertCondition existingCondition) {
+ SelectItem conditionExpression, ResourceType rtype, AlertCondition existingCondition, Runnable closeFunc) {
super();
this.editMode = existingCondition != null;
this.existingCondition = existingCondition;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
index 782e4b5..8f4a36f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
@@ -196,7 +196,7 @@ public class ConditionsEditor extends EnhancedVLayout {
}
});
- table.addTableAction(MSG.common_button_edit(), null, new AbstractTableAction(TableActionEnablement.SINGLE) {
+ table.addTableAction(MSG.view_alert_definition_editCondition(), null, new AbstractTableAction(TableActionEnablement.SINGLE) {
public void executeAction(ListGridRecord[] selection, Object actionValue) {
AlertCondition condition = getDataSource().copyValues(selection[0]);
showConditionEditor(condition);
@@ -252,7 +252,7 @@ public class ConditionsEditor extends EnhancedVLayout {
final int numConditions = conditions.size();
final ConditionEditor newConditionEditor = new ConditionEditor(conditions, modifiedConditions,
ConditionsEditor.this.conditionExpression, ConditionsEditor.this.resourceType,
- new Runnable() {
+ existingCondition, new Runnable() {
@Override
public void run() {
updated = updated || numConditions != conditions.size()
@@ -260,7 +260,7 @@ public class ConditionsEditor extends EnhancedVLayout {
winModal.markForDestroy();
refresh();
}
- }, existingCondition);
+ });
winModal.addItem(newConditionEditor);
winModal.show();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
index 2cbe8c6..d69f7f4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
@@ -197,15 +197,14 @@ public class ResourceAlertDefinitionsView extends AbstractAlertDefinitionsView {
protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals,
final AsyncCallback<AlertDefinition> resultReceiver) {
if (alertDefinition.getId() == 0) {
- GWTServiceLookup.getAlertDefinitionService().createAlertDefinition(alertDefinition,
- Integer.valueOf(resource.getId()), new AsyncCallback<Integer>() {
+ GWTServiceLookup.getAlertDefinitionService().createAlertDefinitionAndReturn(alertDefinition,
+ Integer.valueOf(resource.getId()), new AsyncCallback<AlertDefinition>() {
@Override
- public void onSuccess(Integer result) {
+ public void onSuccess(AlertDefinition result) {
CoreGUI.getMessageCenter().notify(
new Message(MSG.view_alert_definitions_create_success(), Severity.Info));
- alertDefinition.setId(result.intValue());
ResourceAlertDefinitionsView.this.refresh();
- resultReceiver.onSuccess(alertDefinition);
+ resultReceiver.onSuccess(result);
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index c86d0cd..25742f5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -146,10 +146,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+ unregisterHandler();
setAlertDefinition(getAlertDefinition()); // reverts data back to original
makeViewOnly();
}
@@ -159,6 +156,15 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
addMember(tabSet);
addMember(buttons);
}
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ if (alertDefinition == null || alertDefinition.getId() == 0) {
+ // disable the back button when creating new definition
+ setBackButtonDisabled(true);
+ }
+ }
public AlertDefinition getAlertDefinition() {
return alertDefinition;
@@ -197,8 +203,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
recovery.makeEditable();
dampening.makeEditable();
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
+ unregisterHandler();
handlerRegistration = addVisibilityChangedHandler(new VisibilityChangedHandler() {
public void onVisibilityChanged(VisibilityChangedEvent event) {
if (!event.getIsVisible()) {
@@ -207,15 +212,13 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
if (value) {
save();
}
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
}
});
}
}
});
// disable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(true);
+ setBackButtonDisabled(true);
}
public void makeViewOnly() {
@@ -228,6 +231,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
notifications.makeViewOnly();
recovery.makeViewOnly();
dampening.makeViewOnly();
+ setBackButtonDisabled(false);
}
public void saveAlertDefinition() {
@@ -249,20 +253,13 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
new AsyncCallback<AlertDefinition>() {
@Override
public void onSuccess(final AlertDefinition alertDef) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
setAlertDefinition(alertDef);
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+ unregisterHandler();
}
@Override
public void onFailure(Throwable caught) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
-
+ unregisterHandler();
// no error handling, the notification is done in the subclasses of AbstractAlertDefinitionsView
}
});
@@ -270,4 +267,22 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
tabSet.selectTab(generalPropertiesTab);
}
}
+
+ private void setBackButtonDisabled(boolean enabled) {
+ Canvas layoutCandidate = getParentElement();
+ if (layoutCandidate instanceof EnhancedVLayout) {
+ EnhancedVLayout parentLayout = (EnhancedVLayout) getParentElement();
+ Canvas backButton = parentLayout.getMember("backButton");
+ if (backButton != null) {
+ backButton.setDisabled(enabled);
+ }
+ }
+ }
+
+ private void unregisterHandler() {
+ if (handlerRegistration != null) {
+ handlerRegistration.removeHandler();
+ handlerRegistration = null;
+ }
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
index 0921b2b..794a67f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
@@ -32,6 +32,9 @@ public interface AlertDefinitionGWTService extends RemoteService {
int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException;
+ AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId)
+ throws RuntimeException;
+
AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition, boolean purgeInternals)
throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
index 181eef5..da1d981 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
@@ -66,8 +66,18 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
@Override
public int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
try {
- int results = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(), alertDefinition, resourceId, true);
- return results;
+ int result = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(), alertDefinition, resourceId, true);
+ return result;
+ } catch (Throwable t) {
+ throw getExceptionToThrowToClient(t);
+ }
+ }
+
+ @Override
+ public AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
+ try {
+ AlertDefinition result = alertDefManager.createAlertDefinitionAndRerurnIt(getSessionSubject(), alertDefinition, resourceId, true);
+ return SerialUtility.prepare(result, "createAlertDefinitionAndReturn");
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
@@ -77,9 +87,9 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
public AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition,
boolean resetMatching) throws RuntimeException {
try {
- AlertDefinition results = alertDefManager.updateAlertDefinition(getSessionSubject(), alertDefinitionId,
+ AlertDefinition result = alertDefManager.updateAlertDefinition(getSessionSubject(), alertDefinitionId,
alertDefinition, resetMatching);
- return SerialUtility.prepare(results, "updateAlertDefinition");
+ return SerialUtility.prepare(result, "updateAlertDefinition");
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index d00a969..8f8fec5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -201,19 +201,30 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId)
throws InvalidAlertDefinitionException {
-
- return createAlertDefinitionInternal(subject, alertDefinition, resourceId, false, false);
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, false,
+ false);
+ return newAlertDefinition.getId();
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean validateNotificationConfiguration)
- throws InvalidAlertDefinitionException {
-
- return createAlertDefinitionInternal(subject, alertDefinition, resourceId, true, validateNotificationConfiguration);
+ public int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
+ validateNotificationConfiguration);
+ return newAlertDefinition.getId();
+ }
+
+ @Override
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
+ validateNotificationConfiguration);
+ return newAlertDefinition;
}
- private int createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ private AlertDefinition createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
checkAlertDefinition(subject, null, alertDefinition, resourceId, validateNotificationConfiguration);
// if this is an resource alert definition, set up the link to a resource
@@ -279,7 +290,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
AlertDefinitionEvent.CREATED);
}
- return alertDefinition.getId();
+ return alertDefinition;
}
private void fixRecoveryId(AlertDefinition definition) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index 5afa1f9..ee0e161 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -65,6 +65,29 @@ public interface AlertDefinitionManagerLocal {
*/
int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean finalizeNotificationConfiguration)
throws InvalidAlertDefinitionException;
+
+ /**
+ * Creates a new alert definition. Note that the suject is checked to have necessary authz, which might not
+ * be what you want in all use cases. See {@link #createDependentAlertDefinition(Subject, AlertDefinition, int)}
+ * for further discussion of this. The only difference between
+ * {@link GroupAlertDefinitionManagerLocal#createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)}
+ * and this method is the return type.
+ *
+ * @param subject the user creating the alert definition
+ * @param alertDefinition the new alert definition to persist
+ * @param resourceId the resource id for which the def is being created
+ * @param finalizeNotificationConfiguration if true, the configuration of the def's notifications is validated.
+ * This is NOT what you want if, for example, you are merely creating a copy of an existing definition.
+ * Some notifications might require more input when creating the notification than is then persisted in their configs
+ * (prominent example being the CLI alert sender).
+ * This would then cause the validation to fail every time you created a copy of a definition and tried
+ * to persist it. Note that passing false AND having new, unpersisted notifications in the alert definition can
+ * lead to invalid configuration being stored for the notifications.
+ * @return the instance of newly created alert definition
+ * @throws InvalidAlertDefinitionException
+ */
+ AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException;
/**
* This is exactly the same as {@link #createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)} but
commit b638cc12a5796b7ccb3789bf94768303b0ce0e3c
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon May 20 13:29:43 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - I18n (Instead of "Edit", now the button label says "Edit Condition").
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 00a68ef..b630706 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -977,6 +977,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Trait Value
view_alert_definition_condition_editor_option_operation = Operation Execution
view_alert_definition_condition_editor_option_resource_configuration = Resource Configuration Change
view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = View Group Definition
view_alert_definition_for_type = View Template
view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index a27fb3c..cab205f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -993,6 +993,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Změna hodno
view_alert_definition_condition_editor_option_operation = Spuštění operace
view_alert_definition_condition_editor_option_resource_configuration = Změna konfigurace zdroje
view_alert_definition_condition_editor_resource_configuration_tooltip = Podmínka je splněna, když se změní konfigurace zdroje.
+view_alert_definition_editCondition = Editovat podmínku
view_alert_definition_for_group = Zobrazit definici skupiny
view_alert_definition_for_type = Zobrazit šablonu
view_alert_definition_notification_cliScript_editor_anotherUser = Jiný uživatel
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 902951d..057785a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -883,6 +883,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Änderung de
view_alert_definition_condition_editor_option_operation = Ausführung der Operation
view_alert_definition_condition_editor_option_resource_configuration = Änderung der Konfiguration der Ressource
##view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = Gruppendefinition ansehen
view_alert_definition_for_type = Vorlage ansehen
view_alert_definition_notification_cliScript_editor_anotherUser = Anderer Benutzer
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 8f47413..a929966 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -969,6 +969,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = トレイト
view_alert_definition_condition_editor_option_operation = オペレーションの実行
view_alert_definition_condition_editor_option_resource_configuration = リソース構成の変化
view_alert_definition_condition_editor_resource_configuration_tooltip = この条件はリソース構成が変更されると引き起こされます
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = ビューグループ定義
view_alert_definition_for_type = ビューテンプレート
view_alert_definition_notification_cliScript_editor_anotherUser = 別のユーザー
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 5d19d06..da0a8a5 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -846,6 +846,7 @@ view_alert_definition_condition_editor_option_metric_threshold = 측정 절대
view_alert_definition_condition_editor_option_metric_trait_change = 특성값의 변화
view_alert_definition_condition_editor_option_resource_configuration = 자원 구성의 변화
view_alert_definition_condition_editor_resource_configuration_tooltip = 이 조건은 자원 구성이 변경되면 발생합니다.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = 뷰 그룹 정의
view_alert_definition_notification_cliScript_editor_anotherUser = 다른 사용자
view_alert_definition_notification_cliScript_editor_existingScript = 기존의 스크립트
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 743c4b5..9f342d7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -977,6 +977,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Mudan\u00E7a
view_alert_definition_condition_editor_option_operation = Execu\u00E7\u00E3o de Opera\u00E7\u00E3o
view_alert_definition_condition_editor_option_resource_configuration = Mudan\u00E7a na Configura\u00E7\u00E3o do Recurso
view_alert_definition_condition_editor_resource_configuration_tooltip = Essa condi\u00E7\u00E3o \u00E9 disparada quando a configura\u00E7\u00E3o do recurso for alterada.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = Visualizar Defini\u00E7\u00E3o de Grupo
view_alert_definition_for_type = Visualizar Template
view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 772c4e4..c8ee796 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -943,6 +943,7 @@
#view_alert_definition_condition_editor_option_operation = Operation Execution
#view_alert_definition_condition_editor_option_resource_configuration = Resource Configuration Change
#view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
#view_alert_definition_for_group = View Group Definition
#view_alert_definition_for_type = View Template
#view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 03dfa4e..147b9f8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -963,6 +963,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Trait Value
view_alert_definition_condition_editor_option_operation = Operation Execution
view_alert_definition_condition_editor_option_resource_configuration = \u8d44\u6e90\u914d\u7f6e\u6539\u53d8
view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = \u67e5\u770b\u7ec4\u5b9a\u4e49
view_alert_definition_for_type = \u67e5\u770b\u6a21\u677f
view_alert_definition_notification_cliScript_editor_anotherUser = \u5176\u4ed6\u7528\u6237
commit edaffb818aec221eb0db5338fcf2e669b06e5a70
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 17 17:09:35 2013 -0400
BZ 963982 - make sure we persist the token when the registration was successful, even if the server endpoint was bad
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
index 6e1a95a..a8d8bdf 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
@@ -1376,6 +1376,7 @@ public class AgentMain {
try {
AgentRegistrationResults results = remote_pojo.registerAgent(request);
failover_list = results.getFailoverList();
+ token = results.getAgentToken(); // make sure our finally block gets this - BZ 963982
// Try to do a simple connect to each server in the failover list
// If only some of the servers are unreachable, just keep going;
@@ -1407,7 +1408,6 @@ public class AgentMain {
m_registration = results;
got_registered = true;
retry = false;
- token = results.getAgentToken();
LOG.info(AgentI18NResourceKeys.AGENT_REGISTRATION_RESULTS, results);
} finally {
// stores the new one if successful; restores the old one if we failed for some reason to register
commit 92fd97dd84324980487972bda6f424114e1e712d
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 17 14:11:32 2013 +0200
BZ 962858 check passed resource id and return 404 if invalid
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 288e9f7..70cc588 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -559,6 +559,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiOperation("Get a list of links to the alerts for the passed resource")
public List<Link> getAlertsForResource(@ApiParam("Id of the resource to query") @PathParam("id") int resourceId) {
AlertCriteria criteria = new AlertCriteria();
+
+ // Check for resource existence
+ fetchResource(resourceId);
+
criteria.addFilterResourceIds(resourceId);
List<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 3efd807..cc9558b 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -593,6 +593,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAlertsForUnknownResource() throws Exception {
+ given()
+ .header("Accept", "application/json")
+ .pathParam("id", 12345)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/alerts");
+ }
+
+ @Test
public void testSchedulesForResource() throws Exception {
given()
.header("Accept", "application/json")
commit b8207e9ec0efcf679af774e870f1c3b70fafc6fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 17 09:26:14 2013 +0200
Disable for the moment
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 7e20630..3a7e961 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test
+ @Test(enabled = false)
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
commit 9a040dd824209eb9e71bb22c7cf7d80a7c468485
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Fri May 17 12:41:31 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - Making the "Back to List" button disabled when editing the alert definition.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
index 14b6abf..d915cb0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
@@ -1,8 +1,5 @@
package org.rhq.enterprise.gui.coregui.client.alert.definitions;
-import java.util.Map;
-
-import org.rhq.core.domain.alert.AlertCondition;
import org.rhq.core.domain.alert.AlertDefinition;
/**
@@ -12,8 +9,6 @@ public interface EditAlertDefinitionForm {
AlertDefinition getAlertDefinition();
-// Map<Integer, AlertCondition> getUpdatedAlertConditions();
-
boolean isResetMatching();
void setAlertDefinition(AlertDefinition alertDef);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index b4504c9..c86d0cd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -28,6 +28,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
@@ -145,7 +146,10 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
setAlertDefinition(getAlertDefinition()); // reverts data back to original
makeViewOnly();
}
@@ -193,6 +197,8 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
recovery.makeEditable();
dampening.makeEditable();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
handlerRegistration = addVisibilityChangedHandler(new VisibilityChangedHandler() {
public void onVisibilityChanged(VisibilityChangedEvent event) {
if (!event.getIsVisible()) {
@@ -201,12 +207,15 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
if (value) {
save();
}
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
}
});
}
}
});
+ // disable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(true);
}
public void makeViewOnly() {
@@ -240,13 +249,21 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
new AsyncCallback<AlertDefinition>() {
@Override
public void onSuccess(final AlertDefinition alertDef) {
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
setAlertDefinition(alertDef);
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
}
@Override
public void onFailure(Throwable caught) {
- // nothing, the notification is done in the subclasses of AbstractAlertDefinitionsView
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+
+ // no error handling, the notification is done in the subclasses of AbstractAlertDefinitionsView
}
});
} else {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
index efab26d..41819e1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
@@ -41,6 +41,7 @@ public class BackButton extends StretchImgButton {
public BackButton(String title, final String anchor) {
this();
setTitle("<b>" + title + "</b>");
+ setID("backButton");
addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
CoreGUI.goToView(anchor);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png
new file mode 100644
index 0000000..c323816
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png differ
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png
new file mode 100644
index 0000000..d6cf484
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png differ
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png
new file mode 100644
index 0000000..2addd3a
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png differ
commit d074bd8fa3daf63342bd5426e8599b0cb8f10cef
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:39 2013 +0200
We don't need standalone-osgi.xml
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 05619cb..e9f3bbe 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -220,6 +220,7 @@
<fileset dir="${jboss.home}/standalone/configuration">
<include name="standalone-ha.xml" />
<include name="standalone.xml" />
+ <include name="standalone-osgi.xml" />
<include name="standalone-full-ha.xml" />
</fileset>
</delete>
commit 4e91d0dc17e549213f61ee6a9251423d65c4ccce
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:23 2013 +0200
Fix a small typo
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 5415ed0..902951d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1235,7 +1235,7 @@ view_core_uncaught = Es ist eine nicht abgefangene Ausnahme aufgetreten.
view_dashboardManager_deleteFail = Konnte das Dashboard nicht löschen.
view_dashboardManager_deleted = Dashboard {0} erfolgreich gelöscht
view_dashboardManager_error = Konnte das Dashboard nicht auf dem Server sichern
-view_dashboardManager_saved = Das Dashboard {0} wurde auf dem Server geichert
+view_dashboardManager_saved = Das Dashboard {0} wurde auf dem Server gesichert
view_dashboardManager_success = Dashboard gespeichert
view_dashboard_favorites_error1 = Konnte die Ressoucen-Lesezeichen nicht laden
view_dashboardsManager_error1 = Konnte das neue Dashboard nicht hinzufügen
commit ba97ade9666a32cd20e071110c98a45e32d7f9fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:08 2013 +0200
BZ 961656 - enable LDAP support for the REST-api as well.
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
index 5caa45e..99e2f4d 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
@@ -39,6 +39,7 @@ public class SecurityDomainJBossASClient extends JBossASClient {
public static final String SECURITY_DOMAIN = "security-domain";
public static final String CACHE_TYPE = "cache-type";
public static final String AUTHENTICATION = "authentication";
+ public static final String LOGIN_MODULE = "login-module";
public static final String LOGIN_MODULES = "login-modules";
public static final String CLASSIC = "classic";
public static final String CODE = "code";
@@ -376,6 +377,36 @@ public class SecurityDomainJBossASClient extends JBossASClient {
return;
}
+ /**
+ * send a :flush-cache operation to the passed security domain
+ * @param domain simple name of the domain
+ * @throws Exception
+ */
+ public void flushSecurityDomainCache(String domain) throws Exception {
+ Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN,domain);
+ ModelNode request = createRequest("flush-cache",addr);
+ ModelNode result = execute(request);
+ if (!isSuccess(result)) {
+ log.warn("Flushing " + domain + " failed - principals may be longer cached than expected");
+ }
+ }
+
+ /**
+ * Check if a certain login module is present inside the passed security domain
+ * @param domainName Name of the security domain
+ * @param moduleName Name of the Login module - wich usually is it FQCN
+ * @return True if the module is present
+ * @throws Exception
+ */
+ public boolean securityDomainHasLoginModule(String domainName, String moduleName) throws Exception {
+ Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN,domainName);
+ addr.add(AUTHENTICATION,CLASSIC);
+ addr.add(LOGIN_MODULE,moduleName);
+ ModelNode request = createRequest("read-resource", addr);
+ ModelNode response = execute(request);
+ return isSuccess(response);
+ }
+
/** Immutable helper */
public static class LoginModuleRequest {
private AppConfigurationEntry entry;
diff --git a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
index 319b990..a98b367 100644
--- a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
+++ b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
@@ -2,4 +2,6 @@
<jboss-web>
<security-domain>RHQRESTSecurityDomain</security-domain>
+ <!-- see https://community.jboss.org/wiki/JBossAS7SecurityAuditing for the next tag -->
+ <!--<disable-audit>false</disable-audit>-->
</jboss-web>
diff --git a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
index fb75d94..b601346 100644
--- a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
@@ -10,7 +10,7 @@
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</auth-constraint>
</security-constraint>
@@ -21,7 +21,7 @@
<security-role>
<description>This is valid for all principals, as we do internal checks</description>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</security-role>
</web-app>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
index 1ef5880..28f365f 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
@@ -3,4 +3,6 @@
<jboss-web>
<context-root>rest</context-root>
<security-domain>RHQRESTSecurityDomain</security-domain>
+ <!-- see https://community.jboss.org/wiki/JBossAS7SecurityAuditing for the next tag -->
+ <!--<disable-audit>false</disable-audit>-->
</jboss-web>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index f96839d..f336c60 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -57,7 +57,7 @@
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</auth-constraint>
</security-constraint>
@@ -68,7 +68,7 @@
<security-role>
<description>This is valid for all principals, as we do internal checks</description>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</security-role>
</web-app>
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 8173e68..0b9c078 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -278,6 +278,9 @@ public class InstallerServiceImpl implements InstallerService {
// Set up the logging subsystem
ServerInstallUtil.configureLogging(mcc, serverProperties);
+ ServerInstallUtil.createUserSecurityDomain(mcc);
+ ServerInstallUtil.createRestSecurityDomain(mcc);
+
// create a keystore whose cert has a CN of this server's public endpoint address
File keystoreFile = ServerInstallUtil.createKeystore(serverDetails != null ? serverDetails
: getServerDetailsFromPropertiesOnly(serverProperties), appServerConfigDir);
@@ -601,7 +604,7 @@ public class InstallerServiceImpl implements InstallerService {
* Save the given properties to the server's .properties file.
*
* Note that this is private - it is not exposed to the installer UI. It should have no need to save
- * this data outside of the normal installation process (see {@link #install()}).
+ * this data outside of the normal installation process (see {@link #install}).
*
* @param serverProperties the server properties to save
* @throws Exception if failed to save the properties to the .properties file
@@ -1013,9 +1016,6 @@ public class InstallerServiceImpl implements InstallerService {
// create the security domain needed by the datasources
ServerInstallUtil.createDatasourceSecurityDomain(mcc, serverProperties);
- // create the security domain needed by REST
- ServerInstallUtil.createRESTSecurityDomain(mcc, serverProperties);
-
// set up REST cache
ServerInstallUtil.createNewCaches(mcc, serverProperties);
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
index d6e0d10..3a19833 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
@@ -38,6 +38,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
+import javax.security.auth.login.AppConfigurationEntry;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.Project;
@@ -133,8 +135,6 @@ public class ServerInstallUtil {
"jboss.management.https.port", 6443));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_MGMT_NATIVE,
"jboss.management.native.port", 6999));
- defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_OSGI_HTTP,
- "rhq.server.socket.binding.port.osgi-http", 7090, false));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_REMOTING,
"rhq.server.socket.binding.port.remoting", 3447));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_TXN_RECOVERY_ENV,
@@ -146,7 +146,10 @@ public class ServerInstallUtil {
private static final String RHQ_DATASOURCE_NAME_NOTX = "NoTxRHQDS";
private static final String RHQ_DATASOURCE_NAME_XA = "RHQDS";
private static final String RHQ_DS_SECURITY_DOMAIN = "RHQDSSecurityDomain";
+ private static final String RHQ_USER_SECURITY_DOMAIN = "RHQUserSecurityDomain";
private static final String RHQ_REST_SECURITY_DOMAIN = "RHQRESTSecurityDomain";
+ private static final String JDBC_LOGIN_MODULE_NAME = "org.rhq.enterprise.server.core.jaas.JDBCLoginModule";
+ private static final String DELEGATIG_LOGIN_MODULE_NAME = "org.rhq.enterprise.server.core.jaas.DelegatingLoginModule";
private static final String JDBC_DRIVER_POSTGRES = "postgres";
private static final String JDBC_DRIVER_ORACLE = "oracle";
private static final String JMS_ALERT_CONDITION_QUEUE = "AlertConditionQueue";
@@ -299,6 +302,48 @@ public class ServerInstallUtil {
}
/**
+ * Create the standard user security domain with the JDBCLogin module installed
+ *
+ * @param mcc ModelControllerClient to talk to the underlying AS
+ * @throws Exception If anything goes wrong
+ */
+ public static void createUserSecurityDomain(ModelControllerClient mcc) throws Exception {
+
+ Map<String,String> options = new HashMap<String, String>(2);
+ options.put("hashAlgorithm", "MD5");
+ options.put("hashEncoding", "base64");
+
+ SecurityDomainJBossASClient.LoginModuleRequest loginModuleRequest = new SecurityDomainJBossASClient.LoginModuleRequest(JDBC_LOGIN_MODULE_NAME,
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, options);
+
+
+ SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+ client.createNewSecurityDomain(RHQ_USER_SECURITY_DOMAIN,loginModuleRequest);
+
+ }
+
+ /**
+ * Create a security domain for container managed security used with the rhq-rest.war
+ * @param mcc ModelControllerClient to talk to the underlying AS.
+ * @throws Exception If anything goes wrong
+ */
+ public static void createRestSecurityDomain(ModelControllerClient mcc) throws Exception {
+
+ Map<String,String> options = new HashMap<String, String>(2);
+ options.put("delegateTo", RHQ_USER_SECURITY_DOMAIN);
+ options.put("roles", "rest-user");
+
+ SecurityDomainJBossASClient.LoginModuleRequest loginModuleRequest = new SecurityDomainJBossASClient.LoginModuleRequest(DELEGATIG_LOGIN_MODULE_NAME,
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, options);
+
+
+ SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+ client.createNewSecurityDomain(RHQ_REST_SECURITY_DOMAIN,loginModuleRequest);
+ }
+
+
+
+ /**
* Creates the JMS Queues required for Drift and Alerting.
*
* @param mcc the JBossAS management client
@@ -367,28 +412,6 @@ public class ServerInstallUtil {
return;
}
- /**
- * Creates the security domain for REST.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the obfuscated password to store in the security domain
- * @throws Exception
- */
- public static void createRESTSecurityDomain(ModelControllerClient mcc, HashMap<String, String> serverProperties)
- throws Exception {
-
- final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final String securityDomain = RHQ_REST_SECURITY_DOMAIN;
- if (!client.isSecurityDomain(securityDomain)) {
- String dsJndiName = "java:jboss/datasources/" + RHQ_DATASOURCE_NAME_XA;
- client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- LOG.info("Security domain [" + securityDomain + "] created");
- } else {
- LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
- }
- }
/**
* Creates the Infinispan caches for RHQ.
@@ -856,7 +879,7 @@ public class ServerInstallUtil {
/**
* Returns a database connection with the given set of properties providing the settings that allow for a successful
* database connection. If <code>props</code> is <code>null</code>, it will use the server properties from
- * {@link #getServerProperties()}.
+ * {@link #getServerProperties}.
*
* @param connectionUrl
* @param userName
@@ -898,7 +921,7 @@ public class ServerInstallUtil {
* Use the internal JBossAS mechanism to de-obfuscate a password back to its
* clear text form. This is not true encryption.
*
- * @param obfuscatedPasswordd the obfuscated password
+ * @param obfuscatedPassword the obfuscated password
* @return the clear-text password
*/
public static String deobfuscatePassword(String obfuscatedPassword) {
@@ -1003,7 +1026,7 @@ public class ServerInstallUtil {
/**
* This will create the database schema in the database. <code>props</code> define the connection to the database -
*
- * <p>Note that if the {@link #isDatabaseSchemaExist(Properties) schema already exists}, it will be purged of all
+ * <p>Note that if the {@link #isDatabaseSchemaExist schema already exists}, it will be purged of all
* data/tables and recreated.</p>
*
* @param props the full set of server properties
@@ -1039,7 +1062,7 @@ public class ServerInstallUtil {
/**
* This will update an existing database schema so it can be upgraded to the latest schema version.
*
- * <p>Note that if the {@link #isDatabaseSchemaExist(Properties) schema does not already exist}, errors will
+ * <p>Note that if the {@link #isDatabaseSchemaExist schema does not already exist}, errors will
* occur.</p>
*
* @param props the full set of server properties
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
index 95dd58f..73eeca5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
@@ -57,7 +57,6 @@ import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceMBean, MBeanRegistration {
private Log log = LogFactory.getLog(CustomJaasDeploymentService.class.getName());
- private MBeanServer mbeanServer = null;
/**
* Constructor for {@link CustomJaasDeploymentService}.
@@ -70,21 +69,51 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
*/
public void installJaasModules() {
try {
- log.info("Installing RHQ Server's JAAS login modules");
+ log.info("Updating RHQ Server's JAAS login modules");
Properties systemConfig = LookupUtil.getSystemManager().getSystemConfiguration(
LookupUtil.getSubjectManager().getOverlord());
- registerJaasModules(systemConfig);
+ updateJaasModules(systemConfig);
} catch (Exception e) {
log.fatal("Error deploying JAAS login modules", e);
throw new RuntimeException(e);
}
}
+ @Override
+ public void upgradeRhqUserSecurityDomainIfNeeded() {
+ try {
+ Properties systemConfig = LookupUtil.getSystemManager().getSystemConfiguration(
+ LookupUtil.getSubjectManager().getOverlord());
+
+ String value = systemConfig.getProperty(SystemSetting.LDAP_BASED_JAAS_PROVIDER.getInternalName());
+ boolean isLdapAuthenticationEnabled = (value != null) ? RHQConstants.LDAPJAASProvider.equals(value) : false;
+
+ if (isLdapAuthenticationEnabled) {
+
+ ModelControllerClient mcc = null;
+ mcc = ManagementService.getClient();
+ final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+
+ boolean ldapModulesPresent = client.securityDomainHasLoginModule(RHQ_USER_SECURITY_DOMAIN,
+ "org.rhq.enterprise.server.core.jaas.LdapLoginModule");
+
+
+ if (!ldapModulesPresent) {
+ log.info("Updating RHQ Server's JAAS login modules with LDAP support");
+ updateJaasModules(systemConfig);
+ }
+ }
+ } catch (Exception e) {
+ log.fatal("Error deploying JAAS login modules", e);
+ throw new RuntimeException(e);
+ }
+
+ }
+
/**
* @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer,javax.management.ObjectName)
*/
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
- this.mbeanServer = server;
return name;
}
@@ -107,13 +136,13 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
}
/**
- * Will register the necessary JAAS login Modules. The RHQ_USER_SECURITY_DOMAIN will be created, or recreated
- * if it already exists. This allows us to add/remove ldap support as it is enabled or disabled.
- *
- * @param systemConfig
+ * Will update the necessary JAAS login Modules. The RHQ_USER_SECURITY_DOMAIN will be created, or recreated
+ * if it already exists. This allows us to add/remove ldap support as it is enabled or disabled.
+ *
+ * @param systemConfig System configuration to read the LDAP settings from
* @throws Exception
*/
- private void registerJaasModules(Properties systemConfig) throws Exception {
+ private void updateJaasModules(Properties systemConfig) throws Exception {
ModelControllerClient mcc = null;
try {
@@ -144,7 +173,7 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE, getJdbcOptions(systemConfig));
loginModules.add(jdbcPrincipalCheckLoginModule);
- // this is the LDAP module that checks the LDAP for auth
+ // this is the LDAP module that checks the LDAP for auth
Map<String, String> ldapModuleOptionProperties = getLdapOptions(systemConfig);
try {
validateLdapOptions(ldapModuleOptionProperties);
@@ -170,7 +199,8 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
client.createNewSecurityDomain(RHQ_USER_SECURITY_DOMAIN,
loginModules.toArray(new LoginModuleRequest[loginModules.size()]));
- log.info("Security domain [" + RHQ_USER_SECURITY_DOMAIN + "] created with login modules " + loginModules);
+ client.flushSecurityDomainCache("RHQRESTSecurityDomain");
+ log.info("Security domain [" + RHQ_USER_SECURITY_DOMAIN + "] re-created with login modules " + loginModules);
} catch (Exception e) {
throw new Exception("Error registering RHQ JAAS modules", e);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
index 8d53e2b..47fcc48 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
@@ -41,4 +41,12 @@ public interface CustomJaasDeploymentServiceMBean {
* Installs the JAAS Modules that JON Server uses to allow users to log in.
*/
void installJaasModules();
+
+ /**
+ * Called from the startup bean and will upgrade an existing
+ * RHQUserSecurityDomain if needed - that is if the system
+ * settings say that LDAP support is enabled, but the underlying
+ * modules are not present
+ */
+ void upgradeRhqUserSecurityDomainIfNeeded();
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index 90ffbaf..7963b26 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -95,7 +95,7 @@ import org.rhq.enterprise.server.util.concurrent.AvailabilityReportSerializer;
* This startup singleton EJB performs the rest of the RHQ Server startup initialization.
* In order for it to do its work properly, we must ensure everything has been deployed and started;
* specifically, all EJBs must have been deployed and available.
- *
+ *
* This bean is not meant for client consumption - it is only for startup initialization.
*/
@Singleton
@@ -195,7 +195,7 @@ public class StartupBean implements StartupLocal {
initScheduler(); // make sure this is initialized before starting the plugin deployer
startPluginDeployer(); // make sure this is initialized before starting the server plugin container
startServerPluginContainer(); // before comm in case an agent wants to talk to it
- installJaasModules();
+ upgradeRhqUserSecurityDomainIfNeeded();
startServerCommunicationServices();
startScheduler();
scheduleJobs();
@@ -396,8 +396,7 @@ public class StartupBean implements StartupLocal {
*
* @throws RuntimeException
*/
- private void installJaasModules() throws RuntimeException {
- log.info("Installing JAAS login modules...");
+ private void upgradeRhqUserSecurityDomainIfNeeded() throws RuntimeException {
try {
CustomJaasDeploymentServiceMBean jaas_mbean;
@@ -406,9 +405,9 @@ public class StartupBean implements StartupLocal {
Class<?> iface = CustomJaasDeploymentServiceMBean.class;
jaas_mbean = (CustomJaasDeploymentServiceMBean) MBeanServerInvocationHandler.newProxyInstance(mbs, name,
iface, false);
- jaas_mbean.installJaasModules();
+ jaas_mbean.upgradeRhqUserSecurityDomainIfNeeded();
} catch (Exception e) {
- throw new RuntimeException("Cannot install JAAS login modules!", e);
+ throw new RuntimeException("Cannot upgrade JAAS login modules!", e);
}
}
@@ -632,7 +631,7 @@ public class StartupBean implements StartupLocal {
log.error("Cannot schedule server plugin jobs.", e);
}
- // Alerting Availability Duration Job (create only, nothing actually scheduled here)
+ // Alerting Availability Duration Job (create only, nothing actually scheduled here)
try {
schedulerBean.scheduleTriggeredJob(AlertAvailabilityDurationJob.class, false, null);
} catch (Exception e) {
@@ -647,7 +646,7 @@ public class StartupBean implements StartupLocal {
* immediately begin to send any persisted guaranteed messages that might already exist. This method must be called
* at a time when the server is ready to accept messages from agents because any guaranteed messages that are
* delivered might trigger the agents to send messages back to the server.
- *
+ *
* NOTE: we don't need to do this - so far, none of the messages the server sends to the agent are marked
* with "guaranteed delivery" (this is on purpose and a good thing) so we don't need to start all the agent clients
* in case they have persisted messages. Since the number of agents could be large this cache could be huge and
@@ -673,7 +672,7 @@ public class StartupBean implements StartupLocal {
* Starts the embedded agent, but only if the embedded agent is installed and it is enabled.
*
* @throws RuntimeException if the agent is installed and enabled but failed to start
- *
+ *
* @deprecated we don't have an embedded agent anymore, leaving this in case we resurrect it
*/
private void startEmbeddedAgent() throws RuntimeException {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
new file mode 100644
index 0000000..d89c04b
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
@@ -0,0 +1,209 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.rhq.enterprise.server.core.jaas;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
+
+import org.rhq.core.util.StringUtil;
+
+/**
+ * A login module that just delegates all work to a different security domain.<p/>
+ * When you use container managed security (CMS), EAP 6.1 requires the security domain being
+ * already present in standalone.xml
+ *
+ * With our setup we (re)-create the security domain of RHQUserSecurityDomain dynamically,
+ * which makes CMS fail on startup and also on re-create.
+ *
+ * The approach of just exchanging login modules does not work correctly either (principals
+ * keep being cached, server goes into need-reload state).
+ *
+ * So we now have a security domain for the CMS for the REST api that just delegates to the
+ * RHQUserSecuritDomain.
+ *
+ * <pre>
+ * <security-domain name="RHQRESTSecurityDomain" cache-type="default">
+ * <authentication>
+ * <login-module code="org.rhq.enterprise.server.core.jaas.DelegatingLoginModule" flag="required">
+ * <module-option name="delegateTo" value="RHQUserSecurityDomain"/>
+ * <module-option name="additionalRoles" value="rest-user"/>
+ * </login-module>
+ * </authentication>
+ * </security-domain>
+ *</pre>
+ *
+ * @author Heiko W. Rupp
+ */
+@SuppressWarnings("unused")
+public class DelegatingLoginModule extends UsernamePasswordLoginModule {
+
+ private static Log LOG = LogFactory.getLog("DelegatingLoginModule");
+
+ LoginContext loginContext;
+ private String[] usernamePassword;
+ private Principal identity;
+ private List<String> rolesList;
+ private boolean debugEnabled;
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+ Map<String, ?> options) {
+
+ debugEnabled = log.isDebugEnabled();
+
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ /* This is the login context (=security domain) we want to delegate to */
+ String delegateTo = (String) options.get("delegateTo");
+
+ /* Comma separated list of roles that should be set for the principal */
+ String additionalRoles = (String) options.get("roles");
+ rolesList = StringUtil.explode(additionalRoles, ",");
+
+ if (delegateTo ==null || delegateTo.isEmpty()) {
+ delegateTo = "other";
+ LOG.warn("module-option 'delegateTo' was not set. Defaults to 'other'.");
+ }
+
+ if (debugEnabled) {
+ log.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
+ }
+
+ // Now create the context for later use
+ try {
+ loginContext = new LoginContext(delegateTo, new DelegateCallbackHandler());
+ } catch (LoginException e) {
+ log.warn("Initialize failed : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Do the actual login work - we obtain the user/password passed in and then try to
+ * log into the delegated context. If this succeeds, we tell the super-module,
+ * so this can do further processing (especially running the #commit() method).
+ *
+ * @return True on success
+ * @throws LoginException If anything goes wrong
+ */
+ @Override
+ public boolean login() throws LoginException {
+ try {
+ // Get the username / password the user entred and save if for later use
+ usernamePassword = super.getUsernameAndPassword();
+
+ // Try to log in via the delegate
+ loginContext.login();
+
+ // Nix out the password
+ usernamePassword[1] = null;
+
+ // login was success, so we can continue
+ identity = createIdentity(usernamePassword[0]);
+ useFirstPass=true;
+
+ // This next flag is important. Without it the principal will not be
+ // propagated
+ loginOk = true;
+
+ if (debugEnabled) {
+ log.debug("Login ok for " + usernamePassword[0]);
+ }
+
+ return true;
+ } catch (Exception e) {
+ if (debugEnabled) {
+ LOG.debug("Login failed for : " + usernamePassword[0] + ": " + e.getMessage());
+ }
+ loginOk = false;
+ return false;
+ }
+ }
+
+
+ @Override
+ protected String getUsersPassword() throws LoginException {
+
+ // This is not used but abstract in super.
+ return null;
+ }
+
+ @Override
+ protected Principal getIdentity() {
+ return identity;
+ }
+
+
+ @Override
+ protected Group[] getRoleSets() throws LoginException {
+
+ SimpleGroup roles = new SimpleGroup("Roles");
+
+ for (String role : rolesList ) {
+ roles.addMember( new SimplePrincipal(role));
+ }
+ Group[] roleSets = { roles };
+ return roleSets;
+ }
+
+
+ /**
+ * Handle the callbacks from the other security domain that we delegate to
+ */
+ private class DelegateCallbackHandler implements CallbackHandler {
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ if (debugEnabled) {
+ LOG.debug("private handle callbacks");
+ }
+ for (Callback cb : callbacks) {
+ if (cb instanceof NameCallback) {
+ NameCallback nc = (NameCallback) cb;
+ nc.setName(usernamePassword[0]);
+ }
+ else if (cb instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) cb;
+ pc.setPassword(usernamePassword[1].toCharArray());
+ }
+ else {
+ throw new UnsupportedCallbackException(cb,"Callback " + cb + " not supported");
+ }
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
index 10fef1a..d12336e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
@@ -50,7 +50,7 @@ import org.rhq.enterprise.server.RHQConstants;
* this value is "SELECT password FROM principals WHERE principal=?"
*
* dsJndiName
- * JNDI name of the datasource to use. Default value is java:/HypericDS
+ * JNDI name of the datasource to use. Default value is java:/jboss/datasources/RHQDS
* </pre>
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
index 5640f3f..2b761f6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
@@ -38,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.crypto.CryptoUtil;
import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
import org.rhq.enterprise.server.RHQConstants;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
index e476eeb..6b7add6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.core.jaas;
@@ -42,8 +42,8 @@ import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
/**
- * A login module for authenticating against an LDAP directory server using JNDI, based on configuration properites LDAP
- * module options:
+ * A login module for authenticating against an LDAP directory server using JNDI, based on configuration properties.<br/
+ * LDAP module options:
*
* <pre>
* java.naming.factory.initial
@@ -72,7 +72,7 @@ import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
* BaseDN
* The base of the LDAP tree we are authenticating against. For example:
* o=Covalent Technologies,c=US. Multiple LDAP bases can be used by
- * seperating each DN by ';'
+ * separating each DN by ';'
*
* BindDN
* The BindDN to use if the LDAP server does not support anonymous searches.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
index 52cd33d..de3b836 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
@@ -464,7 +464,7 @@ public class SystemManagerBean implements SystemManagerLocal, SystemManagerRemot
}
} else if (property == SystemSetting.AGENT_MAX_QUIET_TIME_ALLOWED) {
long time = Long.parseLong(value);
- // minimum should be 3 * the agent ping interval, any less risks unwanted backfilling
+ // minimum should be 3 * the agent ping interval, any less risks unwanted backfilling
if (time < 1000L * 60 * 3) {
throw new InvalidSystemConfigurationException("Agent Max Quiet Time Allowed must be at least 3 minutes");
}
commit b9ce1ee3cc01fd2bf5614f10e164a1f4cebfe42c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 16 13:11:14 2013 -0400
BZ 957282 957288 add bundle target of "Base Directory"
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 4a26d19..ad22370 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1337,6 +1337,10 @@
<value-context>pluginConfiguration</value-context>
<value-name>homeDir</value-name>
</destination-base-dir>
+ <destination-base-dir name="Base Directory" description="The base directory for server content, such as '[install-dir]/standalone' (i.e. the value found in the 'Base Directory' connection property)">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>baseDir</value-name>
+ </destination-base-dir>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
<value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
commit f9052819e3da19359081274d62eb6b0f75dd63e2
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Thu May 16 14:28:01 2013 +0200
Bug 962787 - GloballyUncaughtException when changing a parameter in Connection Settings tab of a compatible group after a plugin update
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
index 8b5be2c..b3ccb10 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010-2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.components.configuration;
@@ -71,10 +70,10 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.PopupWindow;
import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedToolStrip;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
/**
* A SmartGWT widget for editing a group of RHQ {@link Configuration}s that conform to the same
@@ -638,28 +637,20 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
}
private Property getProperty(Configuration configuration, Property referenceProperty, Integer index) {
- LinkedList<Property> propertyHierarchy = new LinkedList<Property>();
- Property currentProperty = referenceProperty;
- propertyHierarchy.add(currentProperty);
- do {
- if (currentProperty.getParentMap() != null) {
- currentProperty = currentProperty.getParentMap();
- } else if (currentProperty.getParentList() != null) {
- currentProperty = currentProperty.getParentList();
- } else if (currentProperty.getConfiguration() == null) {
- throw new IllegalStateException(currentProperty + " has no parent.");
- }
- propertyHierarchy.addFirst(currentProperty);
- } while (currentProperty.getConfiguration() == null);
-
- Property property = configuration.get(propertyHierarchy.get(0).getName());
- for (int i = 1, propertyHierarchySize = propertyHierarchy.size(); i < propertyHierarchySize; i++) {
- String childPropertyName = propertyHierarchy.get(i).getName();
+ List<Property> referenceHierarchy = getParentFirstPropertiesHierarchy(referenceProperty);
+ // Add referenceProperty to the configuration, creating parents if necessary
+ Property property = configuration.get(referenceHierarchy.get(0).getName());
+ if (property == null) {
+ property = createPropertyByExample(referenceHierarchy.get(0));
+ configuration.put(property);
+ }
+ for (int i = 1; i < referenceHierarchy.size(); i++) {
+ String childPropertyName = referenceHierarchy.get(i).getName();
if (property instanceof PropertyMap) {
PropertyMap propertyMap = (PropertyMap) property;
property = propertyMap.get(childPropertyName);
if (property == null) {
- property = new PropertySimple(childPropertyName, null);
+ property = createPropertyByExample(referenceHierarchy.get(i));
propertyMap.put(property);
}
} else if (property instanceof PropertyList) {
@@ -667,7 +658,7 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
if (index < propertyList.getList().size()) {
property = propertyList.getList().get(index);
} else {
- property = new PropertySimple(childPropertyName, null);
+ property = createPropertyByExample(referenceHierarchy.get(i));
propertyList.add(property);
}
}
@@ -676,6 +667,35 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
return property;
}
+ private List<Property> getParentFirstPropertiesHierarchy(Property bottomProperty) {
+ LinkedList<Property> propertyHierarchy = new LinkedList<Property>();
+ for (Property currentProperty = bottomProperty; currentProperty != null; ) {
+ propertyHierarchy.addFirst(currentProperty);
+ if (currentProperty.getParentMap() != null) {
+ currentProperty = currentProperty.getParentMap();
+ } else if (currentProperty.getParentList() != null) {
+ currentProperty = currentProperty.getParentList();
+ } else if (currentProperty.getConfiguration() == null) {
+ throw new IllegalStateException(currentProperty + " has no parent.");
+ } else {
+ currentProperty = null;
+ }
+ }
+ return new ArrayList<Property>(propertyHierarchy);
+ }
+
+ private <T extends Property> T createPropertyByExample(T example) {
+ T property = null;
+ if (example instanceof PropertyMap) {
+ property = (T) new PropertyMap(example.getName());
+ } else if (example instanceof PropertyList) {
+ property = (T) new PropertyList(example.getName());
+ } else {
+ property = (T) new PropertySimple(example.getName(), null);
+ }
+ return property;
+ }
+
private boolean isAggregateProperty(PropertySimple propertySimple) {
return (getConfiguration(propertySimple) == getConfiguration());
}
commit ac38cd855156fd93958f82b40ca5cf75a3f6593d
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 17:13:18 2013 -0400
BZ 951382 - for upgrades, let's use the agent preferences upgrade feature
to set the cert store locations explicitly and copy the files
from data/ to conf/ which is the new default location. Note that if
customers already explicitly set the locations of their cert stores,
we leave those intact and continue using what the customer asked to use.
We only do anything IF those settings weren't set and thus defaults
were taking effect.
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
index 4fe7df9..3f9a89b 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
@@ -58,7 +58,7 @@ public interface AgentConfigurationConstants {
/**
* This is the current schema version that our agent configuration knows about.
*/
- int CURRENT_CONFIG_SCHEMA_VERSION = 6;
+ int CURRENT_CONFIG_SCHEMA_VERSION = 7;
/**
* Flag to indicate if the agent's configuration has been setup.
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
index 6c0a2ce..27e68f9 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
@@ -18,10 +18,17 @@
*/
package org.rhq.enterprise.agent;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;
+import mazz.i18n.Logger;
+
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.enterprise.agent.i18n.AgentI18NFactory;
+import org.rhq.enterprise.agent.i18n.AgentI18NResourceKeys;
+import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
import org.rhq.enterprise.communications.util.prefs.PreferencesUpgrade;
import org.rhq.enterprise.communications.util.prefs.PreferencesUpgradeStep;
@@ -31,6 +38,8 @@ import org.rhq.enterprise.communications.util.prefs.PreferencesUpgradeStep;
* @author John Mazzitelli
*/
public class AgentConfigurationUpgrade extends PreferencesUpgrade {
+ private static final Logger LOG = AgentI18NFactory.getLogger(AgentConfigurationUpgrade.class);
+
/**
* This is a convenience method that upgrades the given agent preferences to the latest configuration schema
* version.
@@ -58,7 +67,8 @@ public class AgentConfigurationUpgrade extends PreferencesUpgrade {
list.add(new Step2to3()); // goes from v2 to v3
list.add(new Step3to4()); // goes from v3 to v4
list.add(new Step4to5()); // goes from v4 to v5
- list.add(new Step5to6());
+ list.add(new Step5to6()); // goes from v5 to v6
+ list.add(new Step6to7()); // goes from v6 to v7
return list;
}
@@ -139,4 +149,55 @@ public class AgentConfigurationUpgrade extends PreferencesUpgrade {
preferences.put(AgentConfigurationConstants.SERVER_ALIAS, "rhqserver");
}
}
+
+ static class Step6to7 extends PreferencesUpgradeStep {
+ public int getSupportedConfigurationSchemaVersion() {
+ return 7;
+ }
+
+ public void upgrade(Preferences preferences) {
+ // This new schema version indicates when we changed the default locations for our keystore/truststore
+ // files. Before if these comm settings weren't set, we assumed a default of "data" directory, but now
+ // we assume a default of "conf" directory (if that directory exists). See BZ 951382.
+ File confDir = new File("conf");
+ if (!confDir.exists()) {
+ return; // conf/ doesn't exist (perhaps we are running in a test?) - do nothing and just fallback to the standard defaults
+ }
+
+ String dataDir = preferences.get(AgentConfigurationConstants.DATA_DIRECTORY,
+ AgentConfigurationConstants.DEFAULT_DATA_DIRECTORY);
+
+ String prefNamesFileNames[][] = {
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_KEYSTORE_FILE_NAME },
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE_NAME } };
+
+ for (String[] prefNameFileName : prefNamesFileNames) {
+ String value = preferences.get(prefNameFileName[0], null);
+ if (value == null) {
+ File newFile = new File(confDir, prefNameFileName[1]);
+ value = newFile.getAbsolutePath();
+ preferences.put(prefNameFileName[0], value);
+
+ File oldFile = new File(dataDir, prefNameFileName[1]);
+ if (oldFile.exists()) {
+ try {
+ FileUtil.copyFile(oldFile, newFile);
+ oldFile.delete();
+ } catch (Exception e) {
+ LOG.error(e, AgentI18NResourceKeys.CERT_FILE_COPY_ERROR, oldFile, newFile);
+ }
+ }
+ LOG.debug(AgentI18NResourceKeys.CERT_FILE_LOCATION, prefNameFileName[0], value);
+ }
+ }
+
+ return;
+ }
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
index 21a39a9..16c110a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
@@ -28,6 +28,9 @@ import mazz.i18n.annotation.I18NResourceBundle;
*/
@I18NResourceBundle(baseName = "agent-messages", defaultLocale = "en")
public interface AgentI18NResourceKeys {
+ @I18NMessage("Failed to move old cert file [{0}] to new default location [{1}] - agent communication may fail!")
+ String CERT_FILE_COPY_ERROR = "AgentConfiguration.cert-file-copy-error";
+
@I18NMessage("Explicitly setting file location [{0}] to [{1}]")
String CERT_FILE_LOCATION = "AgentConfiguration.cert-file-location";
commit 3034e3c906a352723834aa4adce41355d7310bce
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 12:30:18 2013 -0400
provide another sample plugin that demonstrates using the embedded plugin extension model
diff --git a/.classpath b/.classpath
index aa4c157..53037dd 100644
--- a/.classpath
+++ b/.classpath
@@ -189,6 +189,8 @@
<classpathentry kind="src" path="modules/integration-tests/jndi-access/jndi-access-test/src/test/resources"/>
<classpathentry kind="src" path="modules/integration-tests/mod_cluster-plugin-test/src/test/java"/>
<classpathentry kind="src" path="etc/samples/skeleton-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/embedded-ext-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/skinny-platform/src/main/java"/>
<classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/samples/simplereport-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
diff --git a/etc/samples/embedded-ext-plugin/pom.xml b/etc/samples/embedded-ext-plugin/pom.xml
new file mode 100644
index 0000000..9427d71
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq.sample.embeddedextplugin</groupId>
+ <artifactId>embedded-ext-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>Embedded Ext RHQ Plugin</name>
+ <description>A sample plugin showing plugin embedded extention</description>
+
+ <properties>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-native-system</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq.sample.skeletonplugin</groupId>
+ <artifactId>skeleton-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Maven Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
+
diff --git a/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java b/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java
new file mode 100644
index 0000000..6e823c3
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java
@@ -0,0 +1,58 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.embeddedextplugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.sample.skeletonplugin.SamplePluginDiscoveryComponent;
+
+/**
+ * This is a discovery class for the embedded extension resource type.
+ */
+public class EmbeddedExtensionDiscoveryComponent extends SamplePluginDiscoveryComponent {
+ private final Log log = LogFactory.getLog(EmbeddedExtensionDiscoveryComponent.class);
+
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ log.info("Discovering embedded extension resources");
+ Set<DiscoveredResourceDetails> discoveredResources = super.discoverResources(context); // call the parent discovery code
+ Set<DiscoveredResourceDetails> extendedResources = new HashSet<DiscoveredResourceDetails>();
+
+ int i = -1;
+ for (DiscoveredResourceDetails discoveredResource : discoveredResources) {
+ String key = "Embedded Extension Resource Key" + (++i > 0 ? String.valueOf(i) : "");
+ String name = "Embedded Extension Resource";
+ String description = "This describes the Embedded Extension Resource";
+
+ discoveredResource.setResourceKey(key);
+ discoveredResource.setResourceName(name);
+ discoveredResource.setResourceDescription(description);
+
+ extendedResources.add(discoveredResource);
+ }
+
+ return extendedResources;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..16dbb7b
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="EmbeddedExtPlugin"
+ displayName="Embedded Extension Plugin"
+ version="1.0"
+ package="org.rhq.sample.embeddedextplugin"
+ description="Defines a resource type that uses the embedded extension model."
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="SkeletonPlugin" useClasses="true" />
+
+ <server name="Embedded Extension Resource"
+ discovery="EmbeddedExtensionDiscoveryComponent"
+ class="org.rhq.sample.skeletonplugin.SamplePluginServerComponent"
+ description="A resource that embeds the skeleton plugin type"
+ sourcePlugin="SkeletonPlugin"
+ sourceType="Sample Plugin Server">
+ </server>
+
+</plugin>
commit 8cbe5ffb7379c26403f9083bc7b0642f490ff9eb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 11:47:55 2013 -0400
provide some additions to the sample skeleton plugin
add a new "skinny platform" plugin sample, used mainly for testing - provides a minimal plugin you can use to run an agent with
diff --git a/etc/samples/skeleton-plugin/pom.xml b/etc/samples/skeleton-plugin/pom.xml
index 56c816e..998bb47 100644
--- a/etc/samples/skeleton-plugin/pom.xml
+++ b/etc/samples/skeleton-plugin/pom.xml
@@ -15,7 +15,7 @@
<description>A template for building a custom RHQ Agent plugin</description>
<properties>
- <rhq.version>4.3.0</rhq.version>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
</properties>
<dependencies>
@@ -42,30 +42,6 @@
<scope>provided</scope> <!-- provided by the agent/plugin-container -->
</dependency>
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>javax.persistence</groupId>
- <artifactId>persistence-api</artifactId>
- <version>1.0</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>hibernate-annotations</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.2.1.GA</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>2.1</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
<!--
Uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog
All three are provided to your plugin by the agent/plugin-container.
@@ -143,79 +119,6 @@
</plugins>
</build>
- <profiles>
- <profile>
- <id>dev</id>
- <properties>
- <!-- define the location of your RHQ root directory - typically rhq.rootDir is overridden in Maven's settings.xml -->
- <rhq.rootDir>/rhq/trunk</rhq.rootDir>
- <rhq.defaultDevContainerPath>dev-container</rhq.defaultDevContainerPath>
- <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
- <rhq.deploymentDir>${rhq.containerDir}/${rhq.agentPluginDir}</rhq.deploymentDir>
- </properties>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>deploy</id>
- <phase>compile</phase>
- <configuration>
- <target>
- <mkdir dir="${rhq.deploymentDir}" />
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Updating ${deployment.file}...</echo>
- <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- <execution>
- <id>deploy-jar-meta-inf</id>
- <phase>package</phase>
- <configuration>
- <target>
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
- <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}">
- <patternset>
- <include name="META-INF/**" />
- </patternset>
- </unjar>
- <jar destfile="${deployment.file}"
- manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
- update="true">
- </jar>
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- <execution>
- <id>undeploy</id>
- <phase>clean</phase>
- <configuration>
- <target>
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Deleting ${deployment.file}...</echo>
- <delete file="${deployment.file}" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-
<repositories>
<repository>
<id>jboss-public-repository-group</id>
diff --git a/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java
new file mode 100644
index 0000000..b8a81ab
--- /dev/null
+++ b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java
@@ -0,0 +1,47 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.skeletonplugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class SamplePluginChildDiscoveryComponent implements ResourceDiscoveryComponent {
+ private final Log log = LogFactory.getLog(SamplePluginChildDiscoveryComponent.class);
+
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ log.info("Discovering my custom plugin's child resources");
+ HashSet<DiscoveredResourceDetails> set = new HashSet<DiscoveredResourceDetails>();
+ String key = "My Child Resource Key";
+ String name = "My Child Resource";
+ String version = "1.0";
+ String description = "This describes My Child Resource";
+ DiscoveredResourceDetails resource = new DiscoveredResourceDetails(context.getResourceType(), key, name,
+ version, description, null, null);
+ set.add(resource);
+ return set;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java
new file mode 100644
index 0000000..a3303e7
--- /dev/null
+++ b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.skeletonplugin;
+
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+
+public class SamplePluginChildServiceComponent implements ResourceComponent, MeasurementFacet {
+ private final Log log = LogFactory.getLog(SamplePluginChildServiceComponent.class);
+
+ public void start(ResourceContext context) {
+ log.info("Starting child resource [" + context.getResourceKey() + "]");
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) {
+ for (MeasurementScheduleRequest request : requests) {
+ String name = request.getName();
+ try {
+ Number value = new Integer(2); // dummy measurement value
+ report.addData(new MeasurementDataNumeric(request, value.doubleValue()));
+ } catch (Exception e) {
+ log.error("Failed to obtain measurement [" + name + "]. Cause: " + e);
+ }
+ }
+
+ return;
+ }
+}
diff --git a/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
index 4f4966d..cde11c5 100644
--- a/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
+++ b/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
@@ -15,6 +15,7 @@
<plugin name="SkeletonPlugin"
displayName="Skeleton Plugin"
version="1.0"
+ description="This is a skeleton plugin that can be used to start your own custom plugin."
package="org.rhq.sample.skeletonplugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xmlns:rhq-plugin"
@@ -110,5 +111,24 @@
<resource-configuration>
<c:simple-property name="port" type="integer" displayName="Port on which to listen" />
</resource-configuration>
+
+ <!--
+ CHANGE: You can optionally define children resource types to represent internal services within your
+ server resource type.
+ -->
+ <service name="Sample Plugin Child Service"
+ discovery="SamplePluginChildDiscoveryComponent"
+ class="SamplePluginChildServiceComponent"
+ description="This is a child service found under the main, top-level server resource type.">
+
+ <plugin-configuration>
+ <c:simple-property name="SamplePluginChildProperty" displayName="Sample Plugin Child Property" default="Value" />
+ </plugin-configuration>
+
+ <metric property="ChildMeasurementName"
+ displayName="The Child Measurement Name"
+ description="Describes what this child measurement is actually telling you" />
+
+ </service>
</server>
</plugin>
diff --git a/etc/samples/skinny-platform/pom.xml b/etc/samples/skinny-platform/pom.xml
new file mode 100644
index 0000000..994462f
--- /dev/null
+++ b/etc/samples/skinny-platform/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq.sample.skinnyplugin</groupId>
+ <artifactId>rhq-skinny-platform-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>RHQ Skinny Platform Plugin</name>
+ <description> A very slimmed down platform plugin, used for testing.</description>
+
+ <properties>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-native-system</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Maven Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
diff --git a/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java
new file mode 100644
index 0000000..0c123b1
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.plugins.skinnyplatform;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+
+public class PlatformComponent implements ResourceComponent<PlatformComponent> {
+ public void start(ResourceContext<PlatformComponent> context) {
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java
new file mode 100644
index 0000000..b53b1c3
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.plugins.skinnyplatform;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+@SuppressWarnings("rawtypes")
+public class PlatformDiscoveryComponent implements ResourceDiscoveryComponent {
+
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ String pcName = context.getPluginContainerName();
+ String hostname = getHostname();
+
+ String name = (pcName != null ? pcName : hostname);
+ String key = "skinny:" + name;
+ String description = context.getResourceType().getDescription();
+ String version = "1.0";
+
+ DiscoveredResourceDetails discoveredResource = new DiscoveredResourceDetails(context.getResourceType(), key,
+ name, version, description, null, null);
+
+ HashSet<DiscoveredResourceDetails> results = new HashSet<DiscoveredResourceDetails>();
+ results.add(discoveredResource);
+ return results;
+ }
+
+ private String getHostname() {
+ String name;
+ try {
+ name = InetAddress.getLocalHost().getHostAddress();
+ } catch (Exception e) {
+ name = null;
+ }
+
+ // we fought the good fight but we just can't get this machine's hostname, give a generic platform name
+ if (name == null) {
+ name = "Unnamed Skinny Platform";
+ }
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..fd50a2a
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="Skinny Platform"
+ displayName="Skinny Platform"
+ version="1.0"
+ package="org.rhq.plugins.skinnyplatform"
+ description="Provides a slimmed down, single platform resource type - used mainly for testing."
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="Generic Platform"
+ class="PlatformComponent"
+ discovery="PlatformDiscoveryComponent"
+ description="A generic platform with very little functionality.">
+ </platform>
+
+</plugin>
commit 98cb0afd7a2bcfcb8f74f3d8182fb9798edd2b49
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue May 14 10:38:22 2013 -0700
[BZ 960646] - Trivial: strengthen opacity on new Availability chart.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 5ef57a8..a301e73 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -243,7 +243,7 @@ public class AvailabilityOverUnderGraphType {
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
})
- .attr("opacity", ".3")
+ .attr("opacity", ".75")
.attr("fill", function (d) {
return calcBarFill(d);
});
@@ -265,7 +265,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "12px")
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-weight", "bold")
- .attr("fill", "#003168")
+ .attr("fill", "#545454")
.text(availChartContext.chartTitle);
svg.append("text")
commit cf37517727392d04d8ab11182fd94474571462d8
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue May 14 09:20:26 2013 -0700
[BZ 960646] - UXD updates to new Availability Charts.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index fbce610..5ef57a8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -169,9 +169,9 @@ public class AvailabilityOverUnderGraphType {
.orient("bottom"),
calcBarY = function (d) {
- var ABOVE = -10,
+ var ABOVE = -6,
BELOW = 0,
- STRADDLE = -5,
+ STRADDLE = -3,
offset;
if (d.availType === 'DOWN') {
@@ -198,19 +198,19 @@ public class AvailabilityOverUnderGraphType {
calcBarFill = function (d) {
if (d.availType === 'DOWN') {
- return "#FF1919"; // red
+ return "#c5888b"; // red
}
else if (d.availType === 'DISABLED') {
return "url(#diagonalHatchFill)"; // grey diagonal hatches
}
else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
+ return "#d8d8d8"; // gray
}
else if (d.availType === 'UP') {
- return "#198C19"; // green
+ return "#8cbe89"; // green
}
else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
+ return "#e1b36b"; // orange
}
else if (d.availType === 'EMPTY') {
return "#CCC"; // gray
@@ -238,12 +238,12 @@ public class AvailabilityOverUnderGraphType {
return calcBarY(d);
})
.attr("height", function (d) {
- return 10;
+ return 6;
})
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
})
- .attr("opacity", ".9")
+ .attr("opacity", ".3")
.attr("fill", function (d) {
return calcBarFill(d);
});
@@ -251,7 +251,7 @@ public class AvailabilityOverUnderGraphType {
// create x-axis
svg.append("g")
.attr("class", "x axis")
- .attr("fill", "#50505a")
+ .attr("fill", "#b0b0b0")
.attr("stroke-width", "0.5")
.attr("transform", "translate(0," + height + ")")
.attr("letter-spacing", "3")
@@ -274,7 +274,7 @@ public class AvailabilityOverUnderGraphType {
.attr("y", 28)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartUpLabel);
@@ -284,7 +284,7 @@ public class AvailabilityOverUnderGraphType {
.attr("y", 39)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartDownLabel);
commit af1fdd5d865ab295969f80949b36c3c38c70ccef
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue May 14 13:21:44 2013 +0200
Fixing a typo in a sample CLI script.
diff --git a/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js b/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
index 9739cb1..a965edf 100644
--- a/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
+++ b/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
@@ -146,7 +146,7 @@ function _restartFunction(asResourceType) {
(asResourceType.name == "JBossAS7 Standalone Server" ||
asResourceType.name == "Managed Server")) {
- return _restartAS7);
+ return _restartAS7;
} else {
throw "The resource group the destination targets doesn't seem to be a JBoss AS server group.";
}
commit 9a3b4d105099320c6c6794ff04e12285c5399667
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu May 9 15:15:02 2013 +0200
[BZ 620603] - Re-enabling the limited JOIN FETCH reporting
with a more informative message, asking the users to co-operate in
identifying the individual uses of the problematic JOIN FETCH queries that
we potentially missed.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
index f826e41..8eb4b3e 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -15,8 +15,8 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
/**
- * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries.
- * It will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
+ * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries. It
+ * will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
* that Hibernate itself offers that merely dumps a message about in-memory filtering of results resulting from the use
* of JOIN FETCH together with limits.
*
@@ -24,7 +24,7 @@ import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
*/
public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
- private static Log LOG = LogFactory.getLog("JOIN FETCH Perf");
+ private static Log LOG = LogFactory.getLog("JOIN FETCH Performance");
public JoinFetchReportingQueryTranslator(String queryIdentifier, String query, Map enabledFilters,
SessionFactoryImplementor factory) {
@@ -49,11 +49,14 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
}
}
- public void report() {
+ public void report(String method) {
if (time != 0) {
time = System.currentTimeMillis() - time;
- LOG.warn("List with first: " + firstRow + ", max: " + maxRows + " took " + time + "ms:\n" +
- getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" + extractRHQCalls(new Exception()));
+ LOG.warn("Encountered a query with potentially bad performance. While this is not a bug and the " +
+ "system functions as designed, please report this to RHQ community so that we can reimplement our" +
+ " code to work better.\n" + method + "() with first: " + firstRow + ", max: " + maxRows + " took "
+ + time + "ms:\n" + getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" +
+ extractRHQCalls(new Exception()));
}
}
@@ -80,7 +83,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
List ret = super.list(session, queryParameters);
- usage.report();
+ usage.report("list");
return ret;
}
@@ -91,7 +94,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
Iterator ret = super.iterate(queryParameters, session);
- usage.report();
+ usage.report("iterate");
return ret;
}
@@ -103,7 +106,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
ScrollableResults ret = super.scroll(queryParameters, session);
- usage.report();
+ usage.report("scroll");
return ret;
}
diff --git a/modules/core/domain/src/main/resources/META-INF/persistence.xml b/modules/core/domain/src/main/resources/META-INF/persistence.xml
index a15fd2e..1bbd8c2 100644
--- a/modules/core/domain/src/main/resources/META-INF/persistence.xml
+++ b/modules/core/domain/src/main/resources/META-INF/persistence.xml
@@ -21,9 +21,7 @@
<!--<property name="com.intellij.javaee.persistence.datasource" value="rhq-oracle" />-->
<property name="com.intellij.javaee.persistence.datasource" value="rhq-postgres" />
- <!-- Used only for debugging the usages of JOIN FETCHes
<property name="hibernate.query.factory_class" value="org.rhq.core.domain.util.JoinFetchReportingQueryTranslatorFactory" />
- -->
<!-- This value doesn't have any theoretical grounds and is purely based on experiments. Value of 32 gives
the best compromise between the quick load of queries with low and high limits (i.e. page size in tens vs.
commit db62629626fdd9049cf89cfa58dc5b14b2a98ea9
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu May 9 13:11:50 2013 +0200
[BZ 620603] - Don't use JOIN FETCH in criteria queries with limits.
Use the "manual" initialization of lazy fields and collections in
that case instead.
Together with the "hibernate.default_batch_fetch_size" setting in the
hibernate configuration, this offers superior performance over the join
fetch and in memory filtering of results when the number of rows in the
"primary" tables times the number of rows in the "join-fetched" table
is non-trivial.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
new file mode 100644
index 0000000..f826e41
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -0,0 +1,110 @@
+package org.rhq.core.domain.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.ScrollableResults;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.event.spi.EventSource;
+import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
+
+/**
+ * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries.
+ * It will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
+ * that Hibernate itself offers that merely dumps a message about in-memory filtering of results resulting from the use
+ * of JOIN FETCH together with limits.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
+
+ private static Log LOG = LogFactory.getLog("JOIN FETCH Perf");
+
+ public JoinFetchReportingQueryTranslator(String queryIdentifier, String query, Map enabledFilters,
+ SessionFactoryImplementor factory) {
+ super(queryIdentifier, query, enabledFilters, factory);
+ }
+
+ private class JoinFetchUsage {
+ private long time;
+ private Integer firstRow;
+ private Integer maxRows;
+
+ public JoinFetchUsage(QueryParameters queryParameters) {
+ boolean collect = containsCollectionFetches();
+ boolean hasLimit =
+ queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
+
+ if (collect && hasLimit) {
+ firstRow = queryParameters.getRowSelection().getFirstRow();
+ maxRows = queryParameters.getRowSelection().getMaxRows();
+
+ time = System.currentTimeMillis();
+ }
+ }
+
+ public void report() {
+ if (time != 0) {
+ time = System.currentTimeMillis() - time;
+ LOG.warn("List with first: " + firstRow + ", max: " + maxRows + " took " + time + "ms:\n" +
+ getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" + extractRHQCalls(new Exception()));
+ }
+ }
+
+ private String extractRHQCalls(Throwable t) {
+ StringBuilder bld = new StringBuilder();
+
+ StackTraceElement[] elements = t.getStackTrace();
+
+ //skip the report() and list() calls, hence 2
+ for (int i = 2; i < elements.length; ++i) {
+ StackTraceElement e = elements[i];
+ if (e.getClassName().startsWith("org.rhq")) {
+ bld.append("\n").append(e.toString());
+ }
+ }
+
+ return bld.toString();
+ }
+ }
+
+ @Override
+ public List list(SessionImplementor session, QueryParameters queryParameters) throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ List ret = super.list(session, queryParameters);
+
+ usage.report();
+
+ return ret;
+ }
+
+ @Override
+ public Iterator iterate(QueryParameters queryParameters, EventSource session) throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ Iterator ret = super.iterate(queryParameters, session);
+
+ usage.report();
+
+ return ret;
+ }
+
+ @Override
+ public ScrollableResults scroll(QueryParameters queryParameters, SessionImplementor session)
+ throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ ScrollableResults ret = super.scroll(queryParameters, session);
+
+ usage.report();
+
+ return ret;
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
new file mode 100644
index 0000000..71e1bf2
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
@@ -0,0 +1,27 @@
+package org.rhq.core.domain.util;
+
+import java.util.Map;
+
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.hql.spi.FilterTranslator;
+import org.hibernate.hql.spi.QueryTranslator;
+import org.hibernate.hql.spi.QueryTranslatorFactory;
+
+/**
+ * A query translator factory to be set in the hibernate configuration to report the usage of JOIN FETCH with limit.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslatorFactory implements QueryTranslatorFactory {
+ @Override
+ public QueryTranslator createQueryTranslator(String queryIdentifier, String queryString, Map filters,
+ SessionFactoryImplementor factory) {
+ return new JoinFetchReportingQueryTranslator(queryIdentifier, queryString, filters, factory);
+ }
+
+ @Override
+ public FilterTranslator createFilterTranslator(String queryIdentifier, String queryString, Map filters,
+ SessionFactoryImplementor factory) {
+ return new JoinFetchReportingQueryTranslator(queryIdentifier, queryString, filters, factory);
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
index 6963141..f87a814 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
@@ -276,6 +276,10 @@ public class PageControl implements Serializable, Cloneable {
orderingFields = new LinkedList<OrderingField>();
}
+ public boolean isUnlimited() {
+ return getPageNumber() == 0 && getPageSize() == SIZE_UNLIMITED;
+ }
+
// TODO (ips, 10/12/11): Incorporate firstRecord field into equals() and hashCode().
@Override
@@ -334,4 +338,4 @@ public class PageControl implements Serializable, Cloneable {
return new PageControl(pageNumber, pageSize, getOrderingFieldsAsArray());
}
-}
\ No newline at end of file
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
index ce7ab20..af5842a 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
@@ -30,6 +30,11 @@ public class UnlimitedPageControl extends PageControl {
}
@Override
+ public boolean isUnlimited() {
+ return true;
+ }
+
+ @Override
public void reset() {
getOrderingFields().clear();
}
diff --git a/modules/core/domain/src/main/resources/META-INF/persistence.xml b/modules/core/domain/src/main/resources/META-INF/persistence.xml
index 8e28c68..a15fd2e 100644
--- a/modules/core/domain/src/main/resources/META-INF/persistence.xml
+++ b/modules/core/domain/src/main/resources/META-INF/persistence.xml
@@ -20,6 +20,16 @@
<!--<property name="com.intellij.javaee.persistence.datasource" value="rhq-oracle" />-->
<property name="com.intellij.javaee.persistence.datasource" value="rhq-postgres" />
+
+ <!-- Used only for debugging the usages of JOIN FETCHes
+ <property name="hibernate.query.factory_class" value="org.rhq.core.domain.util.JoinFetchReportingQueryTranslatorFactory" />
+ -->
+
+ <!-- This value doesn't have any theoretical grounds and is purely based on experiments. Value of 32 gives
+ the best compromise between the quick load of queries with low and high limits (i.e. page size in tens vs.
+ thousands) in an inventory with 30 agents and >20000 resources. -->
+ <property name="hibernate.default_batch_fetch_size" value="32"/>
+
</properties>
</persistence-unit>
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
index 9066916..afa622f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
@@ -40,10 +40,11 @@
<!-- These classes are overriden for GWT because their original form doesn't gwt-compile. -->
<exclude name="**/ObfuscatedPropertySimple.*"/>
+ <exclude name="**/JoinFetchReporting*.*" />
</source>
<!--<generate-with class="org.rhq.core.rebind.RecordBuilderGenerator">
<when-type-assignable class="org.rhq.core.domain.util.Recordizable"/>
</generate-with>-->
-</module>
\ No newline at end of file
+</module>
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
new file mode 100644
index 0000000..e92696e
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -0,0 +1,9 @@
+package org.rhq.core.domain.util;
+
+/**
+ * GWT friendly impl of this beast.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslator {
+}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
new file mode 100644
index 0000000..9bd8512
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
@@ -0,0 +1,7 @@
+package org.rhq.core.domain.util;
+
+/**
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslatorFactory {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index 8f0d2cc..d7cc470 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -308,7 +308,11 @@ public final class CriteriaQueryGenerator {
public String getQueryString(boolean countQuery) {
StringBuilder results = new StringBuilder();
+
+ PageControl pc = getPageControl(criteria);
+
results.append("SELECT ");
+
if (countQuery) {
if (groupByClause == null) { // non-grouped method
// use count(*) instead of count(alias) due to https://bugzilla.redhat.com/show_bug.cgi?id=699842
@@ -325,7 +329,9 @@ public final class CriteriaQueryGenerator {
results.append(projection).append(NL);
}
}
+
results.append("FROM ").append(className).append(' ').append(alias).append(NL);
+
if (countQuery == false) {
/*
* don't fetch in the count query to avoid: "query specified join fetching,
@@ -336,19 +342,28 @@ public final class CriteriaQueryGenerator {
addPersistentBag(fetchField);
} else {
if (this.projection == null) {
- /*
+ /*
* if not altering the projection, join fetching can be using
* to retrieve the associated instance in the same SELECT
+ *
+ * We further avoid a JOIN FETCH when executing queries with limits.
+ * Such execution has performance problems that we solve by initializing the fields
+ * "manually" in the CriteriaQueryRunner and by defining a default batch fetch size in the
+ * persistence.xml.
*/
- results.append("LEFT JOIN FETCH ").append(alias).append('.').append(fetchField).append(NL);
+ if (pc.isUnlimited()) {
+ results.append("LEFT JOIN FETCH ").append(alias).append('.').append(fetchField).append(NL);
+ } else {
+ addJoinFetch(fetchField);
+ }
} else {
- /*
+ /*
* if the projection is altered (perhaps converting it into a constructor query), then all
* fields specified in the fetch must be in the explicit return list. this is not possible
* today with constructor queries, so any altered projection will implicitly disable fetching.
* instead, we'll record which fields need to be explicitly fetched after the primary query
* returns the bulk of the data, and use a similar methodology at the SLSB layer to eagerly
- * load those before returning the PageList back to the caller.
+ * load those before returning the PageList back to the caller.
*/
addJoinFetch(fetchField);
}
@@ -357,7 +372,6 @@ public final class CriteriaQueryGenerator {
}
// figure out the 'LEFT JOIN's needed for 'ORDER BY' tokens
- PageControl pc = getPageControl(criteria);
List<String> orderingFieldRequiredJoins = new ArrayList<String>();
List<String> orderingFieldTokens = new ArrayList<String>();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
index d2a28d5..a788fb0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
@@ -25,6 +25,7 @@ package org.rhq.enterprise.server.util;
import java.lang.reflect.Field;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
@@ -46,7 +47,7 @@ public class CriteriaQueryRunner<T> {
private Criteria criteria;
private CriteriaQueryGenerator queryGenerator;
private EntityManager entityManager;
- private boolean automaticFetching;;
+ private boolean automaticFetching;
public CriteriaQueryRunner(Criteria criteria, CriteriaQueryGenerator queryGenerator, EntityManager entityManager) {
this(criteria, queryGenerator, entityManager, true);
@@ -61,7 +62,7 @@ public class CriteriaQueryRunner<T> {
}
public PageList<T> execute() {
- PageList<T> results = null;
+ PageList<T> results;
PageControl pageControl = CriteriaQueryGenerator.getPageControl(criteria);
Restriction criteriaRestriction = criteria.getRestriction();
@@ -109,7 +110,7 @@ public class CriteriaQueryRunner<T> {
initPersistentBags(entity);
}
}
- if (queryGenerator.isProjectionAltered() && !queryGenerator.getJoinFetchFields().isEmpty()) {
+ if (!queryGenerator.getJoinFetchFields().isEmpty()) {
for (T entity : results) {
initJoinFetchFields(entity);
}
@@ -148,7 +149,15 @@ public class CriteriaQueryRunner<T> {
private void initialize(Object entity, Field field) {
try {
field.setAccessible(true);
- Hibernate.initialize(field.get(entity));
+
+ Object instance = field.get(entity);
+
+ Hibernate.initialize(instance);
+
+ if (instance instanceof Iterable) {
+ Iterator<?> it = ((Iterable<?>)instance).iterator();
+ while(it.hasNext()) it.next();
+ }
} catch (Exception e) {
LOG.warn("Could not initialize " + field);
}
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
index c012d90..8259fde 100644
--- a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
+++ b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
@@ -419,7 +419,7 @@ public class HibernateDetachUtility {
String assistNameDelimiter = assistClassName.contains("javassist") ? "_$$_" : "$$";
assistClassName = assistClassName.substring(0, assistClassName.indexOf(assistNameDelimiter));
- if (!replacement.getClass().getName().contains("hibernate")) {
+ if (replacement != null && !replacement.getClass().getName().contains("hibernate")) {
nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
depth + 1, serializationType);
@@ -607,4 +607,4 @@ public class HibernateDetachUtility {
// ignore this
}
}
-}
\ No newline at end of file
+}
commit 6079e06ac677015c8f87838e7ac8e52cc766d5f6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon May 13 12:36:17 2013 +0200
Bug 962379 - [as7] Garbage Collector Resource misses 'collection-count' and 'collection-time' per minute metrics
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 742c4d5..4a26d19 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -7214,8 +7214,8 @@
<c:simple-property name="includeRuntime" readOnly="true" default="true"/>
</plugin-configuration>
- <metric property="collection-count" description="The total number of collections that have occurred."/>
- <metric property="collection-time" description="The approximate accumulated collection elapsed time in milliseconds."/>
+ <metric property="collection-count" description="The total number of collections that have occurred." measurementType="trendsup"/>
+ <metric property="collection-time" description="The approximate accumulated collection elapsed time in milliseconds." measurementType="trendsup"/>
<metric property="name" dataType="trait" description="The name representing this garbage collector"/>
<metric property="valid" dataType="trait" description="Whether this this memory manager is valid in the Java virtual machine."/>
commit 8130e34b50dfc81ae0074ac789d784d159b7b9aa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 10 17:01:01 2013 -0400
BZ 699893 911692 - if the user ran EAP 5 with cmd line option -Djboss.server.data.dir=/some/data/dir
then the AS5 plugin should look there, too, to try to find the jnp-service.url file
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
index 01eb105..670347f 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
@@ -500,32 +500,42 @@ public class ApplicationServerDiscoveryComponent implements ResourceDiscoveryCom
}
private String getJnpURL(JBossInstanceInfo cmdLine, File installHome, File configDir) {
- File jnpServiceUrlFile = new File(configDir, "data/jnp-service.url");
- if (jnpServiceUrlFile.exists() && jnpServiceUrlFile.canRead()) {
- BufferedReader br = null;
- try {
- br = new BufferedReader(new FileReader(jnpServiceUrlFile));
- String jnpUrl = br.readLine();
- if (jnpUrl != null) {
- if (log.isDebugEnabled()) {
- log.debug("Read JNP URL from jnp-service.url file: " + jnpUrl);
+ ArrayList<File> possibleJnpServiceUrlFiles = new ArrayList<File>(2);
+ possibleJnpServiceUrlFiles.add(new File(configDir, "data/jnp-service.url"));
+ // if the app server was told to go somewhere else to store its data files, look in there too (BZ 699893)
+ if (cmdLine.getSystemProperties() != null) {
+ String dataDir = cmdLine.getSystemProperties().getProperty("jboss.server.data.dir");
+ if (dataDir != null) {
+ possibleJnpServiceUrlFiles.add(new File(dataDir, "jnp-service.url"));
+ }
+ }
+ for (File jnpServiceUrlFile : possibleJnpServiceUrlFiles) {
+ if (jnpServiceUrlFile.exists() && jnpServiceUrlFile.canRead()) {
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new FileReader(jnpServiceUrlFile));
+ String jnpUrl = br.readLine();
+ if (jnpUrl != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Read JNP URL from jnp-service.url file: " + jnpUrl);
+ }
+ return jnpUrl;
}
- return jnpUrl;
- }
- } catch (IOException ioe) {
- // Nothing to do
- } finally {
- if (br != null) {
- try {
- br.close();
- } catch (IOException e) {
- // nada
+ } catch (IOException ioe) {
+ // Nothing to do
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ // nada
+ }
}
}
}
}
- log.warn("Failed to read JNP URL from '" + jnpServiceUrlFile + "'.");
+ log.warn("Failed to read JNP URL from: " + possibleJnpServiceUrlFiles);
// Above did not work, so fall back to our previous scheme
JnpConfig jnpConfig = getJnpConfig(installHome, configDir, cmdLine.getSystemProperties());
commit d2523a093115225352825051b5a795a7226a7c23
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 10 15:56:04 2013 -0400
BZ 903402 - fix code if windows drive is missing but otherwise the path is absolute
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
index 35a2263..e3c4a27 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
@@ -243,7 +243,7 @@ public class JBossInstanceInfo {
for (String pathElement : this.classPath) {
if (pathElement.endsWith("run.jar")) {
runJar = new File(pathElement);
- if (!runJar.isAbsolute()) {
+ if (!runJar.isAbsolute() && !runJar.exists()) {
runJar = new File(this.processInfo.getExecutable().getCwd(), runJar.getPath());
}
if (!runJar.exists()) {
diff --git a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
index 9dadd39..b515af7 100644
--- a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
+++ b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
@@ -237,7 +237,7 @@ public class JBossInstanceInfo {
for (String pathElement : this.classPath) {
if (pathElement.endsWith("run.jar")) {
runJar = new File(pathElement);
- if (!runJar.isAbsolute()) {
+ if (!runJar.isAbsolute() && !runJar.exists()) {
runJar = new File(this.processInfo.getExecutable().getCwd(), runJar.getPath());
}
if (!runJar.exists()) {
commit 01d875b284d842df2ac4f099598b5f2a5f320bf2
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 16:34:51 2013 +0200
Provide the old method signature as fallback in case other plugins that inherit from this one, still need it.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index 9eb63f9..48fbf1f 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -53,12 +53,23 @@ public enum JBossProductType {
}
/**
+ * Determine the product type of a JBoss install. This implies an api version of 1.x which
+ * is a JBossAS 7.x
+ * @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
+ * @return the product type
+ * @deprecated "Use the version with the apiVersion"
+ */
+ @Deprecated
+ public static JBossProductType determineJBossProductType(File homeDir) {
+ return determineJBossProductType(homeDir,"1.0");
+ }
+
+ /**
* Determines the product type of a JBoss product installation.
*
- *
* @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
*
- * @param apiVersion
+ * @param apiVersion Api version of the domain api.
* @return the product type
*/
public static JBossProductType determineJBossProductType(File homeDir, String apiVersion) {
commit 3bba88c36f7d4a91ac5ac824c0e5b7fd43c3dd0b
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 14:39:21 2013 +0200
BZ 961787 - try to determine AS/WFLY via domain api version before falling back to directory names, as this is more reliable.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
index 9a4d5bd..cc13406 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
@@ -193,7 +193,8 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
serverPluginConfig.setHostname(managementHostPort.host);
serverPluginConfig.setPort(managementHostPort.port);
pluginConfig.setSimpleValue("realm", hostConfig.getManagementSecurityRealm());
- JBossProductType productType = JBossProductType.determineJBossProductType(homeDir);
+ String apiVersion = hostConfig.getDomainApiVersion();
+ JBossProductType productType = JBossProductType.determineJBossProductType(homeDir, apiVersion);
serverPluginConfig.setProductType(productType);
pluginConfig.setSimpleValue("hostXmlFileName", getHostXmlFileName(commandLine));
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index 9edfb2f..9eb63f9 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -37,7 +37,7 @@ public enum JBossProductType {
JPP("JPP", "JBoss EAP 6", "JBoss Portal Platform 6", "Portal Platform"),
// EWP("EWP", "JBoss EWP 6", "JBoss Enterprise Web Platform 6", "EWP"),
SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP"),
- WILDFLY8("WildFly","WildFly 8" ,"WildFly Appliction Server 8" , "WildFly");
+ WILDFLY8("WildFly","WildFly 8" ,"WildFly Application Server 8" , "WildFly");
public final String SHORT_NAME;
public final String NAME;
@@ -55,13 +55,28 @@ public enum JBossProductType {
/**
* Determines the product type of a JBoss product installation.
*
+ *
* @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
*
+ * @param apiVersion
* @return the product type
*/
- public static JBossProductType determineJBossProductType(File homeDir) {
+ public static JBossProductType determineJBossProductType(File homeDir, String apiVersion) {
try {
- return determineJBossProductTypeViaProductConfFile(homeDir);
+ JBossProductType jBossProductType = determineJBossProductTypeViaProductConfFile(homeDir);
+ if (jBossProductType==null) {
+ // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
+ // and thus have no product type. So we need to check differently
+ // AS 7.0/1 use a domain api version of 1.x, while WildFly uses version 2.0+
+ // like 2.0 in "urn:jboss:domain:2.0" from <server xmlns="..." > element in standalone.xml
+ if (apiVersion.startsWith("1")) {
+ jBossProductType = JBossProductType.AS;
+ } else {
+ // We should later check for newer WildFly versions to differentiate them
+ jBossProductType = JBossProductType.WILDFLY8;
+ }
+ }
+ return jBossProductType;
} catch (Exception e) {
// TODO: Log an error.
return determineJBossProductTypeViaHomeDirName(homeDir);
@@ -109,9 +124,7 @@ public enum JBossProductType {
throw new RuntimeException("Unknown product type: " + slot);
}
} else {
- // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
- // so we need another way to distinguish them
- productType = determineJBossProductTypeViaHomeDirName(homeDir);
+ productType = null;
}
return productType;
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
index a8909ff..329246e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
@@ -233,6 +233,14 @@ public class HostConfiguration {
return securityPropertyFile;
}
+ public String getDomainApiVersion() {
+
+ String version = document.getFirstChild().getAttributes().getNamedItem("xmlns").getTextContent();
+
+ version = version.substring(version.lastIndexOf(':')+1);
+ return version;
+ }
+
/**
* Run the passed xpathExpression on the prepopulated hostXml document and
* return the target element or attribute as a String.
commit 8868d16074902e9996f00cce8db697d02fce21ad
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 12:18:26 2013 +0200
BZ 960959 apply inventory status filtering with COMMITTED as default for searches.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index 138ca40..2dde3a4 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -52,7 +52,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Use this to get the global fields for this Criteria field type. Don't use inspection as the field names
* for this abstract base class do not conform (for legacy reasons) to the prefix convention help by the
* subclasses.
- *
+ *
* @return The set of global fields for this Criteria field type. Meaning, usable by all subclasses.
*/
public List<String> getGlobalFields() {
@@ -76,7 +76,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* private NonBindingOverrideFilter filterResourceOnly; // requires overrides - finds only those associated with a resource
* ...
* filterOverrides.put("resourceTypeOnly", "resourceType IS NOT NULL"); // notice no ? parameter
- *
+ *
* Note: Typically a null value is analogous to OFF.
*/
public enum NonBindingOverrideFilter {
@@ -87,12 +87,12 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Apply a restriction to reduce the cost of the {@link Criteria}-based query generation and execution routines.
*/
public enum Restriction {
- /**
+ /**
* This returns an empty {@link PageList} result whose {@link PageList#getTotalSize()} method otherwise
* contains the correct value.
*/
COUNT_ONLY,
- /**
+ /**
* This will return the {@link PageList} result whose {@link PageList#isUnbounded()} returned true, meaning
* that the value contained within {@link PageList#getTotalSize()} is invalid / undefined.
*/
@@ -121,10 +121,10 @@ public abstract class Criteria implements Serializable, BaseCriteria {
// All Criteria support sorting on ID
protected PageOrdering sortId;
-
+
// All Criteria support filtering on ID
protected Integer filterId;
-
+
// All Criteria support filtering on IDs
protected List<Integer> filterIds;
@@ -176,7 +176,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
addSortField("id");
this.sortId = sortId;
}
-
+
public void addFilterId(Integer filterId) {
this.filterId = filterId;
}
@@ -189,6 +189,13 @@ public abstract class Criteria implements Serializable, BaseCriteria {
orderingFieldNames.add("sort" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
}
+ /**
+ * Sets the paging constraints to return items [pageNumber * pageSize , ((pageNumber+1) * pageSize) -1 ].
+ * For this to work correctly, you also need to set the sort
+ * criteria (do not rely on implicit id-sorting to work correctly.
+ * @param pageNumber The page to fetch. This is 0-based.
+ * @param pageSize The number of items to return.
+ */
public void setPaging(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
@@ -196,7 +203,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
/**
* If the pageControl is set, then this criteria object will completely ignore any
- * calls made to setPaging(pageNumber, pageSize) as well as addSortField(fieldName),
+ * calls made to setPaging(pageNumber, pageSize) as well as addSortField(fieldName),
* which is useful from a server-side calling context where the PageControl object
* will already have been created for you by the extensions at the JSF layer.
*/
@@ -248,7 +255,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
/**
* If set to true, string-based filters will use exact string matches;
- * Default is 'false', which means we'll fuzzy match
+ * Default is 'false', which means we'll fuzzy match
*/
public void setStrict(boolean strict) {
this.strict = strict;
@@ -262,9 +269,9 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* By default, two queries will be generated for this Criteria: one which fetches the requested page/subset of
* entity results, and one which fetches the total cardinality of the result set. If you wish to only retrieve one
* of those pieces of data, you can do so by setting a restriction on the query generation and execution routines.
- *
+ *
* The restriction, once set, can be removed by passing NULL to this method.
- *
+ *
* @see Restriction
*/
public void setRestriction(Restriction restriction) {
@@ -325,7 +332,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Somewhat analogous to JPA's Query.getSingleResult. Wrap a CriteriaQuery result with this method when
* expecting a single result from the fetch. If the result set has only one entry it is returned. Otherwise
* a RuntimeException is thrown, indicating whether no results, or multiple results were found.
- *
+ *
* @param result
* @return
* @throws RuntimeException In not exactly one result is found. The message will include either the String
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 7a198bd..0038099 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -52,8 +52,6 @@ import org.infinispan.Cache;
import org.infinispan.manager.CacheContainer;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
@@ -349,6 +347,7 @@ public class AbstractRestBean {
rwt.setTypeName(resourceType.getName());
rwt.setTypeId(resourceType.getId());
rwt.setPluginName(resourceType.getPlugin());
+ rwt.setStatus(res.getInventoryStatus().name());
Resource parent = res.getParentResource();
if (parent != null) {
rwt.setParentId(parent.getId());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
index cea84c2..3879f73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
@@ -23,7 +23,10 @@ import javax.ejb.ApplicationException;
/**
* Exception if arguments are bad.
* Don't use java.lang.IllegalArgumentException, as this is no
- * Application Exception and gets wrapped
+ * Application Exception and gets wrapped.
+ *
+ * The ExceptionMapper translates this into a 406 repsonse code
+ *
* @author Heiko W. Rupp
*/
@ApplicationException(rollback = false, inherited = true)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 3e1d195..288e9f7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -177,14 +177,28 @@ public class ResourceHandlerBean extends AbstractRestBean {
@GET @GZIP
@Path("/")
+ @ApiError(code = 406, reason = "The passed inventory status was invalid")
@ApiOperation(value = "Search for resources by the given search string, possibly limited by category and paged", responseClass = "ResourceWithType")
- public Response getResourcesByQuery(@ApiParam("String to search in the resource name") @QueryParam("q") String q,
+ public Response getResourcesByQuery(@ApiParam("Limit results to param in the resource name") @QueryParam("q") String q,
@ApiParam("Limit to category (PLATFORM, SERVER, SERVICE") @QueryParam("category") String category,
@ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
- @ApiParam("Page for paging") @QueryParam("page") Integer page,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @ApiParam(value = "Limit to Inventory status of the resources", allowableValues = "ALL, NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED")
+ @DefaultValue("COMMITTED") @QueryParam("status") String status,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
+
ResourceCriteria criteria = new ResourceCriteria();
+ if (!status.toLowerCase().equals("all")) {
+ try {
+ criteria.addFilterInventoryStatus(InventoryStatus.valueOf(status.toUpperCase()));
+ } catch (IllegalArgumentException iae) {
+ throw new BadArgumentException("status","Value " + status + " is not in the list of allowed values: ALL, NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED" );
+ }
+ } else {
+ // JavaDoc says to explicitly set to null in order to get all Status
+ criteria.addFilterInventoryStatus(null);
+ }
if (q!=null) {
criteria.addFilterName(q);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 6b9aace..703e897 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -52,6 +52,7 @@ public class ResourceWithType {
Integer typeId;
String pluginName;
Integer parentId;
+ String status;
List<Link> links = new ArrayList<Link>();
private String ancestry;
@@ -126,6 +127,15 @@ public class ResourceWithType {
this.parentId = parentId;
}
+ @ApiProperty(value = "Inventory status of the resource.",allowableValues = "NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED" )
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
@XmlElementRef
public List<Link> getLinks() {
return links;
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index c71bbd8..3efd807 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -113,7 +113,6 @@ public class ResourcesTest extends AbstractBase {
@Test
public void testGetPlatformUILink() {
- Response response =
given()
.header(acceptJson)
.pathParam("id", _platformId)
@@ -145,6 +144,74 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testResourceQueryAllStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","all")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(200)
+ .body("links.self", notNullValue())
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryCommittedStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","committed")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(200)
+ .body("links.self", notNullValue())
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryNewStatus() throws Exception {
+
+ // Unfortunately we can not assume that there are
+ // any resources in other states than COMMITTED
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("status","NeW")
+ .expect()
+ .statusCode(200)
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryBadStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","Frobnitz")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(406)
+ .when()
+ .get("/resource");
+ }
+
+ @Test
public void testResourceQueryCategory() throws Exception {
with()
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
index 6cbcea0..f060101 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
@@ -33,6 +33,7 @@ public class Resource {
String typeName;
String pluginName;
Integer parentId;
+ String status;
int typeId;
List<Map> links;
String ancestry;
@@ -103,4 +104,12 @@ public class Resource {
public void setAncestry(String ancestry) {
this.ancestry = ancestry;
}
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
}
commit c12f45a0dac01b601ce05fc7046042b83e51b184
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 11:15:25 2013 +0200
Make this test use the RHQ server, so that no external EAP needs to be set up.
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 5532b13..7e3f45a 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -176,7 +176,7 @@ public class ContentTest extends AbstractBase {
List<Map<String,Object>> resources =
given()
.header(acceptJson)
- .queryParam("q","EAP (127.0.0.1:9990)") // TODO fragile -- better search for it?
+ .queryParam("q","EAP (127.0.0.1:6990)") // TODO Can we identify the RHQ server itself better?
.queryParam("category","SERVER")
.expect()
.statusCode(200)
@@ -188,6 +188,7 @@ public class ContentTest extends AbstractBase {
assert resources.size()>0;
int as7Id = Integer.valueOf((String)resources.get(0).get("resourceId"));
+ int createdResourceId=-1;
// create child of eap6 as deployment
try {
@@ -223,25 +224,33 @@ public class ContentTest extends AbstractBase {
int status = response.getStatusCode();
String location = response.getHeader("Location");
- System.out.println("Location " + location + "\n\n");
+ System.out.println("\nLocation " + location + "\n\n");
assert location!=null;
// We need to check what we got. A 302 means the deploy is still
// in progress, so we need to wait a little longer
while (status==302) {
- status =
+ response =
given()
.header(acceptJson)
.log().everything()
.expect()
- .statusCode(isOneOf(200,201,302))
+ .statusCode(isOneOf(200, 201, 302))
.log().everything()
.when()
- .get(location)
- .getStatusCode();
+ .get(location);
+
+ status = response.getStatusCode();
}
+ createdResourceId = response.jsonPath().getInt("resourceId");
+
+ System.out.println("\n Deploy is done, resource Id = " + createdResourceId + " \n");
+ System.out.flush();
+
+ assert createdResourceId != -1;
+
} finally {
// Remove the uploaded content
@@ -254,47 +263,23 @@ public class ContentTest extends AbstractBase {
.when()
.delete("/content/{handle}");
+ System.out.println("\n Content removed \n");
+ System.out.flush();
+
+
+ // We need to wait here a little, as the machinery is not used to
+ // quick create-delete-cycles
+ Thread.sleep(20*1000L);
- // try to remove the created resource
- Response response =
given()
- .queryParam("q", "test-simple.war")
.header(acceptJson)
+ .queryParam("physical", "true") // Also remove target on the EAP instance
+ .pathParam("id",createdResourceId)
+ .log().everything()
.expect()
.log().everything()
.when()
- .get("/resource");
-
- List links = response.body().jsonPath().getList("links");
-
- System.out.println(links);
- assert links!=null;
-
- if (links.size()>0) {
-
- String link = null;
- @SuppressWarnings("unchecked")
- List<Map<String,Map<String,String>>> listOfMaps = (List<Map<String, Map<String, String>>>) links.get(0);
-
- for (Map<String,Map<String,String>> map : listOfMaps) {
- if (map.containsKey("self")) {
- link = map.get("self").get("href");
- break;
- }
- }
-
- assert link != null;
-
- System.out.println("Link: " + link);
-
- given()
- .header(acceptJson)
- .queryParam("physical","true") // Also remove target on the EAP instance
- .expect()
- .log().everything()
- .when()
- .delete(link);
- }
+ .delete("/resource/{id}");
}
commit 80e9f520ab6dfa5fa42357aa7fa5dbfdeb98d631
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 9 21:50:21 2013 -0400
BZ 951382 - if keystore/truststore is left undefined in agent config, we'll explicitly set the pref for the user using the "conf/" location
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
index d959552..6e1a95a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
@@ -2313,6 +2313,9 @@ public class AgentMain {
* @throws Exception if any error causes the startup to fail
*/
private void startCommServices(BootstrapLatchCommandListener listener) throws Exception {
+ // BZ 951382 - if any locations for keystore/truststore are not configured, set our own defaults to the conf/ directory
+ assignDefaultLocationToKeystoreTruststoreFiles();
+
// create our client sender so we can send commands to our server
// do this before we create our auto-discovery listener and start the server-side services
// since it will be needed by the listener very quickly if the server is already online
@@ -2348,6 +2351,41 @@ public class AgentMain {
return;
}
+ private void assignDefaultLocationToKeystoreTruststoreFiles() {
+ File confDir = new File("conf");
+ if (!confDir.exists()) {
+ return; // conf/ doesn't exist (perhaps we are running in a test?) - do nothing and just fallback to the standard defaults
+ }
+
+ String prefNamesFileNames[][] = {
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_KEYSTORE_FILE_NAME },
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE_NAME } };
+
+ Preferences prefs = m_configuration.getPreferences();
+ for (String[] prefNameFileName : prefNamesFileNames) {
+ String value = prefs.get(prefNameFileName[0], null);
+ if (value == null) {
+ value = new File(confDir, prefNameFileName[1]).getAbsolutePath();
+ prefs.put(prefNameFileName[0], value);
+ LOG.debug(AgentI18NResourceKeys.CERT_FILE_LOCATION, prefNameFileName[0], value);
+ }
+ }
+
+ try {
+ prefs.flush();
+ } catch (Exception e) {
+ LOG.warn(AgentI18NResourceKeys.CANNOT_STORE_PREFERENCES, "keystore/truststore files", e);
+ }
+
+ return;
+ }
+
private boolean isAutoDiscoveryEnabled() {
return m_autoDiscoveryListener != null;
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
index 10761ff..21a39a9 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
@@ -28,6 +28,9 @@ import mazz.i18n.annotation.I18NResourceBundle;
*/
@I18NResourceBundle(baseName = "agent-messages", defaultLocale = "en")
public interface AgentI18NResourceKeys {
+ @I18NMessage("Explicitly setting file location [{0}] to [{1}]")
+ String CERT_FILE_LOCATION = "AgentConfiguration.cert-file-location";
+
@I18NMessage("The configured server alias [{0}] cannot be resolved - will use localhost address. Cause: {1}")
String SERVER_ALIAS_UNKNOWN = "AgentConfiguration.server-alias-unknown";
commit 7c4577c895a469b5ddce6aa91eb6935eb5cf6cc9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 8 22:23:58 2013 -0400
BZ 535800 - can't use default protocol because it is automatically initialized and cached, not allowing us to use a customized one
add a main() for quick testing
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
index 6097ebe..16a4544 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
@@ -23,7 +23,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
@@ -62,29 +61,13 @@ public class SecureConnector {
private final String truststoreAlgorithm;
/**
- * The {@link #openSecureConnection(URL) secure connections} built by this object will not
- * authenticate the server endpoint, but they will use the default secure socket protocol to
- * encrypt the connection traffic (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>).
- *
- * @throws NoSuchAlgorithmException if the default secure connection protocol cannot be determined
- */
- public SecureConnector() throws NoSuchAlgorithmException {
- this(null, null, null, null, null);
- }
-
- /**
* The {@link #openSecureConnection(URL) secure connections} built by this object will
* not authenticate the server endpoint, but they will use the given secure socket protocol
* to encrypt the connection traffic.
*
- * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
- * the JVM's default secure socket protocol will be used
- * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
- *
- * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
- * the default secure connection protocol cannot be determined
+ * @param secureSocketProtocol the secure socket protocol to use (e.g. "TLS")
*/
- public SecureConnector(String secureSocketProtocol) throws NoSuchAlgorithmException {
+ public SecureConnector(String secureSocketProtocol) {
this(secureSocketProtocol, null, null, null, null);
}
@@ -97,28 +80,22 @@ public class SecureConnector {
* truststore parameters are ignored and the secure connections built by this object will
* not authenticate the server endpoint.
*
- * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
- * the JVM's default secure socket protocol will be used
- * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ * @param secureSocketProtocol the secure socket protocol to use (e.g. "TLS")
* @param truststoreFile the truststore file containing authorized certificates
- * @param truststorePassword the password to the truststore file
- * @param truststoreType the type of the truststore file; if <code>null</code>, then the JVM's
+ * @param truststorePassword the password to the truststore file (if a file is given, this must not be <code>null</code>)
+ * @param truststoreType the type of the truststore file (e.g. "JKS"); if <code>null</code>, then the JVM's
* default type is used (see <code>java.security.KeyStore.getDefaultType()</code>)
- * @param truststoreAlgorithm the standard name of the trust management algorithm; if <code>null</code>,
- * then the JVM's default algorithm is used (see
+ * @param truststoreAlgorithm the standard name of the trust management algorithm (e.g. "SunX509");
+ * if <code>null</code>, then the JVM's default algorithm is used (see
* <code>javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()</code>)
- *
- * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
- * the default secure connection protocol cannot be determined
*/
public SecureConnector(String secureSocketProtocol, File truststoreFile, String truststorePassword,
- String truststoreType, String truststoreAlgorithm) throws NoSuchAlgorithmException {
+ String truststoreType, String truststoreAlgorithm) {
if (secureSocketProtocol == null) {
- this.secureSocketProtocol = SSLContext.getDefault().getProtocol();
- } else {
- this.secureSocketProtocol = secureSocketProtocol;
+ throw new IllegalArgumentException("secure socket protocol cannot be null");
}
+ this.secureSocketProtocol = secureSocketProtocol;
if (truststoreFile == null) {
// no truststore file was provided, we don't need to know any truststore parameters
@@ -129,17 +106,21 @@ public class SecureConnector {
} else {
// the truststore file is provided, make sure we have non-null truststore parameters, using defaults if need be
this.truststoreFile = truststoreFile;
+
+ if (truststorePassword == null) {
+ throw new IllegalArgumentException("truststorePassword cannot be null");
+ }
this.truststorePassword = truststorePassword;
if (truststoreType == null) {
truststoreType = KeyStore.getDefaultType();
}
- this.truststoreType = (truststoreType != null) ? truststoreType : "JKS";
+ this.truststoreType = truststoreType;
if (truststoreAlgorithm == null) {
truststoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
}
- this.truststoreAlgorithm = (truststoreAlgorithm != null) ? truststoreAlgorithm : "SunX509";
+ this.truststoreAlgorithm = truststoreAlgorithm;
}
return;
@@ -216,4 +197,16 @@ public class SecureConnector {
return true;
}
};
+
+ public static void main(String[] args) throws Exception {
+ HttpsURLConnection conn = new SecureConnector("TLS").openSecureConnection(new URL(args[0]));
+ java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+ java.io.InputStream input = new java.io.BufferedInputStream(conn.getInputStream(), 32768);
+ byte[] buffer = new byte[32768];
+ for (int bytesRead = input.read(buffer); bytesRead != -1; bytesRead = input.read(buffer)) {
+ out.write(buffer, 0, bytesRead);
+ }
+ out.flush();
+ System.out.println(out.toString());
+ }
}
\ No newline at end of file
commit 2c6438cd554b64aa97f2b83d1d5fe7f005d9f68f
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 8 16:43:36 2013 -0400
BZ 535800 - allow the agent to download the agent update binary over the configured SSL channel
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
index 9edad7f..ccd46db 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
+import javax.net.ssl.HttpsURLConnection;
+
import mazz.i18n.Logger;
import org.rhq.core.util.MessageDigestGenerator;
@@ -153,7 +155,13 @@ public class AgentUpdateDownload {
// we only support http/s
url = getDownloadUrl();
LOG.info(AgentI18NResourceKeys.UPDATE_DOWNLOAD_RETRIEVAL, info, url);
- conn = (HttpURLConnection) url.openConnection();
+
+ if (url.getProtocol().equals("https")) {
+ conn = openSecureConnection(url);
+ } else {
+ conn = (HttpURLConnection) url.openConnection(); // we only support http(s), so this cast is OK
+ }
+
inStream = conn.getInputStream();
// put the update content in the local file system
@@ -277,4 +285,24 @@ public class AgentUpdateDownload {
return false;
}
}
+
+ private HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ AgentConfiguration config = this.agent.getConfiguration();
+ String secureSocketProtocol = config.getClientSenderSecuritySocketProtocol();
+ SecureConnector secureConnector;
+ if (config.isClientSenderSecurityServerAuthMode()) {
+ File file = new File(config.getClientSenderSecurityTruststoreFile());
+ if (!file.isAbsolute()) {
+ file = new File(this.agent.getAgentHomeDirectory(), file.getPath());
+ }
+ String password = config.getClientSenderSecurityTruststorePassword();
+ String type = config.getClientSenderSecurityTruststoreType();
+ String algorithm = config.getClientSenderSecurityTruststoreAlgorithm();
+ secureConnector = new SecureConnector(secureSocketProtocol, file, password, type, algorithm);
+ } else {
+ secureConnector = new SecureConnector(secureSocketProtocol);
+ }
+
+ return secureConnector.openSecureConnection(url);
+ }
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
index b429fa8..6ef123a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,14 @@
*/
package org.rhq.enterprise.agent;
+import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;
+import javax.net.ssl.HttpsURLConnection;
+
import mazz.i18n.Logger;
import org.rhq.core.util.exception.ThrowableUtil;
@@ -100,7 +103,13 @@ public class AgentUpdateVersion {
// we only support http/s
url = getVersionUrl();
LOG.debug(AgentI18NResourceKeys.UPDATE_VERSION_RETRIEVAL, url);
- conn = (HttpURLConnection) url.openConnection();
+
+ if (url.getProtocol().equals("https")) {
+ conn = openSecureConnection(url);
+ } else {
+ conn = (HttpURLConnection) url.openConnection(); // we only support http(s), so this cast is OK
+ }
+
versionProps = new Properties();
inStream = conn.getInputStream();
versionProps.load(inStream);
@@ -142,4 +151,24 @@ public class AgentUpdateVersion {
return;
}
+
+ private HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ AgentConfiguration config = this.agent.getConfiguration();
+ String secureSocketProtocol = config.getClientSenderSecuritySocketProtocol();
+ SecureConnector secureConnector;
+ if (config.isClientSenderSecurityServerAuthMode()) {
+ File file = new File(config.getClientSenderSecurityTruststoreFile());
+ if (!file.isAbsolute()) {
+ file = new File(this.agent.getAgentHomeDirectory(), file.getPath());
+ }
+ String password = config.getClientSenderSecurityTruststorePassword();
+ String type = config.getClientSenderSecurityTruststoreType();
+ String algorithm = config.getClientSenderSecurityTruststoreAlgorithm();
+ secureConnector = new SecureConnector(secureSocketProtocol, file, password, type, algorithm);
+ } else {
+ secureConnector = new SecureConnector(secureSocketProtocol);
+ }
+
+ return secureConnector.openSecureConnection(url);
+ }
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
new file mode 100644
index 0000000..6097ebe
--- /dev/null
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
@@ -0,0 +1,219 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.agent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * If you need to make a connection to an external HTTP server using the https protocol,
+ * use this class to build the connection. You can specify which trusted certificates can be used
+ * to verify and authenticate the remote server via truststore file parameters passed into the constructor.
+ * In other words, you don't have to rely on the global system properties javax.net.ssl.keyStore and
+ * javax.net.ssl.trustStore to make your connection.
+ *
+ * This is useful if some other object running in your JVM requires
+ * javax.net.ssl.keyStore/javax.net.ssl.trustStore set to something other than what you want to use.
+ * Since those system properties can only be set once during the lifetime of the JVM, it is not possible
+ * to change them at runtime and expect the change to take effect. Besides, even if you could change them,
+ * this could then effect the other objects that do need those properties set to particular values.
+ *
+ * This object has the ability to make an encrypted call without requiring a truststore to exist (that is,
+ * you can encrypt the call but you will not have the server endpoint verified and authenticated). This
+ * can be useful if you aren't concerned with authenticating the endpoint but do want to encrypt the
+ * traffic.
+ *
+ * @author John Mazzitelli
+ */
+public class SecureConnector {
+ private final String secureSocketProtocol;
+ private final File truststoreFile;
+ private final String truststorePassword;
+ private final String truststoreType;
+ private final String truststoreAlgorithm;
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will not
+ * authenticate the server endpoint, but they will use the default secure socket protocol to
+ * encrypt the connection traffic (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>).
+ *
+ * @throws NoSuchAlgorithmException if the default secure connection protocol cannot be determined
+ */
+ public SecureConnector() throws NoSuchAlgorithmException {
+ this(null, null, null, null, null);
+ }
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will
+ * not authenticate the server endpoint, but they will use the given secure socket protocol
+ * to encrypt the connection traffic.
+ *
+ * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
+ * the JVM's default secure socket protocol will be used
+ * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ *
+ * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
+ * the default secure connection protocol cannot be determined
+ */
+ public SecureConnector(String secureSocketProtocol) throws NoSuchAlgorithmException {
+ this(secureSocketProtocol, null, null, null, null);
+ }
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will
+ * authenticate the server endpoint using the given truststore file and its related parameters.
+ * The connection will use the given secure socket protocol to encrypt the connection traffic.
+ *
+ * Note that if the given <code>truststoreFile</code> is <code>null</code>, the other
+ * truststore parameters are ignored and the secure connections built by this object will
+ * not authenticate the server endpoint.
+ *
+ * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
+ * the JVM's default secure socket protocol will be used
+ * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ * @param truststoreFile the truststore file containing authorized certificates
+ * @param truststorePassword the password to the truststore file
+ * @param truststoreType the type of the truststore file; if <code>null</code>, then the JVM's
+ * default type is used (see <code>java.security.KeyStore.getDefaultType()</code>)
+ * @param truststoreAlgorithm the standard name of the trust management algorithm; if <code>null</code>,
+ * then the JVM's default algorithm is used (see
+ * <code>javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()</code>)
+ *
+ * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
+ * the default secure connection protocol cannot be determined
+ */
+ public SecureConnector(String secureSocketProtocol, File truststoreFile, String truststorePassword,
+ String truststoreType, String truststoreAlgorithm) throws NoSuchAlgorithmException {
+
+ if (secureSocketProtocol == null) {
+ this.secureSocketProtocol = SSLContext.getDefault().getProtocol();
+ } else {
+ this.secureSocketProtocol = secureSocketProtocol;
+ }
+
+ if (truststoreFile == null) {
+ // no truststore file was provided, we don't need to know any truststore parameters
+ this.truststoreFile = null;
+ this.truststorePassword = null;
+ this.truststoreType = null;
+ this.truststoreAlgorithm = null;
+ } else {
+ // the truststore file is provided, make sure we have non-null truststore parameters, using defaults if need be
+ this.truststoreFile = truststoreFile;
+ this.truststorePassword = truststorePassword;
+
+ if (truststoreType == null) {
+ truststoreType = KeyStore.getDefaultType();
+ }
+ this.truststoreType = (truststoreType != null) ? truststoreType : "JKS";
+
+ if (truststoreAlgorithm == null) {
+ truststoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ }
+ this.truststoreAlgorithm = (truststoreAlgorithm != null) ? truststoreAlgorithm : "SunX509";
+ }
+
+ return;
+ }
+
+ public HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ // we assume the URL is https - if it is not, its an error so just let the cast throw exception
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+
+ TrustManager[] trustManagers;
+ SSLContext sslContext = SSLContext.getInstance(getSecureSocketProtocol());
+
+ if (getTruststoreFile() == null) {
+ // we are configured to not care about authenticating the server, just encrypt but don't worry about certificates
+ trustManagers = new TrustManager[] { NO_OP_TRUST_MANAGER };
+ connection.setHostnameVerifier(NO_OP_HOSTNAME_VERIFIER);
+ } else {
+ // We need to configure our SSL connection with the agent's truststore so we can authenticate the server.
+ // First, create a KeyStore, but load it with our truststore entries.
+ KeyStore keyStore = KeyStore.getInstance(getTruststoreType());
+ keyStore.load(new FileInputStream(getTruststoreFile()), getTruststorePassword().toCharArray());
+ // now create a truststore manager instance and initialize it with our KeyStore we created with all our truststore entries
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(getTruststoreAlgorithm());
+ tmf.init(keyStore);
+ trustManagers = tmf.getTrustManagers();
+ }
+
+ sslContext.init(null, trustManagers, null);
+ connection.setSSLSocketFactory(sslContext.getSocketFactory());
+
+ return connection;
+ }
+
+ public String getSecureSocketProtocol() {
+ return this.secureSocketProtocol;
+ }
+
+ public File getTruststoreFile() {
+ return this.truststoreFile;
+ }
+
+ public String getTruststorePassword() {
+ return this.truststorePassword;
+ }
+
+ public String getTruststoreType() {
+ return this.truststoreType;
+ }
+
+ public String getTruststoreAlgorithm() {
+ return this.truststoreAlgorithm;
+ }
+
+ private static TrustManager NO_OP_TRUST_MANAGER = new X509TrustManager() {
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ return;
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ return;
+ }
+ };
+
+ private static HostnameVerifier NO_OP_HOSTNAME_VERIFIER = new HostnameVerifier() {
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ };
+}
\ No newline at end of file
commit 8091c631ae4cebe9a19825f3c107753590bec922
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 10:15:23 2013 -0700
[BZ 960646] - RFE Redesigned Availability Chart - i18n.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index f0db5a2..fbce610 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -124,11 +124,13 @@ public class AvailabilityOverUnderGraphType {
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverEndLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()()
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
);
@@ -264,7 +266,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-weight", "bold")
.attr("fill", "#003168")
- .text("Availability");
+ .text(availChartContext.chartTitle);
svg.append("text")
.attr("class", "upLabel")
@@ -274,7 +276,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "9px")
.attr("fill", "#50505a")
.style("text-anchor", "end")
- .text("UP");
+ .text(availChartContext.chartUpLabel);
svg.append("text")
.attr("class", "downLabel")
@@ -284,7 +286,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "9px")
.attr("fill", "#50505a")
.style("text-anchor", "end")
- .text("DOWN");
+ .text(availChartContext.chartDownLabel);
}
@@ -355,8 +357,16 @@ public class AvailabilityOverUnderGraphType {
return MSG.chart_hover_start_label();
}
- public String getChartHoverEndLabel() {
- return MSG.chart_hover_end_label();
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
}
public String getChartHoverBarLabel() {
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 0c5af20..00a68ef 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+avail_chart_down_label = DOWN
+avail_chart_title_label = Availability
+avail_chart_up_label = UP
chart_date_label = Date
chart_down_label = Down
chart_hover_availability_label = Availability
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 42405aa..a27fb3c 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -29,6 +29,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 8185e7f..5415ed0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -9,6 +9,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index c15e129..8f47413 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -9,6 +9,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 8105460..5d19d06 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -7,6 +7,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index d50a54e..743c4b5 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index fb45e35..772c4e4 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -6,6 +6,9 @@
## http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
##
####################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index e929386..03dfa4e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 081a9a2..3b35252 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -48,7 +48,7 @@ var ChartContext = function (chartId, chartHeight, metricsData, xAxisLabel, char
this.chartSelection = this.chartHandle + " svg";
},
-AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverStartLabel, hoverEndLabel, hoverBarLabel, availabilityLabel, chartHoverTimeFormat, chartHoverDateFormat) {
+AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverStartLabel, hoverBarLabel, availabilityLabel, chartHoverTimeFormat, chartHoverDateFormat, chartTitle, chartUpLabel, chartDownLabel) {
"use strict";
if (!(this instanceof AvailChartContext)) {
throw new Error("AvailChartContext function cannot be called as a function.")
@@ -60,10 +60,12 @@ AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverSta
this.dateLabel = dateLabel;
this.timeLabel = timeLabel;
this.hoverStartLabel = hoverStartLabel;
- this.hoverEndLabel = hoverEndLabel;
this.hoverBarLabel = hoverBarLabel;
this.hoverBarAvailabilityLabel = availabilityLabel;
this.chartHoverTimeFormat = chartHoverTimeFormat;
this.chartHoverDateFormat = chartHoverDateFormat;
+ this.chartTitle = chartTitle;
+ this.chartDownLabel = chartDownLabel;
+ this.chartUpLabel = chartUpLabel;
};
commit 59df0f08367521576187063a6bbafaa6ba0be9c2
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 08:45:18 2013 -0700
Make x-axis more readable on Safari, IE. These browsers even though they are using the same SVG fonts, render wider fonts showing up as labels running into one another. Reduced the clutter on the x-axis for increased readability.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index e38df39..f0db5a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -162,7 +162,7 @@ public class AvailabilityOverUnderGraphType {
xAxis = $wnd.d3.svg.axis()
.scale(timeScale)
- .ticks(12)
+ .ticks(8)
.tickSize(13, 0, 0)
.orient("bottom"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index bf08615..4d71192 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -129,13 +129,8 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
else {
console.log("Using Large Charts Profile");
// we use the width already defined above
- if(isIEBrowserGreaterThanOrEqualTo(9)){
- xTicks = 8;
- xTickSubDivide = 5;
- }else {
- xTicks = 12;
- xTickSubDivide = 5;
- }
+ xTicks = 8;
+ xTickSubDivide = 5;
chartData = chartContext.data;
}
commit c8bbd8b0c5dcfa51a2d653a95bc83d73d80178be
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 08:30:08 2013 -0700
[BZ 960521] Globally uncaught exception on clicking on resource name link on IE9.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 4e6a0ce..e38df39 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -215,7 +215,7 @@ public class AvailabilityOverUnderGraphType {
}
else {
// should not ever happen, but...
- console.warn("AvailabilityType not valid.");
+ console.log("AvailabilityType not valid.");
return "#000"; //black
}
},
@@ -318,13 +318,11 @@ public class AvailabilityOverUnderGraphType {
return {
// Public API
- draw: function (chartContext) {
+ draw: function (availChartContext) {
"use strict";
- console.info("AvailabilityChart");
- //console.time("availabilityChart");
+ console.log("AvailabilityChart");
drawBars(availChartContext);
createHovers();
- //console.timeEnd("availabilityChart");
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index 15f400d..bf08615 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -38,7 +38,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
*/
@Override
public native void drawJsniChart() /*-{
- //console.log("Draw Stacked Bar jsni chart");
+ console.log("Draw Stacked Bar jsni chart");
var global = this,
// create a chartContext object (from rhq.js) with the data required to render to a chart
@@ -120,14 +120,14 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
// if window is too small server up small chart
if (useSmallCharts()) {
- //console.log("Using Small Charts Profile for width: "+getChartWidth());
+ console.log("Using Small Charts Profile for width: "+getChartWidth());
width = 250;
xTicks = 3;
xTickSubDivide = 2;
chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
}
else {
- //console.log("Using Large Charts Profile");
+ console.log("Using Large Charts Profile");
// we use the width already defined above
if(isIEBrowserGreaterThanOrEqualTo(9)){
xTicks = 8;
@@ -613,8 +613,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
"use strict";
// Guard condition that can occur when a portlet has not been configured yet
if (chartContext.data.length > 0) {
- //console.info("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
- //console.time("chart");
+ console.log("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
determineScale();
createHeader(chartContext.chartTitle);
@@ -624,11 +623,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
createXandYAxes();
createAvgLines();
if (oobMax > 0) {
- //console.info("OOB Data Exists!");
+ console.log("OOB Data Exists!");
createOOBLines();
}
createHovers(chartContext);
- //console.timeEnd("chart");
}
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 27c4cc0..081a9a2 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -2,29 +2,9 @@
* Charting Javascript Functions.
*/
-// Avoid `console` errors in browsers that lack a console.
-(function() {
- var method;
- var noop = function () {};
- var methods = [
- 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
- 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
- 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
- 'timeStamp', 'trace', 'warn'
- ];
- var length = methods.length;
- var console = (window.console = window.console || {});
-
- while (length--) {
- method = methods[length];
-
- // Only stub undefined methods.
- if (!console[method]) {
- console[method] = noop;
- }
- }
-} ());
-
+// Handle browsers not supporting console object
+if (!window.console) window.console = {};
+if (!window.console.log) window.console.log = function () { };
/**
* ChartContext Constructor Object
commit db8f9686b96e2e3c44e61162b1a0d2d388fc59e9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 13:48:42 2013 +0200
BZ 960529 - check for non-existing resources when obtaining availability
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 4e00625..3e1d195 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -338,6 +338,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiParam(value="Start time", defaultValue = "30 days ago") @QueryParam("start") long start,
@ApiParam(value="End time", defaultValue = "Now") @QueryParam("end") long end,
@Context HttpHeaders headers) {
+
+ // Vaildate it the resource exists
+ fetchResource(resourceId);
+
if (end==0)
end = System.currentTimeMillis();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 1dee0f1..c71bbd8 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -499,6 +499,22 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testCreateChildForUnknownParent() throws Exception {
+
+ given()
+ .body("{\"value\":\"CPU\"}") // Type of new resource
+ .header("Content-Type", "application/json")
+ .header("Accept", "application/json")
+ .pathParam("name", "test")
+ .queryParam("plugin", "Platforms")
+ .queryParam("parentId", 321)
+ .expect()
+ .statusCode(404)
+ .log().ifError()
+ .when().post("/resource/{name}");
+ }
+
+ @Test
public void testAlertsForResource() throws Exception {
given()
.header("Accept", "application/json")
@@ -521,6 +537,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testSchedulesForUnknownResource() throws Exception {
+ given()
+ .header("Accept", "application/json")
+ .pathParam("id", 123)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/schedules");
+ }
+
+ @Test
public void testAvailabilityForResourceJson() throws Exception {
given()
.header(acceptJson)
@@ -532,6 +559,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAvailabilityForUnknownResource() throws Exception {
+ given()
+ .header(acceptJson)
+ .pathParam("id", 532)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/availability");
+ }
+
+ @Test
public void testAvailabilityForResourceXml() throws Exception {
given()
.header(acceptXml)
@@ -554,6 +592,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAvailabilityHistoryForUnknownResource() throws Exception {
+ given()
+ .header(acceptJson)
+ .pathParam("id", -42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/availability/history");
+ }
+
+ @Test
public void testAvailabilityHistoryForResourceXml() throws Exception {
given()
.header(acceptXml)
commit 17c3db8f19d0b70a6f0d910450523c245cd6f8b9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 09:17:48 2013 +0200
Code cleanup and improvements for the REST-api
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 2746823..7a198bd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -81,21 +81,21 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@SuppressWarnings("unchecked")
public class AbstractRestBean {
- Log log = LogFactory.getLog(getClass().getName());
+ protected Log log = LogFactory.getLog(getClass().getName());
- static private final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
+ private static final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
@javax.annotation.Resource( name = "ISPN")
- protected CacheContainer container;
+ private CacheContainer container;
protected Cache<CacheKey, Object> cache;
/** Subject of the caller that gets injected via {@link SetCallerInterceptor} */
protected Subject caller;
@EJB
- ResourceManagerLocal resMgr;
+ protected ResourceManagerLocal resMgr;
@EJB
- ResourceGroupManagerLocal resourceGroupManager;
+ protected ResourceGroupManagerLocal resourceGroupManager;
@PostConstruct
public void start() {
@@ -116,15 +116,15 @@ public class AbstractRestBean {
freemarker.template.Configuration config = new freemarker.template.Configuration();
// XXX fall-over to ClassTL after failure in FTL seems not to work
- // FileTemplateLoader ftl = new FileTemplateLoader(new File("src/main/resources"));
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "/rest_templates/");
TemplateLoader[] loaders = new TemplateLoader[] { ctl };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
config.setTemplateLoader(mtl);
- if (!templateName.endsWith(".ftl"))
+ if (!templateName.endsWith(".ftl")) {
templateName = templateName + ".ftl";
+ }
Template template = config.getTemplate(templateName);
StringWriter out = new StringWriter();
@@ -171,8 +171,9 @@ public class AbstractRestBean {
CacheValue value = (CacheValue) cache.get(key);
+ boolean debugEnabled = log.isDebugEnabled();
if (null != value) {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Hit for " + key);
}
@@ -180,12 +181,12 @@ public class AbstractRestBean {
o = value.getValue();
} else {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Hit ignored, caller " + caller.toString() + " not found");
}
}
} else {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Miss for " + key);
}
}
@@ -351,8 +352,9 @@ public class AbstractRestBean {
Resource parent = res.getParentResource();
if (parent != null) {
rwt.setParentId(parent.getId());
- } else
+ } else {
rwt.setParentId(0);
+ }
rwt.setAncestry(res.getAncestry());
@@ -429,8 +431,9 @@ public class AbstractRestBean {
protected ResourceGroup fetchGroup(int groupId, boolean requireCompatible) {
ResourceGroup resourceGroup;
resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
- if (resourceGroup == null)
+ if (resourceGroup == null) {
throw new StuffNotFoundException("Group with id " + groupId);
+ }
if (requireCompatible) {
if (resourceGroup.getGroupCategory() != GroupCategory.COMPATIBLE) {
throw new BadArgumentException("Group with id " + groupId,"it is no compatible group");
@@ -445,8 +448,9 @@ public class AbstractRestBean {
gr.setId(group.getId());
gr.setCategory(group.getGroupCategory());
gr.setRecursive(group.isRecursive());
- if (group.getGroupDefinition()!=null)
+ if (group.getGroupDefinition()!=null) {
gr.setDynaGroupDefinitionId(group.getGroupDefinition().getId());
+ }
gr.setExplicitCount(group.getExplicitResources().size());
gr.setImplicitCount(group.getImplicitResources().size());
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
@@ -526,16 +530,6 @@ public class AbstractRestBean {
return ms;
}
- Configuration mapToConfiguration(Map<String,Object> in) {
- Configuration config = new Configuration();
- for (Map.Entry<String,Object> entry : in.entrySet()) {
- config.put(new PropertySimple(entry.getKey(),entry.getValue())); // TODO honor more types
- }
-
- return config;
-
- }
-
/**
* Set the caching header on the response
* @param builder Response builder to put the caching header on
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 06bc8ae..d203cd3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -106,22 +106,22 @@ import org.rhq.enterprise.server.rest.domain.Link;
public class AlertDefinitionHandlerBean extends AbstractRestBean {
@EJB
- AlertDefinitionManagerLocal alertDefinitionManager;
+ private AlertDefinitionManagerLocal alertDefinitionManager;
@EJB
- AlertNotificationManagerLocal notificationMgr;
+ private AlertNotificationManagerLocal notificationMgr;
@EJB
- AlertConditionManagerLocal conditionMgr;
+ private AlertConditionManagerLocal conditionMgr;
@EJB
- AlertManagerLocal alertManager;
+ private AlertManagerLocal alertManager;
@EJB
- ResourceGroupManagerLocal resourceGroupMgr;
+ private ResourceGroupManagerLocal resourceGroupMgr;
@EJB
- ResourceTypeManagerLocal resourceTypeMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
@@ -169,8 +169,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@Context Request request, @Context UriInfo uriInfo) {
AlertDefinition def = alertDefinitionManager.getAlertDefinition(caller, definitionId);
- if (def==null)
+ if (def==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId );
+ }
EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
@@ -285,8 +286,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@Context UriInfo uriInfo) {
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,definitionId);
- if (definition==null)
+ if (definition==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId);
+ }
definition = new AlertDefinition(definition); // detach
@@ -302,10 +304,12 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
// Set the recovery id if such a definition exists at all
if (definitionRest.getRecoveryId()>0) {
AlertDefinition recoveryDef = alertDefinitionManager.getAlertDefinition(caller,definitionRest.getRecoveryId());
- if (recoveryDef!=null)
+ if (recoveryDef!=null) {
definition.setRecoveryId(definitionRest.getRecoveryId());
- else
+ }
+ else {
throw new StuffNotFoundException("Alert to recover with id " + definitionRest.getRecoveryId());
+ }
}
@@ -348,34 +352,24 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < vals.length ; i++) {
builder.append(vals[i].name());
- if (i < vals.length-1)
+ if (i < vals.length-1) {
builder.append(", ");
+ }
}
throw new BadArgumentException("dampening category","Allowed values are: " + builder.toString());
}
AlertDampening dampening = new AlertDampening(dampeningCategory);
- if (adr.getDampeningCount()!=null) {
- if (adr.getDampeningCount().contains(" ")) {
- String tmp = adr.getDampeningCount().trim();
- int num = Integer.parseInt(tmp.substring(0,tmp.indexOf(' ')));
- tmp = tmp.substring(tmp.lastIndexOf(' ')).trim();
- dampening.setValue(num);
- dampening.setValueUnits(AlertDampening.TimeUnits.valueOf(tmp.toUpperCase()));
- }
- else {
- dampening.setValue(Integer.parseInt(adr.getDampeningCount()));
- }
- }
- if (adr.getDampeningPeriod()!=null) {
- if (adr.getDampeningPeriod().contains(" ")) {
- String tmp = adr.getDampeningPeriod().trim();
- int num = Integer.parseInt(tmp.substring(0,tmp.indexOf(' ')));
- tmp = tmp.substring(tmp.lastIndexOf(' ')).trim();
- dampening.setPeriod(num);
- dampening.setPeriodUnits(AlertDampening.TimeUnits.valueOf(tmp.toUpperCase()));
- }
- else {
- dampening.setPeriod(Integer.parseInt(adr.getDampeningPeriod()));
+ if (adr.getDampeningCount()>-1) {
+ dampening.setValue(adr.getDampeningCount());
+ }
+ if (adr.getDampeningPeriod()>0) {
+ dampening.setPeriod(adr.getDampeningPeriod());
+ try {
+ if (adr.getDampeningUnit()!=null) {
+ dampening.setPeriodUnits(AlertDampening.TimeUnits.valueOf(adr.getDampeningUnit().toUpperCase()));
+ }
+ } catch (Exception e) {
+ throw new BadArgumentException("dampenign unit", "Allowed values are MINUTES,HOURS,DAYS, WEEKS");
}
}
@@ -439,8 +433,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
definition2 = entityManager.find(AlertDefinition.class,definitionId);
AlertCondition condition=null;
for (AlertCondition c: definition2.getConditions()) {
- if (c.getId() == conditionId)
+ if (c.getId() == conditionId) {
condition=c;
+ }
}
definition2.getConditions().remove(condition);
@@ -522,8 +517,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The id of the condition to retrieve") @PathParam("cid") int conditionId) {
AlertCondition condition = conditionMgr.getAlertConditionById(conditionId);
- if (condition==null)
+ if (condition==null) {
throw new StuffNotFoundException("No condition with id " + conditionId);
+ }
AlertConditionRest acr = conditionToConditionRest(condition);
return Response.ok(acr).build();
@@ -565,8 +561,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
AlertConditionRest result = conditionToConditionRest(createdCondition);
Response.ResponseBuilder builder;
- if (isCreate)
+ if (isCreate) {
builder = Response.created(uri);
+ }
else {
builder = Response.ok();
builder.location(uri);
@@ -583,8 +580,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The id of the notification definition to retrieve") @PathParam("nid") int notificationId) {
AlertNotification notification = notificationMgr.getAlertNotification(caller,notificationId);
- if (notification==null)
+ if (notification==null) {
throw new StuffNotFoundException("No notification with id " + notificationId);
+ }
AlertNotificationRest anr = notificationToNotificationRest(notification);
return Response.ok(anr).build();
@@ -618,8 +616,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The updated notification definition to use") AlertNotificationRest notificationRest) {
AlertNotification notification = notificationMgr.getAlertNotification(caller,notificationId);
- if (notification==null)
+ if (notification==null) {
throw new StuffNotFoundException("No notification with id " + notificationId);
+ }
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,notification.getAlertDefinition().getId());
@@ -634,8 +633,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
List<AlertNotification> notifications = definition.getAlertNotifications();
int newNotifId = 0;
for (AlertNotification n : notifications) {
- if (n.getSenderName().equals(notification.getSenderName()))
+ if (n.getSenderName().equals(notification.getSenderName())) {
newNotifId = n.getId();
+ }
}
AlertNotification result = notificationMgr.getAlertNotification(caller,newNotifId);
@@ -667,8 +667,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
// Now check if the definition exists as well
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,definitionId);
- if (definition==null)
+ if (definition==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId);
+ }
// definition and sender are valid, continue
int existingNotificationCount = definition.getAlertNotifications().size();
@@ -816,10 +817,13 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
adr.setDampeningCategory(dampening.getCategory().name());
AlertDampening.TimeUnits units = dampening.getValueUnits();
String s = units != null ? " " + units.name() : "";
- adr.setDampeningCount(dampening.getValue() + s);
+ adr.setDampeningCount(dampening.getValue());
units = dampening.getPeriodUnits();
s = units != null ? " " + units.name() : "";
- adr.setDampeningPeriod(dampening.getPeriod() + s);
+ adr.setDampeningPeriod(dampening.getPeriod());
+ if (dampening.getPeriodUnits()!=null) {
+ adr.setDampeningUnit(dampening.getPeriodUnits().name());
+ }
if (def.getResource()!=null) {
adr.getLinks().add(createUILink(uriInfo,UILinkTemplate.RESOURCE_ALERT_DEF,def.getResource().getId(),adr.getId()));
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 0a37a9d..4c80bd1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -79,10 +79,8 @@ import org.rhq.enterprise.server.rest.domain.*;
@Interceptors(SetCallerInterceptor.class)
public class AlertHandlerBean extends AbstractRestBean {
-// private final Log log = LogFactory.getLog(AlertHandlerBean.class);
-
@EJB
- AlertManagerLocal alertManager;
+ private AlertManagerLocal alertManager;
@GZIP
@@ -107,10 +105,12 @@ public class AlertHandlerBean extends AbstractRestBean {
if (resourceId!=null && definitionId!=null) {
throw new BadArgumentException("At most one of 'resourceId' and 'definitionId' may be given");
}
- if (size==0)
+ if (size==0) {
throw new BadArgumentException("size","Must not be 0");
- if (page<1)
+ }
+ if (page<1) {
throw new BadArgumentException("page","Must be >=1");
+ }
AlertCriteria criteria = new AlertCriteria();
@@ -119,8 +119,9 @@ public class AlertHandlerBean extends AbstractRestBean {
pageControl.setPageNumber(page);
criteria.setPageControl(pageControl);
}
- else
+ else {
criteria.setPaging(page-1, size); // TODO implement linking to next page
+ }
if (since!=null) {
criteria.addFilterStartTime(since);
@@ -335,8 +336,9 @@ public class AlertHandlerBean extends AbstractRestBean {
AlertCriteria criteria = new AlertCriteria();
criteria.addFilterId(id);
List<Alert> alerts = alertManager.findAlertsByCriteria(caller,criteria);
- if (alerts.isEmpty())
+ if (alerts.isEmpty()) {
throw new StuffNotFoundException("Alert with id " + id);
+ }
return alerts.get(0);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
index 07b2a1c..1099679 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
@@ -43,9 +43,9 @@ import org.rhq.enterprise.server.rest.domain.RHQErrorWrapper;
public class CustomExceptionMapper implements ExceptionMapper<Exception> {
@Context
- HttpHeaders httpHeaders;
+ private HttpHeaders httpHeaders;
- Log log = LogFactory.getLog(getClass().getName());
+ private Log log = LogFactory.getLog(getClass().getName());
@Override
public Response toResponse(Exception e) {
@@ -53,24 +53,25 @@ public class CustomExceptionMapper implements ExceptionMapper<Exception> {
Response.ResponseBuilder builder;
Response.Status status;
- if (e instanceof StuffNotFoundException)
+ if (e instanceof StuffNotFoundException) {
status =Response.Status.NOT_FOUND;
- else if (e instanceof ResourceNotFoundException)
+ } else if (e instanceof ResourceNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ResourceGroupNotFoundException)
+ } else if (e instanceof ResourceGroupNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ResourceTypeNotFoundException)
+ } else if (e instanceof ResourceTypeNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ParameterMissingException)
+ } else if (e instanceof ParameterMissingException) {
status = Response.Status.NOT_ACCEPTABLE;
- else if (e instanceof BadArgumentException)
+ } else if (e instanceof BadArgumentException) {
status = Response.Status.NOT_ACCEPTABLE;
- else if (e instanceof PermissionException)
+ } else if (e instanceof PermissionException) {
status = Response.Status.FORBIDDEN;
- else if (e instanceof EJBException && e.getCause()!=null && e.getCause() instanceof IllegalArgumentException)
+ } else if (e instanceof EJBException && e.getCause()!=null && e.getCause() instanceof IllegalArgumentException) {
status = Response.Status.NOT_ACCEPTABLE;
- else
+ } else {
status = Response.Status.SERVICE_UNAVAILABLE;
+ }
builder = Response.status(status);
String message = e.getMessage();
@@ -93,8 +94,9 @@ public class CustomExceptionMapper implements ExceptionMapper<Exception> {
log.debug(e.getMessage());
mediaType = MediaType.TEXT_PLAIN_TYPE;
}
- if (mediaType.getType().equals("text") && mediaType.getSubtype().equals("csv"))
+ if (mediaType.getType().equals("text") && mediaType.getSubtype().equals("csv")) {
mediaType = MediaType.TEXT_PLAIN_TYPE;
+ }
if (mediaType.equals(MediaType.TEXT_PLAIN_TYPE)) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index ccfed9f..8bc2cb9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -47,6 +47,8 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import com.wordnik.swagger.annotations.ApiError;
+import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
@@ -69,13 +71,17 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.core.domain.util.StringUtils;
+import org.rhq.enterprise.server.operation.OperationDefinitionNotFoundException;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceNotFoundException;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
import org.rhq.enterprise.server.rest.domain.OperationHistoryRest;
import org.rhq.enterprise.server.rest.domain.OperationRest;
import org.rhq.enterprise.server.rest.domain.SimplePropDef;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
/**
* Deal with operations
@@ -88,32 +94,31 @@ import org.rhq.enterprise.server.rest.domain.SimplePropDef;
public class OperationsHandlerBean extends AbstractRestBean {
@EJB
- OperationManagerLocal opsManager;
+ private OperationManagerLocal opsManager;
@EJB
- ResourceManagerLocal resourceManager;
+ private ResourceManagerLocal resourceManager;
@GET
@Path("definition/{id}")
@Cache(maxAge = 1200)
@ApiOperation("Retrieve a single operation definition by its id")
public Response getOperationDefinition(
- @ApiParam("Id of the definition to retrieve") @PathParam("id") int definitionId,
- @ApiParam("Id of a resource that supports this operation") @QueryParam("resourceId") Integer resourceId,
- @Context UriInfo uriInfo,
- @Context Request request,
- @Context HttpHeaders httpHeaders) {
-
-
+ @ApiParam("Id of the definition to retrieve") @PathParam("id") int definitionId,
+ @ApiParam("Id of a resource that supports this operation") @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request) {
OperationDefinition def;
def = getFromCache(definitionId, OperationDefinition.class);
if (def==null) {
- def = opsManager.getOperationDefinition(caller,definitionId);
- if (def==null)
- throw new StuffNotFoundException("OperationDefinition with id " + definitionId);
- else
+ try {
+ def = opsManager.getOperationDefinition(caller,definitionId);
putToCache(definitionId,OperationDefinition.class,def);
+ }
+ catch (OperationDefinitionNotFoundException ode) {
+ throw new StuffNotFoundException("Operation definition with id " + definitionId);
+ }
}
EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
@@ -145,43 +150,27 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
- private void copyParamsForDefinition(OperationDefinition def, OperationDefinitionRest odr) {
- ConfigurationDefinition cd = def.getParametersConfigurationDefinition();
- if (cd==null)
- return;
-
- for (Map.Entry<String,PropertyDefinition> entry : cd.getPropertyDefinitions().entrySet()) {
- PropertyDefinition pd = entry.getValue();
- if (pd instanceof PropertyDefinitionSimple) {
- PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
- SimplePropDef prop = new SimplePropDef();
- prop.setName(pds.getName());
- prop.setRequired(pds.isRequired());
- prop.setType(pds.getType());
- prop.setDefaultValue(pds.getDefaultValue());
- odr.addParam(prop);
- }
- log.debug("copyParams: " + pd.getName() + " not yet supported");
- }
- }
-
@GZIP
@GET
@Path("definitions")
@Cache(maxAge = 1200)
@ApiOperation("List all operation definitions for a resource")
public Response getOperationDefinitions(
- @ApiParam(value = "Id of the resource",required = true) @QueryParam("resourceId") Integer resourceId,
- @Context UriInfo uriInfo,
- @Context Request request,
- @Context HttpHeaders httpHeaders) {
+ @ApiParam(value = "Id of the resource", required = true) @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request) {
- if (resourceId == null)
+ if (resourceId == null) {
throw new ParameterMissingException("resourceId");
+ }
- Resource res =resourceManager.getResource(caller,resourceId);
- if(res==null)
+ Resource res;
+ try {
+ res = resourceManager.getResource(caller,resourceId);
+ }
+ catch (ResourceNotFoundException rnfe) {
throw new StuffNotFoundException("resource with id " + resourceId);
+ }
ResourceType resourceType = res.getResourceType();
@@ -226,16 +215,24 @@ public class OperationsHandlerBean extends AbstractRestBean {
@ApiParam(value = "Id of the resource", required = true) @QueryParam("resourceId") Integer resourceId,
@Context UriInfo uriInfo) {
- if (resourceId == null)
+ if (resourceId == null) {
throw new ParameterMissingException("resourceId");
+ }
- Resource res =resourceManager.getResource(caller,resourceId);
- if(res==null)
+ try {
+ // Check if the resource exists at all
+ resourceManager.getResource(caller,resourceId);
+ }
+ catch (ResourceNotFoundException rnfe) {
throw new StuffNotFoundException("resource with id " + resourceId);
+ }
- OperationDefinition opDef = opsManager.getOperationDefinition(caller,definitionId);
- if (opDef==null) {
+ OperationDefinition opDef;
+ try {
+ opDef = opsManager.getOperationDefinition(caller,definitionId);
+ }
+ catch (OperationDefinitionNotFoundException odnfe) {
throw new StuffNotFoundException("Operation definition with id " + definitionId);
}
OperationRest operationRest = new OperationRest(resourceId,definitionId);
@@ -266,9 +263,11 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Path("{id}")
@ApiOperation("Return a (draft) operation")
public Response getOperation(@ApiParam("Id of the operation to retrieve") @PathParam("id") int operationId) {
+
OperationRest op = getFromCache(operationId,OperationRest.class);
- if (op==null)
+ if (op==null) {
throw new StuffNotFoundException("Operation with id " + operationId);
+ }
return Response.ok(op).build();
}
@@ -277,20 +276,40 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Path("{id}")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@ApiOperation("Update a (draft) operation. If the state is set to 'ready', the operation will be scheduled")
+ @ApiErrors({
+ @ApiError(code = 404, reason = "No draft operation with the passed id exists"),
+ @ApiError(code = 406, reason = "Draft was set for scheduling, but parameters failed validation"),
+ @ApiError(code = 200, reason = "Update was successful, operation was scheduled if requested" )
+ }
+ )
public Response updateOperation(@ApiParam("Id of the operation to update") @PathParam("id") int operationId,
OperationRest operation, @Context UriInfo uriInfo) {
- if (!operation.isReadyToSubmit() && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
- // TODO check all the required parameters for presence before allowing to submit
- operation.setReadyToSubmit(true);
+ OperationRest op = getFromCache(operationId,OperationRest.class);
+ if (op==null) {
+ throw new StuffNotFoundException("Operation with id " + operationId);
}
+
+ Configuration parameters = ConfigurationHelper.mapToConfiguration(operation.getParams());
+
if (operation.isReadyToSubmit()) {
- // todo check params
- // submit
+ OperationDefinition opDef = opsManager.getOperationDefinition(caller,operation.getDefinitionId());
- Configuration parameters = mapToConfiguration(operation.getParams());
+ // Validate parameters
+ ConfigurationDefinition parameterDefinition = opDef.getParametersConfigurationDefinition();
+ List<String> errorMessages = ConfigurationHelper.checkConfigurationWrtDefinition(parameters, parameterDefinition);
+ if (errorMessages.size()>0) {
+ // Configuration is not ok
+ operation.setReadyToSubmit(false);
+ throw new BadArgumentException("Validation of parameters failed", StringUtils.getListAsString(errorMessages,", "));
+ }
+ }
+
+ if (operation.isReadyToSubmit()) {
+
+ // submit
ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,
parameters,"Test");
JobId jobId = new JobId(sched.getJobName(),sched.getJobGroup());
@@ -304,12 +323,12 @@ public class OperationsHandlerBean extends AbstractRestBean {
else {
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/operation/{id}");
- URI uri = uriBuilder.build(operation.getId());
+ URI uri = uriBuilder.build(operationId);
Link editLink = new Link("edit",uri.toString());
operation.addLink(editLink);
}
// Update item in cache
- putToCache(operation.getId(),OperationRest.class,operation);
+ putToCache(operationId,OperationRest.class,operation);
Response.ResponseBuilder builder = Response.ok(operation);
return builder.build();
}
@@ -381,8 +400,9 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
- if (resourceId>0)
+ if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
+ }
criteria.addSortEndTime(PageOrdering.DESC);
@@ -424,30 +444,41 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
-
+ /**
+ * Create a REST-object from the passed operation history
+ * @param history History object to convert
+ * @param uriInfo URI info of the incoming request, used to create links
+ * @return a populated OperationHistoryRest object
+ */
private OperationHistoryRest historyToHistoryRest(ResourceOperationHistory history, UriInfo uriInfo) {
String status;
- if (history.getStatus()==null)
+ if (history.getStatus()==null) {
status = " - no information yet -";
- else
+ }
+ else {
status = history.getStatus().getDisplayName();
+ }
OperationHistoryRest hist = new OperationHistoryRest();
hist.setStatus(status);
- if (history.getResource()!=null)
+ if (history.getResource()!=null) {
hist.setResourceName(history.getResource().getName());
+ }
hist.setOperationName(history.getOperationDefinition().getName());
hist.lastModified(history.getModifiedTime());
- if (history.getErrorMessage()!=null)
+ if (history.getErrorMessage()!=null) {
hist.setErrorMessage(history.getErrorMessage());
+ }
if (history.getResults()!=null) {
Configuration results = history.getResults();
for (Property p : results.getProperties()) {
String val;
- if (p instanceof PropertySimple)
+ if (p instanceof PropertySimple) {
val = ((PropertySimple)p).getStringValue();
- else
+ }
+ else {
val = p.toString();
+ }
hist.getResult().put(p.getName(),val);
}
}
@@ -465,4 +496,34 @@ public class OperationsHandlerBean extends AbstractRestBean {
return hist;
}
+ /**
+ * Copies the parameters of an OperationDefinition into to an object that can be
+ * returned to a REST-client, so that this knows which fields are to be filled in,
+ * of which type they are and which ones are required
+ * @param def OperationsDefinition to "copy"
+ * @param definitionRest The definition to fill in
+ */
+ private void copyParamsForDefinition(OperationDefinition def, OperationDefinitionRest definitionRest) {
+ ConfigurationDefinition cd = def.getParametersConfigurationDefinition();
+ if (cd==null) {
+ return;
+ }
+
+ for (Map.Entry<String,PropertyDefinition> entry : cd.getPropertyDefinitions().entrySet()) {
+ PropertyDefinition pd = entry.getValue();
+ if (pd instanceof PropertyDefinitionSimple) {
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+ SimplePropDef prop = new SimplePropDef();
+ prop.setName(pds.getName());
+ prop.setRequired(pds.isRequired());
+ prop.setType(pds.getType());
+ prop.setDefaultValue(pds.getDefaultValue());
+ definitionRest.addParam(prop);
+ }
+ log.debug("copyParams: " + pd.getName() + " not yet supported");
+ }
+ }
+
+
+
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
index 16fd62f..d3f3f50 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
@@ -1,9 +1,12 @@
package org.rhq.enterprise.server.rest;
+import javax.ejb.ApplicationException;
+
/**
* Exception thrown if (Query) Parameters are missing
* @author Heiko W. Rupp
*/
+@ApplicationException(rollback = false, inherited = true)
public class ParameterMissingException extends RuntimeException {
public ParameterMissingException(String what) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
index 1377be4..1b563da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
@@ -76,25 +76,25 @@ import org.rhq.enterprise.server.rest.reporting.SuspectMetricLocal;
public class ReportsHandlerBean extends AbstractRestBean {
@EJB
- AlertDefinitionLocal alertDefinitionLocal;
+ private AlertDefinitionLocal alertDefinitionLocal;
@EJB
- ConfigurationHistoryLocal configurationHistoryLocal;
+ private ConfigurationHistoryLocal configurationHistoryLocal;
@EJB
- DriftComplianceLocal driftComplianceLocal;
+ private DriftComplianceLocal driftComplianceLocal;
@EJB
- InventorySummaryLocal inventorySummaryLocal;
+ private InventorySummaryLocal inventorySummaryLocal;
@EJB
- PlatformUtilizationLocal platformUtilizationLocal;
+ private PlatformUtilizationLocal platformUtilizationLocal;
@EJB
- RecentAlertLocal recentAlertLocal;
+ private RecentAlertLocal recentAlertLocal;
@EJB
- RecentDriftLocal recentDriftLocal;
+ private RecentDriftLocal recentDriftLocal;
@EJB
- RecentOperationsLocal recentOperationsLocal;
+ private RecentOperationsLocal recentOperationsLocal;
@EJB
- SuspectMetricLocal suspectMetricLocal;
+ private SuspectMetricLocal suspectMetricLocal;
- String[] reports = {
+ private String[] reports = {
"alertDefinitions",
"configurationHistory",
"driftCompliance",
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 1c2b516..4e00625 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -108,6 +108,7 @@ import org.rhq.enterprise.server.rest.domain.MetricSchedule;
import org.rhq.enterprise.server.rest.domain.ResourceWithChildren;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
import org.rhq.enterprise.server.rest.domain.StringValue;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
/**
* Class that deals with getting data about resources
@@ -755,8 +756,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
if (resType==null)
throw new StuffNotFoundException("ResourceType with name [" + typeName + "] and plugin [" + plugin + "]");
- Configuration pluginConfig = mapToConfiguration(request.getPluginConfig());
- Configuration deployConfig = mapToConfiguration(request.getResourceConfig());
+ Configuration pluginConfig = ConfigurationHelper.mapToConfiguration(request.getPluginConfig());
+ Configuration deployConfig = ConfigurationHelper.mapToConfiguration(request.getResourceConfig());
String packageName = DEFAULT_PACKAGE;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
index 3aded78..612b3f7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
@@ -51,7 +51,7 @@ import org.rhq.enterprise.server.rest.domain.Link;
@Stateless
public class RootHandlerBean extends AbstractRestBean {
- String[] roots = { // rel, target
+ private String[] roots = { // rel, target
"platforms","resource/platforms",
"groups","group",
"dynaGroups","group/definitions",
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
index 3db8dc5..1da5411 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
@@ -52,10 +52,10 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
public class SetCallerInterceptor {
@Resource
- EJBContext ejbContext;
+ private EJBContext ejbContext;
@EJB
- SubjectManagerLocal subjectManager;
+ private SubjectManagerLocal subjectManager;
private SessionManager sessionManager = SessionManager.getInstance();
@@ -76,8 +76,9 @@ public class SetCallerInterceptor {
caller = subjectManager.getSubjectByName(p.getName());
}
- if (caller==null)
+ if (caller==null) {
throw new IllegalAccessException("No calling principal provided");
+ }
// Get Subject with a session
caller = sessionManager.put(caller);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
index 23bbd4b..a6c81b3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
@@ -55,9 +55,9 @@ public class StatusHandlerBean extends AbstractRestBean {
@EJB
- SystemInfoManagerLocal infoMgr;
+ private SystemInfoManagerLocal infoMgr;
@EJB
- ServerManagerLocal serverManager;
+ private ServerManagerLocal serverManager;
@GZIP
@ApiOperation(value="Retrieve the current configured state of the server along with some runtime information." +
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
index 9851425..cd57b67 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
@@ -74,8 +74,6 @@ import org.rhq.enterprise.server.rest.domain.UserRest;
@Stateless
public class UserHandlerBean extends AbstractRestBean {
- // private final Log log = LogFactory.getLog(UserHandlerBean.class);
-
/**
* List of favorite {@link org.rhq.core.domain.resource.Resource} id's, delimited by '|' characters. Default is "".
*/
@@ -88,10 +86,10 @@ public class UserHandlerBean extends AbstractRestBean {
public static final String GROUP_HEALTH_GROUPS = ".dashContent.grouphealth.groups";
@EJB
- SubjectManagerLocal subjectManager;
+ private SubjectManagerLocal subjectManager;
@EJB
- ResourceManagerLocal resourceManager;
+ private ResourceManagerLocal resourceManager;
@GZIP
@GET
@@ -112,10 +110,12 @@ public class UserHandlerBean extends AbstractRestBean {
ResourceWithType rwt = fillRWT(res, uriInfo);
ret.add(rwt);
} catch (Exception e) {
- if (e instanceof ResourceNotFoundException)
+ if (e instanceof ResourceNotFoundException) {
log.debug("Favorite resource with id " + id + " not found - not returning to the user");
- else
+ }
+ else {
log.warn("Retrieving resource with id " + id + " failed: " + e.getLocalizedMessage());
+ }
}
}
Response.ResponseBuilder builder;
@@ -151,11 +151,12 @@ public class UserHandlerBean extends AbstractRestBean {
ResourceGroup res = resourceGroupManager.getResourceGroup(caller, id);
GroupRest rwt = fillGroup(res, uriInfo);
ret.add(rwt);
- } catch (Exception e) {
- if (e instanceof ResourceGroupNotFoundException)
- log.debug("Favorite group with id " + id + " not found - not returning to the user");
- else
- log.warn("Retrieving group with id " + id + " failed: " + e.getLocalizedMessage());
+ }
+ catch (ResourceGroupNotFoundException e) {
+ log.debug("Favorite group with id " + id + " not found - not returning to the user");
+ }
+ catch (Exception e) {
+ log.warn("Retrieving group with id " + id + " failed: " + e.getLocalizedMessage());
}
}
Response.ResponseBuilder builder;
@@ -222,8 +223,8 @@ public class UserHandlerBean extends AbstractRestBean {
@Path("favorites/group/{id}")
@ApiOperation(value = "Remove a group from favorites")
public void removeResourceGroupFromFavorites(@ApiParam(name = "id", value = "Id of the group")
- @PathParam("id")
- int id) {
+ @PathParam("id") int id) {
+
Set<Integer> favIds = getGroupIdsForFavorites();
if (favIds.contains(id)) {
favIds.remove(id);
@@ -242,8 +243,9 @@ public class UserHandlerBean extends AbstractRestBean {
HttpHeaders headers) {
Subject subject = subjectManager.getSubjectByName(loginName);
- if (subject == null)
+ if (subject == null) {
throw new StuffNotFoundException("User with login " + loginName);
+ }
EntityTag eTag = new EntityTag(Long.toOctalString(subject.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
@@ -273,7 +275,8 @@ public class UserHandlerBean extends AbstractRestBean {
PropertySimple prop = conf.getSimple(RESOURCE_HEALTH_RESOURCES);
if (prop == null) {
conf.put(new PropertySimple(RESOURCE_HEALTH_RESOURCES, builder.toString()));
- } else {
+ }
+ else {
prop.setStringValue(builder.toString());
}
caller.setUserConfiguration(conf);
@@ -290,7 +293,8 @@ public class UserHandlerBean extends AbstractRestBean {
PropertySimple prop = conf.getSimple(GROUP_HEALTH_GROUPS);
if (prop == null) {
conf.put(new PropertySimple(GROUP_HEALTH_GROUPS, builder.toString()));
- } else {
+ }
+ else {
prop.setStringValue(builder.toString());
}
caller.setUserConfiguration(conf);
@@ -308,13 +312,22 @@ public class UserHandlerBean extends AbstractRestBean {
private Set<Integer> getGroupIdsForFavorites() {
Configuration conf = caller.getUserConfiguration();
- if (conf==null)
+ if (conf==null) {
return new HashSet<Integer>();
+ }
String favsString = conf.getSimpleValue(GROUP_HEALTH_GROUPS, "");
Set<Integer> favIds = getIdsFromFavString(favsString);
return favIds;
}
+ /**
+ * Parse the String with favorites.
+ * The list of favorites is stored in the server as a list
+ * of ids separated by a pipe '|' character.
+ *
+ * @param favsString String as stored in for the user
+ * @return Set of ids of the favorites
+ */
private Set<Integer> getIdsFromFavString(String favsString) {
Set<Integer> favIds = new TreeSet<Integer>();
if (!favsString.isEmpty()) {
@@ -326,13 +339,21 @@ public class UserHandlerBean extends AbstractRestBean {
return favIds;
}
+ /**
+ * Create the String with favorites to store for the user
+ * The list of favorites is stored in the server as a list
+ * of ids separated by a pipe '|' character
+ * @param favIds Set of favorite ids
+ * @return String representation
+ */
private StringBuilder buildFavStringFromSet(Set<Integer> favIds) {
StringBuilder builder = new StringBuilder();
Iterator<Integer> iter = favIds.iterator();
while (iter.hasNext()) {
builder.append(iter.next());
- if (iter.hasNext())
+ if (iter.hasNext()) {
builder.append('|');
+ }
}
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
index 2224732..f40d92c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
@@ -43,8 +43,9 @@ public class AlertDefinitionRest {
List<AlertConditionRest> conditions = new ArrayList<AlertConditionRest>();
List<AlertNotificationRest> notifications = new ArrayList<AlertNotificationRest>();
String dampeningCategory;
- String dampeningCount;
- String dampeningPeriod;
+ int dampeningCount;
+ int dampeningPeriod;
+ String dampeningUnit;
List<Link> links = new ArrayList<Link>();
@SuppressWarnings("unused")
@@ -138,24 +139,33 @@ public class AlertDefinitionRest {
this.dampeningCategory = dampeningCategory;
}
- @ApiProperty(value = "Number of occurrences of an alert (in a given period)")
- public String getDampeningCount() {
+ @ApiProperty(value = "Number of occurrences of an alert (in a given period). Valid values are > -1")
+ public int getDampeningCount() {
return dampeningCount;
}
- public void setDampeningCount(String dampeningCount) {
+ public void setDampeningCount(int dampeningCount) {
this.dampeningCount = dampeningCount;
}
@ApiProperty( value = "Period to check events. Only applicable for PARTIAL_COUNT, DURATION_COUNT, INVERSE_COUNT")
- public String getDampeningPeriod() {
+ public int getDampeningPeriod() {
return dampeningPeriod;
}
- public void setDampeningPeriod(String dampeningPeriod) {
+ public void setDampeningPeriod(int dampeningPeriod) {
this.dampeningPeriod = dampeningPeriod;
}
+ @ApiProperty( value = "Unit of the dampening period.",allowableValues = "MINUTES, HOURS, DAYS, WEEKS" )
+ public String getDampeningUnit() {
+ return dampeningUnit;
+ }
+
+ public void setDampeningUnit(String dampeningUnit) {
+ this.dampeningUnit = dampeningUnit;
+ }
+
public List<Link> getLinks() {
return links;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java
new file mode 100644
index 0000000..073966d
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java
@@ -0,0 +1,432 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.rest.helper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+
+/**
+ * Helper class to deal with configuration objects
+ * @author Heiko W. Rupp
+ */
+public class ConfigurationHelper {
+
+ /**
+ * Convert the passed map into a RHQ configuration object
+ * @param in Map with items to convert. Map.Entry.Key is the name of the property and Map.Entry.Value the value
+ * @return a new Configuration object
+ */
+ public static Configuration mapToConfiguration(Map<String, Object> in) {
+ Configuration config = new Configuration();
+ Set<String> mapKeys = in.keySet();
+ for (String mapKey : mapKeys) {
+ Object mapValue = in.get(mapKey);
+
+ if (mapValue instanceof Map) {
+ Map<String,Object> map = (Map<String, Object>) mapValue;
+ PropertyMap propertyMap = getPropertyMap(mapKey, map);
+ config.put(propertyMap);
+ }
+ else if (mapValue instanceof List) {
+ List<Object> objects = (List<Object>) mapValue;
+ PropertyList propertyList = getPropertyList(mapKey, objects);
+ config.put(propertyList);
+ }
+ else {
+ config.put(new PropertySimple(mapKey,mapValue));
+ }
+ }
+
+ return config;
+
+ }
+
+ public static Map<String,Object> configurationToMap(Configuration configuration, ConfigurationDefinition definition,
+ boolean strict) {
+
+ Map<String,Object> result = new HashMap<String, Object>();
+
+ if (configuration==null) {
+ return result;
+ }
+
+ if (configuration.getProperties().isEmpty()) {
+ return result;
+ }
+
+ for (Property property : configuration.getProperties()) {
+
+ String propertyName = property.getName();
+ PropertyDefinition propertyDefinition = definition.get(propertyName);
+ if (propertyDefinition==null) {
+ if (strict) {
+ throw new IllegalArgumentException("No definition for property " + propertyName + "found");
+ } else {
+ // no definition found and not strict, so skip the property
+ continue;
+ }
+ }
+
+ Object target = convertProperty(property, propertyDefinition, strict);
+ result.put(propertyName,target);
+ }
+
+ return result;
+ }
+
+ private static Object convertProperty(Property property, PropertyDefinition propertyDefinition, boolean strict) {
+ Object target;
+
+ if (property instanceof PropertyMap) {
+ PropertyMap propertyMap = (PropertyMap) property;
+ target = getInnerMap(propertyMap,(PropertyDefinitionMap) propertyDefinition, strict);
+ } else if (property instanceof PropertyList) {
+ PropertyList propertyList = (PropertyList) property;
+ target = getInnerList(propertyList, (PropertyDefinitionList)propertyDefinition, strict);
+ } else {
+ target= convertSimplePropertyValue((PropertySimple) property,
+ ((PropertyDefinitionSimple)propertyDefinition));
+ }
+ return target;
+ }
+
+ private static Map<String, Object> getInnerMap(PropertyMap propertyMap, PropertyDefinitionMap propertyDefinition,
+ boolean strict) {
+
+ Map<String, Property> map = propertyMap.getMap();
+ Map<String,Object> result = new HashMap<String, Object>(map.size());
+
+ Set<String> names = map.keySet();
+ for (String name : names ) {
+ Property property = map.get(name);
+ PropertyDefinition definition = propertyDefinition.get(name);
+
+ Object target = convertProperty(property,definition, strict);
+ result.put(name,target);
+ }
+
+ return result;
+ }
+
+ private static List<Object> getInnerList(PropertyList propertyList, PropertyDefinitionList definition,
+ boolean strict) {
+
+ List<Object> result = new ArrayList<Object>(propertyList.getList().size());
+
+ if (definition==null) {
+ if (strict) {
+ throw new IllegalArgumentException("No Definition exists for " + propertyList.getName());
+ } else {
+ return result;
+ }
+ }
+
+
+ PropertyDefinition memberDefinition = definition.getMemberDefinition();
+ for (Property property : propertyList.getList()) {
+ Object target = convertProperty(property,memberDefinition, strict);
+ result.add(target);
+ }
+
+ return result;
+ }
+
+ private static PropertyList getPropertyList(String propertyName, List<Object> objects) {
+ PropertyList propertyList = new PropertyList(propertyName);
+
+ Property target;
+ for (Object o : objects) {
+ if (o instanceof List) {
+ // Not sure if we actually support that at all inside RHQ
+ List list = (List) o;
+ target = getPropertyList(propertyName,list); // TODO propertyName?
+ } else if (o instanceof Map) {
+ Map map = (Map) o;
+ target = getPropertyMap(propertyName,map); // TODO propertyName?
+ } else {
+ target = new PropertySimple(propertyName,o);
+ }
+ propertyList.add(target);
+ }
+ return propertyList;
+ }
+
+ private static PropertyMap getPropertyMap(String propertyName, Map<String, Object> map) {
+ PropertyMap propertyMap = new PropertyMap(propertyName);
+ Set<String> keys = map.keySet();
+ for (String key : keys) {
+ Object value = map.get(key);
+ Property target;
+ if (value instanceof Map) {
+ target = getPropertyMap(key, (Map)value);
+ } else if (value instanceof List) {
+ target = getPropertyList(key, (List)value);
+ } else {
+ target = new PropertySimple(key,value);
+ }
+ propertyMap.put(target);
+ }
+ return propertyMap;
+ }
+
+ /**
+ * Convert the passed simple property into an object of a matching type. The
+ * type is determined with the help of the passed definition
+ * @param property Property to convert
+ * @param definition Definition of the Property
+ * @return Object with the correct type
+ */
+ public static Object convertSimplePropertyValue(PropertySimple property, PropertyDefinitionSimple definition) {
+
+ if (definition==null) {
+ throw new IllegalArgumentException("No definition provided");
+ }
+
+ if (property==null) {
+ return null;
+ }
+
+ PropertySimpleType type = definition.getType();
+ String val = property.getStringValue();
+
+ Object ret;
+
+ switch (type) {
+ case STRING:
+ ret= val;
+ break;
+ case INTEGER:
+ ret= Integer.valueOf(val);
+ break;
+ case BOOLEAN:
+ ret= Boolean.valueOf(val);
+ break;
+ case LONG:
+ ret= Long.valueOf(val);
+ break;
+ case FLOAT:
+ ret= Float.valueOf(val);
+ break;
+ case DOUBLE:
+ ret= Double.valueOf(val);
+ break;
+ default:
+ ret= val;
+ }
+ return ret;
+ }
+
+
+ /**
+ * Check that the passed configuration is valid wrt the passed definition
+ * @param configuration A Configuration to check
+ * @param definition A Definition to check the Configuration against
+ * @return List of validation failure messages. List is empty if no errors were found.
+ */
+ public static List<String> checkConfigurationWrtDefinition(Configuration configuration,
+ ConfigurationDefinition definition) {
+
+ List<String> messages = new ArrayList<String>();
+
+ if (configuration==null) {
+ messages.add("Configuration is null");
+
+ }
+
+ if (definition==null) {
+ messages.add("Definition is null");
+ }
+
+ if (configuration==null || definition==null) {
+ return messages;
+ }
+
+ // Basic validation is done, now have a look at the properties
+
+ for (PropertyDefinition propDef : definition.getPropertyDefinitions().values()) {
+ String name = propDef.getName();
+ Property property = configuration.get(name);
+
+ checkProperty(messages, propDef, property);
+ }
+
+
+ return messages;
+ }
+
+ /**
+ * Recursively check the passed property against the passed property definition
+ * @param messages Validation error messages are added here
+ * @param propertyDefinition The definition to check against
+ * @param property The property to check
+ */
+ private static void checkProperty(List<String> messages, PropertyDefinition propertyDefinition,
+ Property property) {
+
+ String name = propertyDefinition.getName();
+
+ // If a property is required and not present we can bail out early
+ if (propertyDefinition.isRequired() && property ==null) {
+ messages.add("Required property [" + name + "] not found");
+ return;
+ }
+
+ // If a property is not required and is null, it is fine either
+ if (!propertyDefinition.isRequired() && property==null) {
+ return;
+ }
+
+ // Check if the property and definition are of the same kind (simple, map, list)
+ boolean good = checkIfCompatible(propertyDefinition, property,messages);
+ // We only need to do this dance if the kinds are matching
+ if (good) {
+ if (property instanceof PropertySimple) {
+ checkDataTypeOfSimpleProperty((PropertyDefinitionSimple) propertyDefinition, (PropertySimple) property,
+ messages);
+ } else if (property instanceof PropertyList) {
+ PropertyList propertyList = (PropertyList) property;
+ PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
+ for (Property prop : propertyList.getList()) {
+ checkProperty(messages, propertyDefinitionList.getMemberDefinition(), prop);
+ }
+ } else if (property instanceof PropertyMap) {
+ PropertyMap propertyMap = (PropertyMap) property;
+ PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
+ for (Map.Entry<String,Property> entry : propertyMap.getMap().entrySet()) {
+ Property prop = entry.getValue();
+ PropertyDefinition definition = propertyDefinitionMap.get(name);
+ checkProperty(messages,definition,prop);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that for a Property that is defined with one of the non-string data types, the
+ * stored value is actually valid according to this data type.
+ * This also checks if a property is required, but its value is actually null.
+ *
+ * @param propDef Definition of the property, that contains the data type
+ * @param property The property to check
+ * @param messages Validation issues are added to this list.
+ */
+ private static void checkDataTypeOfSimpleProperty(PropertyDefinitionSimple propDef, PropertySimple property,
+ List<String> messages) {
+
+ String prefix = "Property [" + property.getName() + "] is ";
+ String val = property.getStringValue();
+
+ // If a property is not required and its value is null, we can just return
+ if (!propDef.isRequired() && property.getStringValue()==null) {
+ return;
+ }
+
+ // If a property is required and its value is null, we can just return
+ if (propDef.isRequired() && property.getStringValue()==null) {
+ messages.add(prefix + "required but was 'null'");
+ return;
+ }
+
+
+ switch (propDef.getType()) {
+ case DOUBLE:
+ try {
+ Double.parseDouble(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no double : " + val);
+ }
+ break;
+ case FLOAT:
+ float f;
+ try {
+ f = Float.parseFloat(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no float : " + val);
+ break;
+ }
+ if (f < Float.MIN_VALUE || f > Float.MAX_VALUE) {
+ messages.add(prefix + "no valid float : " + val);
+ }
+ break;
+ case INTEGER:
+ try {
+ Integer.parseInt(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no integer : " + val);
+ }
+ break;
+ case LONG:
+ try {
+ Long.parseLong(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no long : " + val);
+ }
+ break;
+ case BOOLEAN:
+ String s = val.toLowerCase();
+ if (!(s.equals("true") || s.equals("false"))) {
+ messages.add(prefix + "no boolean : " + val);
+ }
+ break;
+ default:
+ // Strings and long strings and directories and files
+ }
+ }
+
+ /**
+ * Check if the Kind of Definition and Property match. I.e. if a PropertyMap corresponds to a PropertyDefinitionMap
+ * @param propDef PropertyDefinition to match
+ * @param property Property to match with the definition
+ * @param messages List of messages to add validation errors to.
+ * @return true if the kinds are matching
+ */
+ private static boolean checkIfCompatible(final PropertyDefinition propDef, final Property property,
+ final List<String> messages) {
+
+ boolean good = false ;
+ if (propDef instanceof PropertyDefinitionSimple && property instanceof PropertySimple) {
+ good = true;
+ } else if (propDef instanceof PropertyDefinitionMap && property instanceof PropertyMap) {
+ good = true;
+ } else if (propDef instanceof PropertyDefinitionList && property instanceof PropertyList) {
+ good = true;
+ }
+ if (!good) {
+ String name = propDef.getName();
+ messages.add("The type of property for [" + name + "] does not match the definition");
+ }
+ return good;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
new file mode 100644
index 0000000..7e20630
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -0,0 +1,756 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.rhq.enterprise.server.configuration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.util.StringUtils;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
+
+/**
+ * Test the ConfigurationHelper class
+ * @author Heiko W. Rupp
+ */
+public class ConfigurationHelperTest {
+
+ @Test
+ public void testConvertSimpleMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2;
+
+ PropertySimple hello = config.getSimple("Hello");
+ assert hello !=null;
+ assert hello.getStringValue().equals("World");
+
+ PropertySimple qu = config.getSimple("Answer");
+ assert qu!=null;
+ Integer value = qu.getIntegerValue();
+ assert value !=null;
+ assert value ==42;
+ }
+
+ @Test
+ public void testConvertWithNestedMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(3);
+ map.put("Hello","World");
+ map.put("Answer",42);
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ map.put("Inner",inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop!=null;
+ assert prop instanceof PropertyMap : "Inner is no map";
+
+ PropertyMap pm = (PropertyMap) prop;
+ Map<String, Property> innerMap = pm.getMap();
+ assert innerMap.size()==1;
+
+ assert inner.containsKey("Foo");
+
+ }
+
+ @Test
+ public void testConvertListOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.add(inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop==null;
+
+ prop = config.get("list");
+ assert prop instanceof PropertyList : "list is no list";
+
+ PropertyList pl = (PropertyList) prop;
+ List<Property> propertyList = pl.getList();
+ assert propertyList.size()==1;
+ PropertyMap innerMapProperty = (PropertyMap) propertyList.get(0);
+
+ Map<String, Property> propertyMap = innerMapProperty.getMap();
+ assert propertyMap.size()==1;
+ Map<String,Property> innerMap = propertyMap;
+
+ assert innerMap.containsKey("Foo");
+ Property property = innerMapProperty.get("Foo");
+ assert property != null;
+ assert property instanceof PropertySimple;
+ PropertySimple ps = (PropertySimple) property;
+ assert ps.getStringValue().equals("Bar");
+
+ }
+
+ @Test
+ public void testConvertWithListOfSimple() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+ List<String> inner = new ArrayList<String>(2);
+ inner.add("Foo");
+ inner.add("Bar");
+ map.put("Inner", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop!=null;
+ assert prop instanceof PropertyList : "Inner is no list";
+
+ PropertyList plist = (PropertyList) prop;
+ List<Property> propertyList = plist.getList();
+ assert propertyList.size()==2;
+ for (Property innerProp : propertyList) {
+ assert innerProp instanceof PropertySimple;
+ PropertySimple ps = (PropertySimple) innerProp;
+ assert ps.getName().equals("Inner");
+ assert ps.getStringValue().equals("Foo") || ps.getStringValue().equals("Bar");
+ }
+
+ }
+
+ @Test
+ public void testConvertAndValidateBoolean() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>();
+ map.put("bool1","true");
+ map.put("bool2","TruE");
+ map.put("bool3","fAlSe");
+ map.put("bool4", "false");
+ map.put("bool5", 42);
+ map.put("bool6", "Hugo");
+ map.put("bool7",null);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==7 : "Expected 7 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool2","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool3","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool4","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool5","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool6","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool7","A boolean",true, PropertySimpleType.BOOLEAN));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==3 : "Expected 3 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMissingRequired() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ // required 2nd entry is missing
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==1 : "Expected 1 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool2","A boolean",true, PropertySimpleType.BOOLEAN));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateNotRequiredButNull() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMismatchingKind() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ map.put("Inner",inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+ // We define Inner as a simple property, but the user supplied a map
+ definition.put(new PropertyDefinitionSimple("Inner","null string",false, PropertySimpleType.STRING));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMismatchingKind2() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+ map.put("Inner","Frobnitz");
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+ // We define Inner as a list property, but the user supplied a simple one
+ definition.put(new PropertyDefinitionList("Inner","Bla",true,
+ new PropertyDefinitionSimple("Inner","fasel",true,PropertySimpleType.STRING)));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateNumeric() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("float1",1.1f);
+ map.put("float2",Double.MAX_VALUE);
+ map.put("float3",null);
+ map.put("float4","abc");
+
+ map.put("double1",1.1d);
+ map.put("double2",null);
+ map.put("double3","hugo");
+
+ map.put("int1",42);
+ map.put("int2",Long.MAX_VALUE);
+ map.put("int3",null);
+ map.put("int4","abc");
+
+ map.put("long1",-5);
+ map.put("long2",null);
+ map.put("long3","Frobnitz");
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==14 : "Expected 14 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("float1","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float2","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float3","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float4","A float",true, PropertySimpleType.FLOAT));
+
+ definition.put(new PropertyDefinitionSimple("double1","A double",true, PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("double2","A double",true, PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("double3","A double",true, PropertySimpleType.DOUBLE));
+
+ definition.put(new PropertyDefinitionSimple("int1","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int2","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int3","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int4","An int",true, PropertySimpleType.INTEGER));
+
+ definition.put(new PropertyDefinitionSimple("long1","A long",true, PropertySimpleType.LONG));
+ definition.put(new PropertyDefinitionSimple("long2","A long",true, PropertySimpleType.LONG));
+ definition.put(new PropertyDefinitionSimple("long3","A long",true, PropertySimpleType.LONG));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==10 : "Expected 10 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testValidateNullConfiguration() throws Exception {
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(null,new ConfigurationDefinition("bla",null));
+ assert errors != null;
+ assert errors.size()==1;
+
+ }
+
+ @Test
+ public void testValidateNullDefinition() throws Exception {
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(new Configuration(),null);
+ assert errors != null;
+ assert errors.size()==1;
+
+ }
+
+ @Test
+ public void testConvertAndValidateSimpleMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("Answer",null,true,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("Optional",null,false,PropertySimpleType.INTEGER));
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2;
+
+ PropertySimple hello = config.getSimple("Hello");
+ assert hello !=null;
+ assert hello.getStringValue().equals("World");
+
+ PropertySimple qu = config.getSimple("Answer");
+ assert qu!=null;
+ Integer integerValue = qu.getIntegerValue();
+ assert integerValue !=null;
+ assert integerValue ==42;
+ }
+
+ @Test
+ public void testConvertValidateNonRequiredNotPresent() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==0 : "Expected 0 props, got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Answer",null,false,PropertySimpleType.INTEGER));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateListOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.add(inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("Answer",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionList("list",null,true,
+ new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+ definition.put(new PropertyDefinitionSimple("aString",null,false,PropertySimpleType.INTEGER));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMapOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ Map<String,Map<String,Object>> list = new HashMap<String, Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.put("outer", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMapWithListOfSimple() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+
+ Map<String,List<String>> list = new HashMap<String, List<String>>();
+ map.put("list",list);
+
+ List<String> inner = new ArrayList<String>();
+ inner.add("Foo");
+ inner.add("Bar");
+ list.put("outer", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionList("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConfigToMapSimple() throws Exception {
+
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("number",42));
+ config.put(new PropertySimple("string","Hello"));
+ config.put(new PropertySimple("bool",true));
+ config.put(new PropertySimple("float",1.1f));
+ config.put(new PropertySimple("double",2.3d));
+ config.put(new PropertySimple("long",Long.MAX_VALUE));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("bool",null,false,PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("float",null,false,PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("double",null,false,PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("long",null,false,PropertySimpleType.LONG));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==6;
+
+ assert map.containsKey("number");
+ assert map.containsKey("string");
+
+ assert map.get("number") != null;
+ assert (Integer)map.get("number") == 42;
+
+ assert map.get("string") != null;
+ assert map.get("string").equals("Hello");
+
+ assert (Boolean)map.get("bool") == true;
+
+ assert map.get("float") != null;
+ assert (Float)map.get("float") ==1.1f;
+
+ assert map.get("double") != null;
+ assert (Double) map.get("double") ==2.3d;
+
+ assert map.get("long") != null;
+ assert (Long)map.get("long") == Long.MAX_VALUE;
+
+ }
+
+ @Test
+ public void testEmptyConfigToMap() throws Exception {
+
+ Configuration config = new Configuration();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==0;
+
+
+ }
+
+ @Test
+ public void testNullConfigToMap() throws Exception {
+
+ Configuration config = null;
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==0;
+
+ }
+
+ @Test
+ public void testConfigToMapComplexList() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ config.put(propertyList);
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionList("aList",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aList");
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMap() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aList",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aString",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aMap");
+ assert map.get("aMap") instanceof Map;
+ Map<String,Object> innerMap = (Map<String, Object>) map.get("aMap");
+
+ assert innerMap.containsKey("aString");
+ assert innerMap.containsKey("aList");
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMapWithBadSetupStrict() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aBla",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aFoo",null,false,PropertySimpleType.STRING)));
+
+ try {
+ ConfigurationHelper.configurationToMap(config,definition, true);
+ assert false;
+ } catch (IllegalArgumentException iae ) {
+ System.out.println("Yep, caught the error");
+ }
+
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aBla",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aFoo",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, false);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aMap");
+
+ }
+
+ @Test
+ public void testConvertSingleValueNoProperty() throws Exception {
+
+ Object o = ConfigurationHelper.convertSimplePropertyValue(null,new PropertyDefinitionSimple("dummy",null,false,PropertySimpleType.STRING));
+
+ assert o == null;
+
+ }
+
+ @Test
+ public void testConvertSingleValueNoDefinition() throws Exception {
+
+ try {
+ ConfigurationHelper.convertSimplePropertyValue(new PropertySimple("foo","bar"),null);
+ assert false;
+ }
+ catch (IllegalArgumentException iae) {
+ System.out.println("Yep, good");
+ }
+
+ }
+}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index 3d9f735..fca0f50 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -266,8 +266,8 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("NONE"))
- .body("dampeningCount",is("0"))
- .body("dampeningPeriod",is("0"))
+ .body("dampeningCount",is(0))
+ .body("dampeningPeriod",is(0))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
@@ -369,8 +369,8 @@ public class AlertTest extends AbstractBase {
alertDefinition.setEnabled(false);
alertDefinition.setPriority("LOW");
alertDefinition.setDampeningCategory("PARTIAL_COUNT");
- alertDefinition.setDampeningCount("3");
- alertDefinition.setDampeningPeriod("5");
+ alertDefinition.setDampeningCount(3);
+ alertDefinition.setDampeningPeriod(5);
AlertDefinition result =
given()
@@ -381,8 +381,8 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("PARTIAL_COUNT"))
- .body("dampeningCount",is("3"))
- .body("dampeningPeriod",is("5"))
+ .body("dampeningCount",is(3))
+ .body("dampeningPeriod",is(5))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
@@ -404,8 +404,9 @@ public class AlertTest extends AbstractBase {
alertDefinition.setEnabled(false);
alertDefinition.setPriority("LOW");
alertDefinition.setDampeningCategory("DURATION_COUNT");
- alertDefinition.setDampeningCount("1");
- alertDefinition.setDampeningPeriod("3 minutes");
+ alertDefinition.setDampeningCount(1);
+ alertDefinition.setDampeningPeriod(3);
+ alertDefinition.setDampeningUnit("minutes");
AlertDefinition result =
given()
@@ -416,8 +417,9 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("DURATION_COUNT"))
- .body("dampeningCount", is("1"))
- .body("dampeningPeriod", is("3 MINUTES"))
+ .body("dampeningCount", is(1))
+ .body("dampeningPeriod", is(3))
+ .body("dampeningUnit", is("MINUTES"))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
index 713a755..e6aea1f 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
@@ -61,8 +61,9 @@ public class OperationsTest extends AbstractBase {
definitionId = -1;
List<Map<String,Object>> list = r.as(List.class);
for (Map<String,Object> map : list) {
- if (map.get("name").equals("discovery"))
+ if (map.get("name").equals("discovery")) {
definitionId = (Integer) map.get("id");
+ }
}
assert definitionId !=-1 : "No discovery operation found";
@@ -85,6 +86,92 @@ public class OperationsTest extends AbstractBase {
}
@Test
+ public void testGetDefinitionByUnknownId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("did",-42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/operation/definition/{did}");
+
+ }
+
+ @Test
+ public void testGetDefinitionsForUnknownResource() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .queryParam("resourceId",42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/operation/definitions");
+ }
+
+ @Test
+ public void testGetDefinitionsForMissingResourceId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .expect()
+ .statusCode(406)
+ .when()
+ .get("/operation/definitions");
+ }
+
+ @Test
+ public void testCreateScheduleByUnknownDefinitionId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("did",-42)
+ .expect()
+ .statusCode(406)
+ .when()
+ .post("/operation/definition/{did}");
+
+ }
+
+ @Test
+ public void testCreateScheduleForUnknownResource() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .queryParam("resourceId", 42)
+ .pathParam("definitionId", definitionId)
+ .expect()
+ .statusCode(404)
+ .when()
+ .post("/operation/definition/{definitionId}");
+ }
+
+ @Test
+ public void testCreateScheduleForMissingResourceId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId", definitionId)
+ .expect()
+ .statusCode(406)
+ .when()
+ .post("/operation/definition/{definitionId}");
+ }
+
+ @Test
public void testCreateDraftOperation() throws Exception {
Operation draft =
@@ -196,8 +283,9 @@ public class OperationsTest extends AbstractBase {
String history = null;
List<Link> links = scheduled.getLinks();
for (Link link : links) {
- if (link.getRel().equals("history"))
- history = (String) link.getHref();
+ if (link.getRel().equals("history")) {
+ history = link.getHref();
+ }
}
assert history != null;
@@ -272,4 +360,98 @@ public class OperationsTest extends AbstractBase {
}
}
+ @Test
+ public void testOpsScheduleMissingRequiredParam() throws Exception {
+
+ int platformId = findIdOfARealPlatform();
+
+ Operation draft =
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId",definitionId)
+ .queryParam("resourceId",platformId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/operation/definition/{definitionId}")
+ .as(Operation.class);
+
+ assert draft != null;
+ assert draft.getDefinitionId() == definitionId;
+
+ int draftId = draft.getId();
+
+ // explicitly remove the param from the draft for
+ // the test
+ Map<String, Object> params = draft.getParams();
+ if (params.containsKey("detailedDiscovery")) {
+ params.remove("detailedDiscovery");
+ }
+
+ // Update to put the new version in the server
+ // We don't want to submit, so the server does not
+ // validate and we should get a 200 back
+ draft.setReadyToSubmit(false);
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+
+
+ // update to schedule, lacking the required param
+ draft.setReadyToSubmit(true);
+
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(406)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+ }
+
+ @Test
+ public void testOpsScheduleRequiredParamWrongDataType() throws Exception {
+
+ int platformId = findIdOfARealPlatform();
+
+ Operation draft =
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId",definitionId)
+ .queryParam("resourceId",platformId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/operation/definition/{definitionId}")
+ .as(Operation.class);
+
+ assert draft != null;
+ assert draft.getDefinitionId() == definitionId;
+
+ int draftId = draft.getId();
+
+ draft.getParams().put("detailedDiscovery", 42);
+ draft.setReadyToSubmit(true);
+
+ // update to schedule
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(406)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+ }
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
index 5922770..d6da534 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
@@ -50,7 +50,7 @@ public class RootURITest extends AbstractBase {
.expect().statusCode(200)
.when().get("/");
- given().header("Accept","application/json")
+ given().header("Accept","application/xml")
.expect().statusCode(200)
.when().get("/index");
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
index 5049a98..b870443 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
@@ -41,8 +41,9 @@ public class AlertDefinition {
List<AlertCondition> conditions = new ArrayList<AlertCondition>();
List<AlertNotification> notifications = new ArrayList<AlertNotification>();
String dampeningCategory = "NONE";
- String dampeningCount;
- String dampeningPeriod;
+ int dampeningCount;
+ int dampeningPeriod;
+ String dampeningUnit;
List<Link> links;
@@ -121,22 +122,30 @@ public class AlertDefinition {
this.dampeningCategory = dampeningCategory;
}
- public String getDampeningCount() {
+ public int getDampeningCount() {
return dampeningCount;
}
- public void setDampeningCount(String dampeningCount) {
+ public void setDampeningCount(int dampeningCount) {
this.dampeningCount = dampeningCount;
}
- public String getDampeningPeriod() {
+ public int getDampeningPeriod() {
return dampeningPeriod;
}
- public void setDampeningPeriod(String dampeningPeriod) {
+ public void setDampeningPeriod(int dampeningPeriod) {
this.dampeningPeriod = dampeningPeriod;
}
+ public String getDampeningUnit() {
+ return dampeningUnit;
+ }
+
+ public void setDampeningUnit(String dampeningUnit) {
+ this.dampeningUnit = dampeningUnit;
+ }
+
public List<Link> getLinks() {
return links;
}
commit d72ac1e6bba8cbeb054a7cbfc8d7df026a09a5fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 09:17:22 2013 +0200
Add another email for Thomas
diff --git a/.mailmap b/.mailmap
index 384ec04..ac0fdc9 100644
--- a/.mailmap
+++ b/.mailmap
@@ -75,5 +75,6 @@ Test JON User <test_jon(a)jon01.qa.atl2.redhat.com>
Todd B Sanders <tsanders(a)dhcp231-67.rdu.redhat.com>
Torben Jäger <torben(a)jit-central.com>
Thomas Segismont <tsegismo(a)redhat.com> Thomas SEGISMONT <tsegismo(a)redhat.com>
+Thomas Segismont <tsegismo(a)redhat.com> Thomas Segismont <tsegismont(a)gmail.com>
Thomas Segismont <tsegismo(a)redhat.com>
hudson auto <wnstb(a)yahoo.com>
commit bbe5654f0755eac835b78351a8ef71a7e3398037
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 7 16:58:43 2013 -0700
[BZ 960646] - RFE Redesigned Availability Chart - Add disabled state cross hatch SVG pattern. Pixel tweeks.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 76c8f69..4e6a0ce 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -18,6 +18,9 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+import java.util.Date;
+import java.util.List;
+
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
@@ -27,9 +30,6 @@ import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import java.util.Date;
-import java.util.List;
-
/**
* Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
* just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
@@ -66,7 +66,7 @@ public class AvailabilityOverUnderGraphType {
// loop through the avail intervals
for (Availability availability : availabilityList) {
sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
// last record will be null
long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
@@ -84,8 +84,9 @@ public class AvailabilityOverUnderGraphType {
// loop through the group avail down intervals
for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
// allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
- ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
@@ -139,7 +140,6 @@ public class AvailabilityOverUnderGraphType {
barOffset = 10,
width = 750 - margin.left - margin.right + barOffset,
height = 40 - margin.top - margin.bottom,
- pixelsOffHeight = 0,
svg;
@@ -161,65 +161,65 @@ public class AvailabilityOverUnderGraphType {
.domain([0, 4]),
xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(12)
- .tickSize(10, 0, 0)
- .orient("bottom"),
-
- calcBarY = function(d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function(d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "#FF9933"; // orange
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // yellow
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.warn("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .scale(timeScale)
+ .ticks(12)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.warn("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
@@ -234,11 +234,9 @@ public class AvailabilityOverUnderGraphType {
})
.attr("y", function (d) {
return calcBarY(d);
-
})
.attr("height", function (d) {
return 10;
-
})
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
@@ -250,43 +248,43 @@ public class AvailabilityOverUnderGraphType {
// create x-axis
svg.append("g")
- .attr("class", "x axis")
- .attr("stroke", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text("Availability");
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text("Availability");
svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text("UP");
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("UP");
svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text("DOWN");
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("DOWN");
}
@@ -306,19 +304,15 @@ public class AvailabilityOverUnderGraphType {
}
function formatHovers(d) {
- var hoverString,
- timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart),
- availEnd = new Date(+d.availEnd);
+ availStart = new Date(+d.availStart);
- hoverString =
- '<div class="chartHoverEnclosingDiv">' +
+ return '<div class="chartHoverEnclosingDiv">' +
'<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>'+ dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
'<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
'</div>';
- return hoverString;
}
@@ -341,7 +335,7 @@ public class AvailabilityOverUnderGraphType {
availabilityGraph.draw(availChartContext);
}
- }-*/;
+ }-*/;
public String getChartId() {
return String.valueOf(entityId);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index 7df45d1..b876c74 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -634,7 +634,7 @@ public abstract class AbstractActivityView extends EnhancedVLayout implements Re
setIsModal(true);
setShowModalMask(true);
setWidth(950);
- setHeight(350);
+ setHeight(370);
setShowResizer(true);
setCanDragResize(true);
centerInPage();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
index b590e86..f8887bf 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
@@ -67,6 +67,31 @@ public class MetricD3GraphView extends EnhancedVLayout {
+ " width=\"6\" height=\"3\">"
+ " <path d=\"M 0 0 6 0\" style=\"stroke:#2E9EC2; fill:none;\"/>"
+ " </pattern>"
+ + "<pattern id=\"diagonalHatchFill\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">"
+ + "<circle cx=\"0\" cy=\"0\" r=\"1000\" fill=\"grey\"/>"
+ + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>"
+ + "<path d=\"M0 60 l45,45\"/>"
+ + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>"
+ + "<path d=\"M0 15 l90,90\"/>"
+ + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>"
+ + "<path d=\"M30 0 l75,75\"/>"
+ + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>"
+ + "<path d=\"M75 0 l30,30\"/>"
+ + "<path d=\"M90 0 l15,15\"/>"
+ + "</g>"
+ + "</pattern>"
+ + "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">" + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>" + "<path d=\"M0 60 l45,45\"/>" + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>" + "<path d=\"M0 15 l90,90\"/>" + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>" + "<path d=\"M30 0 l75,75\"/>" + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>" + "<path d=\"M75 0 l30,30\"/>" + "<path d=\"M90 0 l15,15\"/>" + "</g>"
+ + "</pattern>"
+ " <pattern id=\"downStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
+ " width=\"6\" height=\"3\">"
+ " <path d=\"M 0 0 6 0\" style=\"stroke:#ff8a9a; fill:none;\"/>"
@@ -101,9 +126,9 @@ public class MetricD3GraphView extends EnhancedVLayout {
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs
.append("<div id=\""
- + getFullChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
- + getChartHeight() + "px;\">");
+ + getFullChartId()
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
+ + getChartHeight() + "px;\">");
divAndSvgDefs.append(getSvgDefs());
divAndSvgDefs.append("</svg></div>");
@@ -133,14 +158,11 @@ public class MetricD3GraphView extends EnhancedVLayout {
graph.drawJsniChart();
}
-
public String getFullChartId() {
return "rChart-" + graph.getMetricGraphData().getChartId();
}
-
-
public Integer getChartHeight() {
return graph.getMetricGraphData().getChartHeight();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
index d06bab2..ca8b117 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
@@ -25,7 +25,6 @@ import com.smartgwt.client.widgets.HTMLFlow;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraph;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -43,7 +42,7 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
public AvailabilityD3Graph(AvailabilityOverUnderGraphType graphType) {
super();
this.availabilityGraphType = graphType;
- setHeight(70);
+ setHeight(65);
setWidth100();
}
@@ -83,15 +82,26 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:110px;\">");
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
+ divAndSvgDefs.append(getSvgDefs());
divAndSvgDefs.append("</svg></div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
- graph.setHeight(25);
+ graph.setHeight(65);
addMember(graph);
}
+ /**
+ * Svg definitions for patterns and gradients to use on SVG shapes.
+ * @return xml String
+ */
+ private static String getSvgDefs() {
+ return " <defs>"+
+ "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\"> <path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" /> </pattern>"
+ + "</defs>";
+ }
+
@Override
public void destroy() {
super.destroy();
commit ee5255b684d733fa01989930676f5d0e7e17d51e
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Mon May 6 14:23:28 2013 -0700
[BZ 960646] - RFE Redesigned Availability Charts.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
new file mode 100644
index 0000000..76c8f69
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -0,0 +1,381 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
+ ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ pixelsOffHeight = 0,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(12)
+ .tickSize(10, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function(d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function(d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "#FF9933"; // orange
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // yellow
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.warn("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+
+ })
+ .attr("height", function (d) {
+ return 10;
+
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("stroke", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text("Availability");
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("UP");
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("DOWN");
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var hoverString,
+ timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart),
+ availEnd = new Date(+d.availEnd);
+
+ hoverString =
+ '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>'+ dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+ return hoverString;
+
+ }
+
+ return {
+ // Public API
+ draw: function (chartContext) {
+ "use strict";
+ console.info("AvailabilityChart");
+ //console.time("availabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ //console.timeEnd("availabilityChart");
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getChartHoverEndLabel() {
+ return MSG.chart_hover_end_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index d9a4205..15f400d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -234,8 +234,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
chart.append("g").append("rect")
.attr("class", "rightSidePanel")
.attr("x", xLabel - 10)
- .attr("y", margin.top + 60)
- .attr("height", 100)
+ .attr("y", margin.top + 70)
+ .attr("rx", 10)
+ .attr("ry", 10)
+ .attr("height", 80)
.attr("width", 135)
.attr("opacity", "0.3")
.attr("fill", "#E8E8E8");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 786701b..7691c5f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -42,6 +42,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
@@ -74,7 +75,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
addMember(measurementRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityLineGraphType(resourceGroup.getId()));
+ availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 26f3626..58d3050 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -47,6 +47,7 @@ import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferen
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3Graph;
@@ -130,7 +131,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
addMember(measurementRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityLineGraphType(resource.getId()));
+ availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resource.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
index d03fefe..d06bab2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
@@ -26,6 +26,7 @@ import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraph;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -37,12 +38,12 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
*/
public class AvailabilityD3Graph extends EnhancedVLayout implements AvailabilityGraph {
- protected AvailabilityLineGraphType availabilityGraphType;
+ protected AvailabilityOverUnderGraphType availabilityGraphType;
- public AvailabilityD3Graph(AvailabilityLineGraphType graphType) {
+ public AvailabilityD3Graph(AvailabilityOverUnderGraphType graphType) {
super();
this.availabilityGraphType = graphType;
- setHeight(25);
+ setHeight(70);
setWidth100();
}
@@ -82,7 +83,7 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:20px;\">");
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:110px;\">");
divAndSvgDefs.append("</svg></div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
commit 85215f76e7ec578a7cad3a13e983c6cbffa0650f
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Apr 24 16:16:15 2013 -0700
Trivial: add *.DS_Store files to .gitignore
diff --git a/.gitignore b/.gitignore
index 92b2176..3bd9232 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,6 @@ modules/enterprise/gui/coregui/build/classes/
modules/enterprise/gui/content_http-war/build/classes/
#created by rhq-enterprise-server's unit tests
modules/enterprise/server/jar/transaction.log
-
.idea/
.metadata/
*cache.html
@@ -27,6 +26,7 @@ modules/enterprise/server/jar/transaction.log
.*.jsfdia
.wtpmodules
*~
+*.DS_Store
#these are created by the python script engine during the tests
cachedir/
commit f875212be4a8cfaf0905e2fd376a579197b83148
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue May 7 14:25:34 2013 +0200
Bug 865629 - (PRODMGT-245) Add more metrics to AS7 plugin
Added missing metrics
Added integration test
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index cfe756d..5f538b7 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -615,6 +615,7 @@
<include>org/rhq/modules/plugins/jbossas7/itest/**/*Test.java</include>
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 45f4e05..742c4d5 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -8864,6 +8864,22 @@
<metric property="responseTime"
dataType="calltime" defaultOn="false" units="milliseconds" destinationType="URL"
description="the minimum, maximum, and average response times for requests serviced by this webapp"/>
+ <metric property="active-sessions" displayName="Currently Active Sessions"
+ description="The number of sessions that are currently active"/>
+ <metric property="duplicated-session-ids" displayName="Duplicated Session Ids"
+ description="The number of duplicated session identifiers"/>
+ <metric property="expired-sessions" measurementType="trendsup" displayName="Expired Sessions"
+ description="The number of expired sessions"/>
+ <metric property="max-active-sessions" displayName="Maximum Active Sessions"
+ description="The maximum number of sessions that have been active"/>
+ <metric property="rejected-sessions" measurementType="trendsup" displayName="Rejected Sessions"
+ description="The number of sessions rejected"/>
+ <metric property="session-avg-alive-time" units="milliseconds" displayName="Average Session Alive Time"
+ description="The average alive time of sessions"/>
+ <metric property="session-max-alive-time" units="milliseconds" displayName="Max Session Alive Time"
+ description="The maximum alive time of sessions"/>
+ <metric property="sessions-created" measurementType="trendsup" displayName="Created Sessions"
+ description="The number of sessions created"/>
</service>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
index 6f84e34..5b552bc 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
@@ -19,6 +19,11 @@
package org.rhq.modules.plugins.jbossas7.itest.standalone;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.rhq.core.domain.util.ResourceTypeUtility.getMeasurementDefinitions;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -27,6 +32,8 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
import java.util.Set;
import org.mockito.Mockito;
@@ -47,8 +54,18 @@ import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.content.PackageDetailsKey;
import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.domain.resource.CreateResourceStatus;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.util.MeasurementDefinitionFilter;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.util.FacetLockType;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
import org.rhq.modules.plugins.jbossas7.StandaloneASComponent;
import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
import org.rhq.test.arquillian.DiscoveredResources;
@@ -101,6 +118,9 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
@DiscoveredResources(plugin = PLUGIN_NAME, resourceType = "Deployment")
private Set<Resource> deploymentResources;
+ @DiscoveredResources(plugin = PLUGIN_NAME, resourceType = "Web Runtime")
+ private Set<Resource> webRuntimeResources;
+
private static TestDeployments DEPLOYMENT_TO_SERVE = TestDeployments.DEPLOYMENT_1;
private static long copyStreamAndReturnCount(InputStream in, OutputStream out) throws IOException {
@@ -242,6 +262,60 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
}
@Test(priority = 15)
+ @RunDiscovery
+ public void testWebRuntimeMetricsHaveNonNullValues() throws Exception {
+ assertTrue(webRuntimeResources != null && !webRuntimeResources.isEmpty(),
+ "Web Runtime resource should have been discovered");
+ assertEquals(webRuntimeResources.size(), 1, "Found more than one Web Runtime resource: " + webRuntimeResources);
+
+ Resource webRuntimeResource = webRuntimeResources.iterator().next();
+ ResourceContainer webRuntimeResourceContainer = pluginContainer.getInventoryManager().getResourceContainer(
+ webRuntimeResource);
+ MeasurementFacet measurementFacet = webRuntimeResourceContainer.createResourceComponentProxy(
+ MeasurementFacet.class, FacetLockType.READ, SECONDS.toMillis(5), false, false);
+ MeasurementReport report = new MeasurementReport();
+ Set<MeasurementScheduleRequest> measurementScheduleRequests = getMeasurementScheduleRequests(webRuntimeResource);
+ measurementFacet.getValues(report, measurementScheduleRequests);
+ assertEquals(report.getCallTimeData().size(), 0, "No calltime data was requested");
+ assertTrue(
+ report.getNumericData().size() + report.getTraitData().size() == measurementScheduleRequests.size(),
+ "Some requested measurements are missing: "
+ + getMissingMeasurements(measurementScheduleRequests, report.getNumericData(), report.getTraitData()));
+ }
+
+ private Set<String> getMissingMeasurements(Set<MeasurementScheduleRequest> measurementScheduleRequests,
+ Set<MeasurementDataNumeric> numericData, Set<MeasurementDataTrait> traitData) {
+ Set<String> missingMeasurements = new HashSet<String>();
+ for (MeasurementScheduleRequest measurementScheduleRequest : measurementScheduleRequests) {
+ missingMeasurements.add(measurementScheduleRequest.getName());
+ }
+ for (MeasurementDataNumeric measurementDataNumeric : numericData) {
+ missingMeasurements.remove(measurementDataNumeric.getName());
+ }
+ for (MeasurementDataTrait measurementDataTrait : traitData) {
+ missingMeasurements.remove(measurementDataTrait.getName());
+ }
+ return missingMeasurements;
+ }
+
+ private Set<MeasurementScheduleRequest> getMeasurementScheduleRequests(Resource webRuntimeResource) {
+ Set<MeasurementDefinition> measurementDefinitions = getMeasurementDefinitions(
+ webRuntimeResource.getResourceType(), new MeasurementDefinitionFilter() {
+ private final Set<DataType> acceptableDataTypes = EnumSet.of(DataType.MEASUREMENT, DataType.TRAIT);
+
+ public boolean accept(MeasurementDefinition measurementDefinition) {
+ return acceptableDataTypes.contains(measurementDefinition.getDataType());
+ }
+ });
+ Set<MeasurementScheduleRequest> measurementScheduleRequests = new HashSet<MeasurementScheduleRequest>();
+ for (MeasurementDefinition measurementDefinition : measurementDefinitions) {
+ measurementScheduleRequests.add(new MeasurementScheduleRequest(-1, measurementDefinition.getName(), -1,
+ true, measurementDefinition.getDataType(), measurementDefinition.getRawNumericType()));
+ }
+ return measurementScheduleRequests;
+ }
+
+ @Test(priority = 16)
public void testUndeploy() throws Exception {
Resource deployment = deploymentResources.iterator().next();
DeleteResourceRequest request = new DeleteResourceRequest(0, deployment.getId());
commit e589245b50710f5487ce3efcd527f73c02df8ea3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon May 6 19:02:55 2013 -0400
BZ 817825 don't show "Loading..." for leaf nodes in resource type drop down menus
this still doesn't fix the Platform plugin's platform type submenus.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
index e2650e4..90511d7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
@@ -77,8 +77,6 @@ public class ResourceSelector extends AbstractSelector<Resource, ResourceCriteri
typeSelectItem.setValueField("id");
typeSelectItem.setCanSelectParentItems(true);
typeSelectItem.setLoadDataOnDemand(false);
- typeSelectItem.setEmptyMenuMessage(MSG.common_msg_loading());
- typeSelectItem.setShowIcons(false);
if (this.forceResourceTypeFilter) {
typeSelectItem.setDisabled(true);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
index 136db95..c1c9e66 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
@@ -19,8 +19,6 @@
package org.rhq.enterprise.gui.coregui.client.inventory.resource.type;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -144,12 +142,6 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
}
}
- Collections.sort(nodes, new Comparator<TreeNode>() {
- public int compare(TreeNode o1, TreeNode o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
-
TreeNode[] treeNodes = nodes.toArray(new TreeNode[nodes.size()]);
return treeNodes;
}
@@ -198,9 +190,8 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
setParentID(null);
setAttribute("name", pluginName + " " + pluginStr);
- // setAttribute("plugin",pluginName);
- setIcon("types/plugin_16.png"); // todo doesn't work
setEnabled(true);
+ // setIcon(IconEnum.PLUGIN.getIcon16x16Path()); // IPickTreeItem doesn't appear to want to use this
}
@Override
@@ -245,10 +236,7 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
setAttribute("name", resourceType.getName());
setAttribute("plugin", resourceType.getPlugin());
setAttribute("category", resourceType.getCategory().getDisplayName());
-
- setIcon("types/" + resourceType.getCategory().getDisplayName() + "_up_16.png");
-
- setIsFolder(true);
+ // setIcon(ImageManager.getResourceIcon(resourceType.getCategory())); // IPickTreeItem doesn't appear to want to use this
}
public ResourceType getResourceType() {
commit 82a86c90fcc05ec19b1b9b63771fe12905cb2f09
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon May 6 16:03:20 2013 -0400
BZ 960265 bring back the GWT calltime page
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index a68170a..91db630 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -28,6 +28,7 @@ import com.smartgwt.client.widgets.Canvas;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.DataType;
@@ -55,7 +56,6 @@ import org.rhq.enterprise.gui.coregui.client.drift.ResourceDriftDefinitionsView;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.AbstractTwoLevelTabSetView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.monitoring.IFrameWithMeasurementRangeEditorView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.event.EventCompositeHistoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceCompositeSearchView;
@@ -64,6 +64,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configura
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationEditView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.ResourceAgentView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.CalltimeView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
@@ -437,8 +438,7 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- return new IFrameWithMeasurementRangeEditorView("/rhq/resource/monitor/response-plain.xhtml?id="
- + resource.getId());
+ return new CalltimeView(EntityContext.forResource(resource.getId()));
}
};
updateSubTab(this.monitoringTab, this.monitorCallTime, visible, true, viewFactory);
commit 98f5814fe4acb2dd5a9305170460638e3cd984e1
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:05:04 2013 -0500
Update development version to 4.8.0-SNAPSHOT.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index f1f8cec..dbb487d 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index c4dadc9..efe6d1f 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 4cf6703..138e9ca 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 9d7a132..5afdead 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 32692b5..0beb20b 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index 4f43692..b8c1682 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index b9ee5be..6dac77b 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 4ed6d92..088e268 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index 7c7e949..fe5f377 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 75a7a05..258d050 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 9637dfc..67b02a8 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index 5d80c3f..231ab67 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index f086ca3..4ed7bca 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index acd19c9..7adcd3b 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 9fd9f98..1fb2161 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index d77ee51..cc040f8 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index d572d9d..776459d 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index b3b7706..dc21aad 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 04be12b..46fe305 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index a24c330..8060a89 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 900eb72..9c801de 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 06395a2..3c070a9 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index fc49cf3..18fa318 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index c75dcbc..0374729 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index d05b721..99c875d 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index c3c7175..426d298 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c4992af..c41a8f4 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index b799891..cdc3b9b 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index cb1fad0..2d7093d 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 3b66b92..67ed9a8 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index a41fb6c..d5b7643 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index c312dc1..8148262 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 333aa5d..a140a9c 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 035ade8..cb7dd3a 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 1fa9ec1..018a802 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index a827c3c..d2998cc 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 70ece03..638bccd 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index 2a5091c..c9aa075 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 5d3dbfc..33e330e 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 489d603..3fad441 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index e371826..dec19d0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index 2c7b6f9..cba50db 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index b411a87..6db40f2 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 3ab9e66..7bf574e 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index 07768cd..268af3a 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 32eb12d..acc09aa 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 5c82958..a58f1ca 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index f6a1149c..dc69d9e 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index 0e46986..f186d70 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 6bb6ea2..3e69ded 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 939f107..867ebe1 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 150daf2..23d8e94 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 9f9ba81..5e4e076 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index acb8931..84e34c4 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index 68ea87a..ea9bd42 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index ec91baf..a2102a3 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index ea7bd90..bd5f656 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index c50b5cb..934cb7e 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index c576b41..28d1d56 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 5d9fb43..4338526 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 24813ad..21ec5f7 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index 31acb49..a6c054a 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index b09ed2a..f84398b 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index cd0263b..d4d2564 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 489b37b..648b451 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 94cbe7d..6f56e82 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index c111bcc..21bb689 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 52b3a7c..7111543 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index b43da47..6ab0964 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 33a11a1..32ffc76 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index 80799ab..2a75e07 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 827bc41..dc862db 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 5660473..bb1740d 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 0d80df3..06da613 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index 75b3cdc..6f8ac10 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 494e98e..9c60e30 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index 8c509f4..b2b741e 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index 2b00e67..d4f7715 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 4586a8b..014420b 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 3359f33..7152fc3 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 98783f1..00e558b 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index 82fabfc..f2f2455 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index 348b780..6f36514 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index ed71426..8772058 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index bd47d23..ecebf6c 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index e72aab4..c5a4a41 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index f3cbb2e..baf0801 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index da9cf66..bf4ca3d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index ce66fd5..a9d7296 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index f83573d..48808ac 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index caef075..6ded494 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index b28b9bf..d11992a 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index f110387..7e5f521 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index 6061752..bca2fe4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index 14874eb..2809e95 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 9c3e48d..75a98a4 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 3f6bca5..380f6e6 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 4e663e6..ada89b3 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 6a85842..37ffe0e 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index d576083..a17a3d8 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index c01634b..9424397 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 27f290b..3aa5463 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 7959a32..03349f8 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index c67fc10..8a5f0e6 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 4a3ad1d..a1c3353 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index dd99a37..d8325e4 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index 0303046..adee980 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 9ca39d3..f587112 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index 1a8d193..d1f3e43 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 69f1dbb..93a915f 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index 875e82f..b043e7b 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 221d4cc..f2e6f8a 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 81b2322..cfe756d 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index bd58a06..b792d26 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index c83611c..837852d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 421f24d..3828a6a 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 48e3f93..864f675 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 9255d09..094f451 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index 62ffc81..54b9f53 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 14e39a3..572851e 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 22db736..6b663ff 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index 1f43ea4..68af26a 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index dc4f4aa..ed93d10 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 1d40834..5653d69 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 593a70b..f852e8a 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index ef210b6..e28148c 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 9d6a147..0e27179 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 6ee7474..12ae83c 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 1e323fb..26d37b3 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index e187c17..6bf549f 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 5327977..968a154 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 23dadb6..20e41c4 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 3772829..d31500b 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 3bec031..36ab8be 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index ae92638..74d740b 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index 93856c9..e0a216e 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index d10ef73..3891b84 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index 8cdd836..eb97008 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 52e155c..45c2544 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 1e8c6fc..63eb6ae 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index 1c2bbca..de510c5 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 82d911d..8f4cf31 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index f536119..c343deb 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index da1506f..b46ee9e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 0989c0c6cad40b787e4148d40b95418d1dd7a4cf
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:02:05 2013 -0500
Disable all the arquillian-integration submodules from building when maven.test.skip is true. Also, fix modules that depended on these modules to include them only if they are built.
(cherry picked from commit 7e9678418a8ee2683aafb395c1cc25415ab375e3)
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 7e215a3..9637dfc 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -19,11 +19,30 @@
<name>RHQ Arquillian Integration Modules</name>
<description>parent POM for integration modules with Arquillian</description>
- <modules>
- <module>test-agent-plugin</module>
- <module>container</module>
- <module>archive</module>
- <module>suite-extension</module>
- </modules>
+
+ <profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <modules>
+ <module>test-agent-plugin</module>
+ <module>container</module>
+ <module>archive</module>
+ <module>suite-extension</module>
+ </modules>
+ </profile>
+ </profiles>
</project>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 9c91bc0..fc49cf3 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -1,5 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -24,59 +24,80 @@
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>test-utils</artifactId>
- <version>${project.version}</version>
- </dependency>
+ </dependencies>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-arquillian-agent-plugin-container-embedded</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-testng</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-mockito</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.container</groupId>
- <artifactId>arquillian-container-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.core</groupId>
- <artifactId>arquillian-core-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.container</groupId>
- <artifactId>arquillian-container-test-api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.test</groupId>
- <artifactId>arquillian-test-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.testng</groupId>
- <artifactId>arquillian-testng-container</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.shrinkwrap.resolver</groupId>
- <artifactId>shrinkwrap-resolver-depchain</artifactId>
- <type>pom</type>
- </dependency>
- </dependencies>
+ <profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-arquillian-agent-plugin-container-embedded</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.core</groupId>
+ <artifactId>arquillian-core-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-test-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.test</groupId>
+ <artifactId>arquillian-test-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.testng</groupId>
+ <artifactId>arquillian-testng-container</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-depchain</artifactId>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
</project>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c51fb51..c4992af 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -1,5 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -23,9 +23,7 @@
<profile>
<id>default</id>
<activation>
- <property>
- <name>java.home</name>
- </property>
+ <activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>util</module>
@@ -47,6 +45,38 @@
</modules>
</profile>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>avoid.test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <modules>
+ <module>util</module>
+ <module>native-system</module>
+ <module>comm-api</module>
+ <module>dbutils</module>
+ <module>domain</module>
+ <module>plugin-api</module>
+ <module>client-api</module>
+ <module>plugin-container</module>
+ <module>gui</module>
+ <module>plugin-validator</module>
+ <module>arquillian-integration</module>
+ <module>plugin-test-api</module>
+ <module>plugin-container-itest</module>
+ </modules>
+ </profile>
+
+
<profile>
<id>plugindoc</id>
<modules>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index 9888aa0..d576083 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -63,20 +63,6 @@
<artifactId>snakeyaml</artifactId>
<version>1.10</version>
</dependency>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
@@ -231,6 +217,39 @@
</build>
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>dev</id>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index d9838cf..221d4cc 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -119,21 +119,6 @@
<!-- Test Deps -->
<dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
<groupId>org.jboss.spec.javax.jms</groupId>
<artifactId>jboss-jms-api_1.1_spec</artifactId>
<version>1.0.0.Final</version>
@@ -218,6 +203,39 @@
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>integration-tests</id>
<!--
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 33b2bd7..81b2322 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -99,21 +99,6 @@
<!-- === Test Deps === -->
<dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
@@ -250,6 +235,39 @@
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>java7</id>
<activation>
commit cad0a43803d781bf2ba28eab71b80f822bf2d07d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:01:37 2013 -0500
Update test to avoid disabled managers. This is especially important for the TagManager that can be disabled via build properties.
(cherry picked from commit c9ccdbf61842dd115ce0d3067752e85dbb1db730)
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
index aa0ebd4..024e4f6 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
@@ -87,6 +87,10 @@ public class ScriptingAPIServerTest extends ScriptableAbstractEJB3Test {
//Simplification itself is unit tested separately.
for (RhqManager m : RhqManager.values()) {
+ if (!m.enabled()) {
+ continue;
+ }
+
String name = m.name();
// Only check for the TagManager if it is enabled at all
if (name.contains("TagManager") && !RhqManager.TagManager.enabled()) {
commit 5fecc675d08aa9220a163f0e35530dc6c07447b6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon May 6 16:20:24 2013 +0200
Add test case for Bug 911321 - [EAP 6.1] Reload operation fails in standalone mode
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 23a02c4..33b2bd7 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -30,6 +30,7 @@
<java.tieredCompilation>-Dxxx</java.tieredCompilation>
<java.useCompressedOOPS>-Dxxx</java.useCompressedOOPS>
<rhq.internal>false</rhq.internal>
+ <as7.itest.mock.http.management.server.port>32259</as7.itest.mock.http.management.server.port>
</properties>
@@ -118,6 +119,13 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.aggregate</groupId>
+ <artifactId>jetty-all</artifactId>
+ <version>8.1.8.v20121106</version>
+ <scope>test</scope>
+ </dependency>
+
<!-- For native subsystem -->
<dependency>
<groupId>org.hyperic</groupId>
@@ -588,6 +596,7 @@
<!-- only include integration tests; normal unit tests are handled above by surefire plugin -->
<include>org/rhq/modules/plugins/jbossas7/itest/**/*Test.java</include>
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
@@ -609,6 +618,7 @@
<jboss.domain.portOffset>${jboss.domain.portOffset}</jboss.domain.portOffset>
<jboss.domain.httpManagementPort>${jboss.domain.httpManagementPort}</jboss.domain.httpManagementPort>
<settings.localRepository>${settings.localRepository}</settings.localRepository>
+ <as7.itest.mock.http.management.server.port>${as7.itest.mock.http.management.server.port}</as7.itest.mock.http.management.server.port>
</systemPropertyVariables>
</configuration>
<executions>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java
new file mode 100644
index 0000000..9597d47
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java
@@ -0,0 +1,239 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.modules.plugins.jbossas7.itest.standalone;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.mockito.Mockito.when;
+import static org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper.LOG_EVENT_SOURCES_CONFIG_PROP;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.HOSTNAME;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.MANAGEMENT_CONNECTION_TIMEOUT;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.PASSWORD;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.PORT;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.USER;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.StringUtil;
+import org.rhq.modules.plugins.jbossas7.StandaloneASComponent;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * Check that management operations that might be interrupted by AS server (connection closed before the http response
+ * is sent) don't make RHQ operations fail.
+ *
+ * See https://bugzilla.redhat.com/show_bug.cgi?id=911321
+ *
+ * @author Thomas Segismont
+ */
+public class InterruptibleOperationsTest {
+
+ private static final Log LOG = LogFactory.getLog(InterruptibleOperationsTest.class);
+
+ private static final String HTTP_HOST = "localhost";
+
+ private static final int HTTP_PORT = 31159;
+
+ private static final String HTTP_PORT_VARIABLE = "as7.itest.mock.http.management.server.port";
+
+ @Mock
+ private ResourceContext resourceContext;
+
+ private StandaloneASComponent serverComponent;
+
+ private Server jettyServer;
+
+ private ExecutorService executorService;
+
+ @BeforeMethod
+ private void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ serverComponent = new TestStandaloneASComponent();
+ int httpPort = getJettyPort();
+ setupResourceContext(httpPort);
+ setupJettyServer(httpPort);
+ jettyServer.start();
+ executorService = Executors.newSingleThreadExecutor();
+ serverComponent.start(resourceContext);
+ }
+
+ private void setupJettyServer(int httpPort) {
+ jettyServer = new Server(new InetSocketAddress(HTTP_HOST, httpPort));
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath("/");
+ jettyServer.setHandler(context);
+ HttpServlet testServlet = new TestServlet();
+ context.addServlet(new ServletHolder(testServlet), "/*");
+ }
+
+ private static int getJettyPort() {
+ String httpPortVariable = System.getProperty(HTTP_PORT_VARIABLE);
+ if (StringUtil.isNotBlank(httpPortVariable)) {
+ try {
+ int port = Integer.parseInt(httpPortVariable);
+ LOG.info("Using port " + httpPortVariable + " for http server");
+ return port;
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid port variable: " + httpPortVariable);
+ }
+ }
+ LOG.info("Using default port " + String.valueOf(HTTP_PORT) + " for http server");
+ return HTTP_PORT;
+ }
+
+ private void setupResourceContext(int httpPort) {
+ when(resourceContext.getPluginConfiguration()).thenReturn(pluginConfig(httpPort));
+ when(resourceContext.getResourceKey()).thenReturn("/TestServer");
+ when(resourceContext.getSystemInformation()).thenReturn(SystemInfoFactory.createJavaSystemInfo());
+ when(resourceContext.getAvailabilityContext()).thenReturn(Mockito.mock(AvailabilityContext.class));
+ }
+
+ private Configuration pluginConfig(int httpPort) {
+ Configuration pluginConfig = new Configuration();
+ pluginConfig.setSimpleValue(HOSTNAME, "localhost");
+ pluginConfig.setSimpleValue(PORT, String.valueOf(httpPort));
+ pluginConfig.setSimpleValue(USER, "pipo");
+ pluginConfig.setSimpleValue(PASSWORD, "molo");
+ pluginConfig.setSimpleValue(MANAGEMENT_CONNECTION_TIMEOUT, "-1");
+ pluginConfig.getMap().put(LOG_EVENT_SOURCES_CONFIG_PROP, new PropertyList());
+ return pluginConfig;
+ }
+
+ @AfterMethod
+ private void tearDown() throws Exception {
+ LOG.info("Shutting down Jetty test server");
+ try {
+ if (jettyServer != null) {
+ jettyServer.stop();
+ }
+ } catch (Exception ignore) {
+ }
+ if (executorService != null) {
+ executorService.shutdownNow();
+ }
+ }
+
+ @Test(timeOut = 60 * 1000)
+ public void testReloadOperation() throws Exception {
+ OperationResult operationResult = serverComponent.invokeOperation("reload", new Configuration());
+ assertEquals(operationResult.getSimpleResult(), "Success");
+ }
+
+ @Test(timeOut = 60 * 1000)
+ public void testShutdown() throws Exception {
+ OperationResult operationResult = serverComponent.invokeOperation("shutdown", new Configuration());
+ assertEquals(operationResult.getSimpleResult(), "Success");
+ }
+
+ private class RestartJetty implements Runnable {
+ @Override
+ public void run() {
+ try {
+ jettyServer.stop();
+ } catch (Exception ignore) {
+ }
+ try {
+ Thread.sleep(SECONDS.toMillis(2));
+ } catch (Exception ignore) {
+ }
+ try {
+ jettyServer.start();
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+ private class TestServlet extends HttpServlet {
+
+ private ObjectMapper objectMapper = new ObjectMapper();
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ Operation operation = objectMapper.readValue(req.getInputStream(), Operation.class);
+ // Check if we recevied an operation which a real http management interface might interrupt
+ if (operation.getOperation().equals("reload") || operation.getOperation().equals("shutdown")) {
+ // Schedule a Jetty restart
+ executorService.submit(new RestartJetty());
+ // Then wait until Jetty is shutdown
+ try {
+ Thread.sleep(Long.MAX_VALUE);
+ } catch (InterruptedException ignore) {
+ }
+ return;
+ }
+ // Standard operation. Return simple success
+ Result result = new Result();
+ result.setOutcome("success");
+ objectMapper.writeValue(resp.getOutputStream(), result);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ doPost(req, resp);
+ }
+
+ }
+
+ // Tweak StandaloneASComponent implementation for this test case
+ private class TestStandaloneASComponent extends StandaloneASComponent {
+
+ @Override
+ public AvailabilityType getAvailability() {
+ // Avoid various management requests when component is started
+ return AvailabilityType.DOWN;
+ }
+
+ @Override
+ protected boolean waitUntilDown() throws InterruptedException {
+ // Standard implementation relies on discovery of some resource properties
+ return true;
+ }
+ }
+
+}
commit 1dba477c3fc0034a5a21960db8447fa9b43f5a56
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri May 3 17:10:53 2013 -0500
[BZ 959591] Add back specific ant version based on local pom variables to force the download of the dependency even if not directly used in the pom. Without this, the pom would assume that the version referred here is the version from parent poms. This can cause the submodule artifact to miss ant binaries if not already in the local maven repository.
(cherry picked from commit 2bb45d3c4c9d5edc71acf4380ce7a10a93937aae)
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index ddec938..3b66b92 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -37,12 +37,14 @@
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
+ <version>${ant.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
+ <version>${ant.version}</version>
<scope>provided</scope>
</dependency>
commit 17865107e38aa503c35f5a608cc1972c09bf5a73
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 3 15:01:26 2013 -0700
[BZ 958754] - d3 multi-line chart: time units should have minutes when appropriate. Added the appropriate d3 time format string and updated the nvd3 chart library neither of which fixed the issue. It appears to be an error in nvd3 chart library.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
index 1fec750..a2de9c6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
@@ -19,7 +19,7 @@
package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
/**
- * Contains the chart definition for a Bar Chart Graph.
+ * Contains the chart definition for a MultiLine Graph.
*
* @author Mike Thompson
*/
@@ -39,7 +39,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
*/
public native void drawJsniChart() /*-{
console.log("Draw NVD3 Bar jsni chart");
- console.time("multiChart")
+ console.time("multiChart");
var global = this,
chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
chartHandle = "#rChart-"+chartId,
@@ -49,7 +49,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()(),
displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
- xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I %p",
+ xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
// nvd3 defines their json models a standard way (same model for other graphs)
data = function() {
@@ -63,7 +63,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
};
$wnd.nv.addGraph(function() {
var chart = $wnd.nv.models.multiBarChart()
- .showControls(false)
+ .showControls(true)
.tooltips(true);
chart.xAxis.axisLabel(xAxisLabel)
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css b/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
index cc40dfb..163b9a8 100755
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
@@ -18,8 +18,8 @@
.nvtooltip {
position: absolute;
background-color: rgba(255,255,255,1);
- padding: 10px;
- border: 1px solid #ddd;
+ padding: 1px;
+ border: 1px solid rgba(0,0,0,.2);
z-index: 10000;
font-family: Arial;
@@ -33,12 +33,13 @@
-moz-transition-delay: 500ms;
-webkit-transition-delay: 500ms;
- -moz-box-shadow: 4px 4px 8px rgba(0,0,0,.5);
- -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,.5);
- box-shadow: 4px 4px 8px rgba(0,0,0,.5);
+ -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ box-shadow: 0 5px 10px rgba(0,0,0,.2);
- -moz-border-radius: 10px;
- border-radius: 10px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
pointer-events: none;
@@ -50,15 +51,29 @@
user-select: none;
}
+.nvtooltip.x-nvtooltip,
+.nvtooltip.y-nvtooltip {
+ padding: 8px;
+}
+
.nvtooltip h3 {
margin: 0;
- padding: 0;
+ padding: 4px 14px;
+ line-height: 18px;
+ font-weight: normal;
+ background-color: #f7f7f7;
text-align: center;
+
+ border-bottom: 1px solid #ebebeb;
+
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
}
.nvtooltip p {
margin: 0;
- padding: 0;
+ padding: 5px 14px;
text-align: center;
}
@@ -93,7 +108,7 @@ svg {
svg text {
- font: normal 12px sans-serif;
+ font: normal 12px Arial;
}
svg .title {
@@ -101,7 +116,8 @@ svg .title {
}
.nvd3 .nv-background {
- fill: none;
+ fill: white;
+ fill-opacity: 0;
/*
pointer-events: none;
*/
@@ -109,7 +125,7 @@ svg .title {
.nvd3.nv-noData {
font-size: 18px;
- font-weight: bolf;
+ font-weight: bold;
}
@@ -197,12 +213,10 @@ svg .title {
.nvd3 .nv-bars .negative rect {
zfill: brown;
- cursor: pointer;
}
.nvd3 .nv-bars rect {
zfill: steelblue;
- cursor: pointer;
fill-opacity: .75;
transition: fill-opacity 250ms linear;
@@ -226,10 +240,6 @@ svg .title {
fill: rgba(0,0,0,1);
}
-.nvd3 .nv-x.nv-axis text {
- transform: rotate(90);
-}
-
/**********
* Bars
@@ -302,10 +312,10 @@ svg .title {
.nvd3 .nv-groups path.nv-line {
fill: none;
stroke-width: 2.5px;
+ /*
stroke-linecap: round;
shape-rendering: geometricPrecision;
- /*
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
@@ -318,10 +328,10 @@ svg .title {
.nvd3 .nv-groups path.nv-area {
stroke: none;
+ /*
stroke-linecap: round;
shape-rendering: geometricPrecision;
- /*
stroke-width: 2.5px;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
@@ -350,8 +360,8 @@ svg .title {
}
.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
- fill-opacity: .5;
- stroke-opacity: .5;
+ fill-opacity: .5 !important;
+ stroke-opacity: .5 !important;
}
@@ -397,9 +407,11 @@ svg .title {
* Scatter
*/
+/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
.nvd3 .nv-groups .nv-point {
pointer-events: none;
}
+*/
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 20px;
@@ -485,21 +497,27 @@ svg .title {
* Bullet
*/
-.nvd3.nv-bullet { font: 10px sans-serif; cursor: pointer; }
-.nvd3.nv-bullet rect { fill-opacity: .6; }
-.nvd3.nv-bullet rect:hover { fill-opacity: 1; }
+.nvd3.nv-bullet { font: 10px sans-serif; }
+.nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
+.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
-.nvd3.nv-bullet .nv-measure.nv-s0 { fill: steelblue; }
-.nvd3.nv-bullet .nv-measure.nv-s1 { fill: darkblue; }
.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
.nvd3.nv-bullet .nv-subtitle { fill: #999; }
+.nvd3.nv-bullet .nv-range {
+ fill: #999;
+ fill-opacity: .4;
+}
+.nvd3.nv-bullet .nv-range:hover {
+ fill-opacity: .7;
+}
+
/**********
@@ -515,7 +533,7 @@ svg .title {
}
.nvd3.nv-sparklineplus .nv-hoverValue line {
- stroke: #f44;
+ stroke: #333;
stroke-width: 1.5px;
}
@@ -531,8 +549,11 @@ svg .title {
.nvd3.nv-sparklineplus .nv-xValue,
.nvd3.nv-sparklineplus .nv-yValue {
+ /*
stroke: #666;
- font-size: .5em;
+ */
+ stroke-width: 0;
+ font-size: .9em;
font-weight: normal;
}
@@ -540,6 +561,24 @@ svg .title {
stroke: #f66;
}
+.nvd3.nv-sparklineplus .nv-maxValue {
+ stroke: #2ca02c;
+ fill: #2ca02c;
+}
+
+.nvd3.nv-sparklineplus .nv-minValue {
+ stroke: #d62728;
+ fill: #d62728;
+}
+
+.nvd3.nv-sparklineplus .nv-currentValue {
+ /*
+ stroke: #444;
+ fill: #000;
+ */
+ font-weight: bold;
+ font-size: 1.1em;
+}
/**********
* historical stock
@@ -629,4 +668,35 @@ svg .title {
*/
}
+/**********
+* Parallel Coordinates
+*/
+
+.nvd3 .background path {
+ fill: none;
+ stroke: #ccc;
+ stroke-opacity: .4;
+ shape-rendering: crispEdges;
+}
+
+.nvd3 .foreground path {
+ fill: none;
+ stroke: steelblue;
+ stroke-opacity: .7;
+}
+
+.nvd3 .brush .extent {
+ fill-opacity: .3;
+ stroke: #fff;
+ shape-rendering: crispEdges;
+}
+
+.nvd3 .axis line, .axis path {
+ fill: none;
+ stroke: #000;
+ shape-rendering: crispEdges;
+}
+.nvd3 .axis text {
+ text-shadow: 0 1px 0 #fff;
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
index 2fe2c64..e405d2e 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
@@ -36,29 +36,34 @@ if (nv.dev) {
// Logs all arguments, and returns the last so you can test things in place
nv.log = function() {
- if (nv.dev && console.log && console.log.apply) console.log.apply(console, arguments);
+ if (nv.dev && console.log && console.log.apply)
+ console.log.apply(console, arguments)
+ else if (nv.dev && console.log && Function.prototype.bind) {
+ var log = Function.prototype.bind.call(console.log, console);
+ log.apply(console, arguments);
+ }
return arguments[arguments.length - 1];
};
nv.render = function render(step) {
- step = step || 1; // number of graphs to generate in each timout loop
+ step = step || 1; // number of graphs to generate in each timeout loop
- render.active = true;
+ nv.render.active = true;
nv.dispatch.render_start();
setTimeout(function() {
- var chart;
+ var chart, graph;
- for (var i = 0; i < step && (graph = render.queue[i]); i++) {
+ for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {
chart = graph.generate();
if (typeof graph.callback == typeof(Function)) graph.callback(chart);
nv.graphs.push(chart);
}
- render.queue.splice(0, i);
+ nv.render.queue.splice(0, i);
- if (render.queue.length) setTimeout(arguments.callee, 0);
+ if (nv.render.queue.length) setTimeout(arguments.callee, 0);
else { nv.render.active = false; nv.dispatch.render_end(); }
}, 0);
};
@@ -114,7 +119,7 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
/*****
- * A no frills tooltip implementation.
+ * A no-frills tooltip implementation.
*****/
@@ -143,39 +148,67 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
width = parseInt(container.offsetWidth),
windowWidth = nv.utils.windowSize().width,
windowHeight = nv.utils.windowSize().height,
- scrollTop = body.scrollTop,
- scrollLeft = body.scrollLeft,
+ scrollTop = window.scrollY,
+ scrollLeft = window.scrollX,
left, top;
+ windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16;
+ windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16;
+
+ var tooltipTop = function ( Elem ) {
+ var offsetTop = top;
+ do {
+ if( !isNaN( Elem.offsetTop ) ) {
+ offsetTop += (Elem.offsetTop);
+ }
+ } while( Elem = Elem.offsetParent );
+ return offsetTop;
+ }
+
+ var tooltipLeft = function ( Elem ) {
+ var offsetLeft = left;
+ do {
+ if( !isNaN( Elem.offsetLeft ) ) {
+ offsetLeft += (Elem.offsetLeft);
+ }
+ } while( Elem = Elem.offsetParent );
+ return offsetLeft;
+ }
switch (gravity) {
case 'e':
left = pos[0] - width - dist;
top = pos[1] - (height / 2);
- if (left < scrollLeft) left = pos[0] + dist;
- if (top < scrollTop) top = scrollTop + 5;
- if (top + height > scrollTop + windowHeight) top = scrollTop - height - 5;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left;
+ if (tTop < scrollTop) top = scrollTop - tTop + top;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
break;
case 'w':
left = pos[0] + dist;
top = pos[1] - (height / 2);
- if (left + width > windowWidth) left = pos[0] - width - dist;
- if (top < scrollTop) top = scrollTop + 5;
- if (top + height > scrollTop + windowHeight) top = scrollTop - height - 5;
+ if (tLeft + width > windowWidth) left = pos[0] - width - dist;
+ if (tTop < scrollTop) top = scrollTop + 5;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop - height - 5;
break;
case 'n':
- left = pos[0] - (width / 2);
+ left = pos[0] - (width / 2) - 5;
top = pos[1] + dist;
- if (left < scrollLeft) left = scrollLeft + 5;
- if (left + width > windowWidth) left = windowWidth - width - 5;
- if (top + height > scrollTop + windowHeight) top = pos[1] - height - dist;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = scrollLeft + 5;
+ if (tLeft + width > windowWidth) left = left - width/2 + 5;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
break;
case 's':
left = pos[0] - (width / 2);
top = pos[1] - height - dist;
- if (left < scrollLeft) left = scrollLeft + 5;
- if (left + width > windowWidth) left = windowWidth - width - 5;
- if (scrollTop > top) top = pos[1] + 20;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = scrollLeft + 5;
+ if (tLeft + width > windowWidth) left = left - width/2 + 5;
+ if (scrollTop > tTop) top = scrollTop;
break;
}
@@ -243,7 +276,7 @@ nv.utils.windowSize = function() {
// Easy way to bind multiple functions to window.onresize
-// TODO: give a way to remove a function after its bound, other than removing alkl of them
+// TODO: give a way to remove a function after its bound, other than removing all of them
nv.utils.windowResize = function(fun){
var oldresize = window.onresize;
@@ -255,7 +288,7 @@ nv.utils.windowResize = function(fun){
// Backwards compatible way to implement more d3-like coloring of graphs.
// If passed an array, wrap it in a function which implements the old default
-// behaviour
+// behavior
nv.utils.getColor = function(color) {
if (!arguments.length) return nv.utils.defaultColor(); //if you pass in nothing, get default colors back
@@ -263,7 +296,7 @@ nv.utils.getColor = function(color) {
return function(d, i) { return d.color || color[i % color.length]; };
else
return color;
- //can't really help it if someone passes rubish as color
+ //can't really help it if someone passes rubbish as color
}
// Default color chooser uses the index of an object as before.
@@ -328,7 +361,7 @@ nv.models.axis = function() {
;
var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 60 //only used for tickLabel currently
+ , width = 75 //only used for tickLabel currently
, height = 60 //only used for tickLabel currently
, scale = d3.scale.linear()
, axisLabelText = null
@@ -337,6 +370,7 @@ nv.models.axis = function() {
, rotateLabels = 0
, rotateYLabel = true
, staggerLabels = false
+ , isOrdinal = false
, ticks = null
;
@@ -398,11 +432,11 @@ nv.models.axis = function() {
axisLabel.exit().remove();
switch (axis.orient()) {
case 'top':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
- .attr('text-anchor', 'middle')
- .attr('y', 0);
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));
axisLabel
+ .attr('text-anchor', 'middle')
+ .attr('y', 0)
.attr('x', w/2);
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -428,7 +462,7 @@ nv.models.axis = function() {
}
break;
case 'bottom':
- var xLabelMargin = 30;
+ var xLabelMargin = 36;
var maxTextWidth = 30;
var xTicks = g.selectAll('g').select("text");
if (rotateLabels%360) {
@@ -445,20 +479,22 @@ nv.models.axis = function() {
.attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })
.attr('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
}
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
- .attr('text-anchor', 'middle')
- .attr('y', xLabelMargin);
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));
axisLabel
+ .attr('text-anchor', 'middle')
+ .attr('y', xLabelMargin)
.attr('x', w/2);
if (showMaxMin) {
+ //if (showMaxMin && !isOrdinal) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
+ //.data(scale.domain())
+ .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);
axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');
axisMaxMin.exit().remove();
axisMaxMin
.attr('transform', function(d,i) {
- return 'translate(' + scale(d) + ',0)'
+ return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
})
.select('text')
.attr('dy', '.71em')
@@ -471,7 +507,9 @@ nv.models.axis = function() {
});
d3.transition(axisMaxMin)
.attr('transform', function(d,i) {
- return 'translate(' + scale.range()[i] + ',0)'
+ //return 'translate(' + scale.range()[i] + ',0)'
+ //return 'translate(' + scale(d) + ',0)'
+ return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
});
}
if (staggerLabels)
@@ -480,11 +518,11 @@ nv.models.axis = function() {
break;
case 'right':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
+ axisLabel
.attr('text-anchor', rotateYLabel ? 'middle' : 'begin')
.attr('transform', rotateYLabel ? 'rotate(90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.right,width) - 12) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
- axisLabel
+ .attr('y', rotateYLabel ? (-Math.max(margin.right,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
.attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding());
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -514,11 +552,19 @@ nv.models.axis = function() {
}
break;
case 'left':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
+ /*
+ //For dynamically placing the label. Can be used with dynamically-sized chart axis margins
+ var yTicks = g.selectAll('g').select("text");
+ yTicks.each(function(d,i){
+ var labelPadding = this.getBBox().width + axis.tickPadding() + 16;
+ if(labelPadding > width) width = labelPadding;
+ });
+ */
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
+ axisLabel
.attr('text-anchor', rotateYLabel ? 'middle' : 'end')
.attr('transform', rotateYLabel ? 'rotate(-90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 12) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
- axisLabel
+ .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
.attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding());
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -552,27 +598,41 @@ nv.models.axis = function() {
.text(function(d) { return d });
- //check if max and min overlap other values, if so, hide the values that overlap
if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {
+ //check if max and min overlap other values, if so, hide the values that overlap
g.selectAll('g') // the g's wrapping each tick
.each(function(d,i) {
+ d3.select(this).select('text').attr('opacity', 1);
if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!
if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
- d3.select(this).remove();
- else
- d3.select(this).select('text').remove(); // Don't remove the ZERO line!!
+ d3.select(this).attr('opacity', 0);
+
+ d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!
}
});
+
+ //if Max and Min = 0 only show min, Issue #281
+ if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0)
+ wrap.selectAll('g.nv-axisMaxMin')
+ .style('opacity', function(d,i) { return !i ? 1 : 0 });
+
}
if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {
var maxMinRange = [];
wrap.selectAll('g.nv-axisMaxMin')
.each(function(d,i) {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - this.getBBox().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
- else // i==0, min position
- maxMinRange.push(scale(d) + this.getBBox().width + 4)
+ try {
+ if (i) // i== 1, max position
+ maxMinRange.push(scale(d) - this.getBBox().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
+ else // i==0, min position
+ maxMinRange.push(scale(d) + this.getBBox().width + 4)
+ }catch (err) {
+ if (i) // i== 1, max position
+ maxMinRange.push(scale(d) - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
+ else // i==0, min position
+ maxMinRange.push(scale(d) + 4)
+ }
});
g.selectAll('g') // the g's wrapping each tick
.each(function(d,i) {
@@ -660,6 +720,7 @@ nv.models.axis = function() {
if (!arguments.length) return scale;
scale = _;
axis.scale(scale);
+ isOrdinal = typeof scale.rangeBands === 'function';
d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands');
return chart;
}
@@ -705,6 +766,7 @@ nv.models.historicalBar = function() {
, getY = function(d) { return d.y }
, forceX = []
, forceY = [0]
+ , padData = false
, clipEdge = true
, color = nv.utils.defaultColor()
, xDomain
@@ -726,9 +788,13 @@ nv.models.historicalBar = function() {
// Setup Scales
x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ))
- .range([0, availableWidth]);
- y .domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
+ if (padData)
+ x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
+
+ y .domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
.range([availableHeight, 0]);
// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
@@ -846,13 +912,20 @@ nv.models.historicalBar = function() {
bars
.attr('fill', function(d,i) { return color(d, i); })
.attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - ((availableWidth / data[0].values.length) * .5)) + ',0)'; }) //TODO: better width calculations that don't assume always uniform data spacing;w
+ .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) //TODO: better width calculations that don't assume always uniform data spacing;w
.attr('width', (availableWidth / data[0].values.length) * .9 )
d3.transition(bars)
- .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
- .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });
+ //.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
+ .attr('y', function(d,i) {
+ return getY(d,i) < 0 ?
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 :
+ y(getY(d,i))
+ })
+ .attr('height', function(d,i) { return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) });
//.order(); // not sure if this makes any sense for this model
});
@@ -936,6 +1009,12 @@ nv.models.historicalBar = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -980,6 +1059,7 @@ nv.models.bullet = function() {
, width = 380
, height = 30
, tickFormat = null
+ , color = nv.utils.getColor(['#1f77b4'])
, dispatch = d3.dispatch('elementMouseover', 'elementMouseout')
;
@@ -1002,7 +1082,7 @@ nv.models.bullet = function() {
// Compute the new x-scale.
var x1 = d3.scale.linear()
- .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
+ .domain( d3.extent(d3.merge([forceX, rangez])) )
.range(reverse ? [availableWidth, 0] : [0, availableWidth]);
// Retrieve the old x-scale, if this is an update.
@@ -1013,6 +1093,11 @@ nv.models.bullet = function() {
// Stash the new scale.
this.__chart__ = x1;
+
+ var rangeMin = d3.min(rangez), //rangez[2]
+ rangeMax = d3.max(rangez), //rangez[0]
+ rangeAvg = rangez[1];
+
//------------------------------------------------------------
@@ -1024,6 +1109,12 @@ nv.models.bullet = function() {
var gEnter = wrapEnter.append('g');
var g = wrap.select('g');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeMin');
+ gEnter.append('rect').attr('class', 'nv-measure');
+ gEnter.append('path').attr('class', 'nv-markerTriangle');
+
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
//------------------------------------------------------------
@@ -1032,8 +1123,118 @@ nv.models.bullet = function() {
var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
+ var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },
+ xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };
+
+
+ g.select('rect.nv-rangeMax')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))
+ .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))
+ .datum(rangeMax > 0 ? rangeMax : rangeMin)
+ /*
+ .attr('x', rangeMin < 0 ?
+ rangeMax > 0 ?
+ x1(rangeMin)
+ : x1(rangeMax)
+ : x1(0))
+ */
+
+ g.select('rect.nv-rangeAvg')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeAvg))
+ .attr('x', xp1(rangeAvg))
+ .datum(rangeAvg)
+ /*
+ .attr('width', rangeMax <= 0 ?
+ x1(rangeMax) - x1(rangeAvg)
+ : x1(rangeAvg) - x1(rangeMin))
+ .attr('x', rangeMax <= 0 ?
+ x1(rangeAvg)
+ : x1(rangeMin))
+ */
+
+ g.select('rect.nv-rangeMin')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeMax))
+ .attr('x', xp1(rangeMax))
+ .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))
+ .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))
+ .datum(rangeMax > 0 ? rangeMin : rangeMax)
+ /*
+ .attr('width', rangeMax <= 0 ?
+ x1(rangeAvg) - x1(rangeMin)
+ : x1(rangeMax) - x1(rangeAvg))
+ .attr('x', rangeMax <= 0 ?
+ x1(rangeMin)
+ : x1(rangeAvg))
+ */
+
+ g.select('rect.nv-measure')
+ .style('fill', color)
+ .attr('height', availableHeight / 3)
+ .attr('y', availableHeight / 3)
+ .attr('width', measurez < 0 ?
+ x1(0) - x1(measurez[0])
+ : x1(measurez[0]) - x1(0))
+ .attr('x', xp1(measurez))
+ .on('mouseover', function() {
+ dispatch.elementMouseover({
+ value: measurez[0],
+ label: 'Current',
+ pos: [x1(measurez[0]), availableHeight/2]
+ })
+ })
+ .on('mouseout', function() {
+ dispatch.elementMouseout({
+ value: measurez[0],
+ label: 'Current'
+ })
+ })
+
+ var h3 = availableHeight / 6;
+ if (markerz[0]) {
+ g.selectAll('path.nv-markerTriangle')
+ .attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' })
+ .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')
+ .on('mouseover', function() {
+ dispatch.elementMouseover({
+ value: markerz[0],
+ label: 'Previous',
+ pos: [x1(markerz[0]), availableHeight/2]
+ })
+ })
+ .on('mouseout', function() {
+ dispatch.elementMouseout({
+ value: markerz[0],
+ label: 'Previous'
+ })
+ });
+ } else {
+ g.selectAll('path.nv-markerTriangle').remove();
+ }
+
+
+ wrap.selectAll('.nv-range')
+ .on('mouseover', function(d,i) {
+ var label = !i ? "Maximum" : i == 1 ? "Mean" : "Minimum";
+
+ dispatch.elementMouseover({
+ value: d,
+ label: label,
+ pos: [x1(d), availableHeight/2]
+ })
+ })
+ .on('mouseout', function(d,i) {
+ var label = !i ? "Maximum" : i == 1 ? "Mean" : "Minimum";
+ dispatch.elementMouseout({
+ value: d,
+ label: label
+ })
+ })
+/* // THIS IS THE PREVIOUS BULLET IMPLEMENTATION, WILL REMOVE SHORTLY
// Update the range rects.
var range = g.selectAll('rect.nv-range')
.data(rangez);
@@ -1069,6 +1270,7 @@ nv.models.bullet = function() {
measure.enter().append('rect')
.attr('class', function(d, i) { return 'nv-measure nv-s' + i; })
+ .style('fill', function(d,i) { return color(d,i ) })
.attr('width', w0)
.attr('height', availableHeight / 3)
.attr('x', reverse ? x0 : 0)
@@ -1119,13 +1321,14 @@ nv.models.bullet = function() {
});
d3.transition(marker)
- .attr('transform', function(d) { return 'translate(' + x1(d) + ',' + (availableHeight / 2) + ')' });
+ .attr('transform', function(d) { return 'translate(' + (x1(d) - x1(0)) + ',' + (availableHeight / 2) + ')' });
marker.exit().remove();
+*/
});
- d3.timer.flush();
+ // d3.timer.flush(); // Not needed?
return chart;
}
@@ -1199,6 +1402,12 @@ nv.models.bullet = function() {
return chart;
};
+ chart.color = function(_) {
+ if (!arguments.length) return color;
+ color = nv.utils.getColor(_);
+ return chart;
+ };
+
//============================================================
@@ -1271,9 +1480,7 @@ nv.models.bulletChart = function() {
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
- /*
- // Disabled until I figure out a better way to check for no data with the bullet chart
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
+ if (!d || !ranges.call(this, d, i)) {
var noDataText = container.selectAll('.nv-noData').data([noData]);
noDataText.enter().append('text')
@@ -1283,14 +1490,13 @@ nv.models.bulletChart = function() {
noDataText
.attr('x', margin.left + availableWidth / 2)
- .attr('y', margin.top + availableHeight / 2)
+ .attr('y', 18 + margin.top + availableHeight / 2)
.text(function(d) { return d });
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
- */
//------------------------------------------------------------
@@ -1382,7 +1588,7 @@ nv.models.bulletChart = function() {
// Update the tick groups.
var tick = g.selectAll('g.nv-tick')
- .data(x1.ticks( availableWidth / 100 ), function(d) {
+ .data(x1.ticks( availableWidth / 50 ), function(d) {
return this.textContent || format(d);
});
@@ -1467,6 +1673,8 @@ nv.models.bulletChart = function() {
chart.dispatch = dispatch;
chart.bullet = bullet;
+ d3.rebind(chart, bullet, 'color');
+
// left, right, top, bottom
chart.orient = function(x) {
if (!arguments.length) return orient;
@@ -1577,13 +1785,15 @@ nv.models.cumulativeLineChart = function() {
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, id = lines.id()
+ , state = { index: 0, rescaleY: rescaleY }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -1610,24 +1820,32 @@ nv.models.cumulativeLineChart = function() {
nv.tooltip.show([left, top], content, null, null, offsetElement);
};
-
+/*
+ //Moved to see if we can get better behavior to fix issue #315
var indexDrag = d3.behavior.drag()
.on('dragstart', dragStart)
.on('drag', dragMove)
.on('dragend', dragEnd);
- function dragStart(d,i) {}
+ function dragStart(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'ew-resize');
+ }
function dragMove(d,i) {
d.x += d3.event.dx;
d.i = Math.round(dx.invert(d.x));
d3.select(this).attr('transform', 'translate(' + dx(d.i) + ',0)');
+ chart.update();
}
function dragEnd(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'auto');
chart.update();
}
+*/
//============================================================
@@ -1646,6 +1864,48 @@ nv.models.cumulativeLineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
+
+ var indexDrag = d3.behavior.drag()
+ .on('dragstart', dragStart)
+ .on('drag', dragMove)
+ .on('dragend', dragEnd);
+
+
+ function dragStart(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'ew-resize');
+ }
+
+ function dragMove(d,i) {
+ index.x = d3.event.x;
+ index.i = Math.round(dx.invert(index.x));
+ updateZero();
+ }
+
+ function dragEnd(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'auto');
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+ }
+
+
+
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -1684,6 +1944,9 @@ nv.models.cumulativeLineChart = function() {
.map(function(series,i) {
var initialDomain = d3.extent(series.values, lines.y());
+ //account for series being disabled when losing 95% or more
+ if (initialDomain[0] < -.95) initialDomain[0] = -.95;
+
return [
(initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
(initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
@@ -1720,6 +1983,7 @@ nv.models.cumulativeLineChart = function() {
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
+ gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
@@ -1771,9 +2035,30 @@ nv.models.cumulativeLineChart = function() {
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+ // Show error if series goes below 100%
+ var tempDisabled = data.filter(function(d) { return d.tempDisabled });
+
+ wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
+ if (tempDisabled.length) {
+ wrap.append('text').attr('class', 'tempDisabled')
+ .attr('x', availableWidth / 2)
+ .attr('y', '-.71em')
+ .style('text-anchor', 'end')
+ .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
+ }
+
+
+
//------------------------------------------------------------
// Main Chart Component(s)
+ gEnter.select('.nv-background')
+ .append('rect');
+
+ g.select('.nv-background rect')
+ .attr('width', availableWidth)
+ .attr('height', availableHeight);
+
lines
//.x(function(d) { return d.x })
.y(function(d) { return d.display.y })
@@ -1781,14 +2066,15 @@ nv.models.cumulativeLineChart = function() {
.height(availableHeight)
.color(data.map(function(d,i) {
return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled }));
var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
+ .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
- d3.transition(linesWrap).call(lines);
+ //d3.transition(linesWrap).call(lines);
+ linesWrap.call(lines);
var indexLine = linesWrap.selectAll('.nv-indexLine')
@@ -1812,7 +2098,8 @@ nv.models.cumulativeLineChart = function() {
xAxis
.scale(x)
- .ticks( availableWidth / 100 )
+ //Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)
+ .ticks( Math.min(data[0].values.length,availableWidth/70) )
.tickSize(-availableHeight, 0);
g.select('.nv-x.nv-axis')
@@ -1836,11 +2123,46 @@ nv.models.cumulativeLineChart = function() {
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
+
+ function updateZero() {
+ indexLine
+ .data([index]);
+
+ chart.update();
+ }
+
+ g.select('.nv-background rect')
+ .on('click', function() {
+ index.x = d3.mouse(this)[0];
+ index.i = Math.round(dx.invert(index.x));
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+
+ updateZero();
+ });
+
+ lines.dispatch.on('elementClick', function(e) {
+ index.i = e.pointIndex;
+ index.x = dx(index.i);
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+
+ updateZero();
+ });
+
controls.dispatch.on('legendClick', function(d,i) {
d.disabled = !d.disabled;
rescaleY = !d.disabled;
- selection.transition().call(chart);
+ state.rescaleY = rescaleY;
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ selection.call(chart);
});
@@ -1855,7 +2177,11 @@ nv.models.cumulativeLineChart = function() {
});
}
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ selection.call(chart);
});
/*
@@ -1875,6 +2201,37 @@ nv.models.cumulativeLineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+
+ if (typeof e.index !== 'undefined') {
+ index.i = e.index;
+ index.x = dx(index.i);
+
+ state.index = e.index;
+
+ indexLine
+ .data([index]);
+ }
+
+
+ if (typeof e.rescaleY !== 'undefined') {
+ rescaleY = e.rescaleY;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
});
@@ -1944,6 +2301,12 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.rescaleY = function(_) {
+ if (!arguments.length) return rescaleY;
+ rescaleY = _
+ return rescaleY;
+ };
+
chart.showControls = function(_) {
if (!arguments.length) return showControls;
showControls = _;
@@ -1968,6 +2331,18 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -1986,16 +2361,20 @@ nv.models.cumulativeLineChart = function() {
return data.map(function(line, i) {
var v = lines.y()(line.values[idx], idx);
+ //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
+ if (v < -.95) {
+ //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
+ line.tempDisabled = true;
+ return line;
+ }
+
+ line.tempDisabled = false;
+
line.values = line.values.map(function(point, pointIndex) {
point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };
return point;
})
- /*
- TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
- if (v < -.9) {
- //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically currect till it hits 100)
- }
- */
+
return line;
})
}
@@ -2027,6 +2406,7 @@ nv.models.discreteBar = function() {
, xDomain
, yDomain
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
+ , rectClass = 'discreteBar'
;
//============================================================
@@ -2128,7 +2508,7 @@ nv.models.discreteBar = function() {
var barsEnter = bars.enter().append('g')
.attr('transform', function(d,i,j) {
- return 'translate(' + x(getX(d,i)) + ', ' + y(0) + ')'
+ return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'
})
.on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
d3.select(this).classed('hover', true);
@@ -2180,13 +2560,13 @@ nv.models.discreteBar = function() {
barsEnter.append('rect')
.attr('height', 0)
- .attr('width', x.rangeBand() / data.length )
+ .attr('width', x.rangeBand() * .9 / data.length )
if (showValues) {
barsEnter.append('text')
.attr('text-anchor', 'middle')
bars.select('text')
- .attr('x', x.rangeBand() / 2)
+ .attr('x', x.rangeBand() * .9 / 2)
.attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })
.text(function(d,i) { return valueFormat(getY(d,i)) });
} else {
@@ -2198,16 +2578,24 @@ nv.models.discreteBar = function() {
.style('fill', function(d,i) { return d.color || color(d,i) })
.style('stroke', function(d,i) { return d.color || color(d,i) })
.select('rect')
- .attr('width', x.rangeBand() / data.length);
+ .attr('class', rectClass)
+ .attr('width', x.rangeBand() * .9 / data.length);
d3.transition(bars)
//.delay(function(d,i) { return i * 1200 / data[0].values.length })
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ', ' + (getY(d,i) < 0 ? y(0) : y(getY(d,i))) + ')'
+ .attr('transform', function(d,i) {
+ var left = x(getX(d,i)) + x.rangeBand() * .05,
+ top = getY(d,i) < 0 ?
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 : //make 1 px positive bars show up above y=0
+ y(getY(d,i));
+
+ return 'translate(' + left + ', ' + top + ')'
})
- .select('rect')
- .attr('height', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
- });
+ .select('rect')
+ .attr('height', function(d,i) {
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)) || 1)
+ });
//store old scales for use in transitions on update
@@ -2313,6 +2701,11 @@ nv.models.discreteBar = function() {
return chart;
};
+ chart.rectClass= function(_) {
+ if (!arguments.length) return rectClass;
+ rectClass = _;
+ return chart;
+ }
//============================================================
@@ -2343,7 +2736,7 @@ nv.models.discreteBarChart = function() {
, x
, y
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate')
;
xAxis
@@ -2388,7 +2781,7 @@ nv.models.discreteBarChart = function() {
- margin.top - margin.bottom;
- chart.update = function() { selection.transition().call(chart); };
+ chart.update = function() { dispatch.beforeUpdate(); selection.transition().call(chart); };
chart.container = this;
@@ -2486,10 +2879,11 @@ nv.models.discreteBarChart = function() {
var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
- if (staggerLabels)
+ if (staggerLabels) {
xTicks
.selectAll('text')
- .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '0' : '12') + ')' })
+ .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
+ }
yAxis
.scale(y)
@@ -2753,7 +3147,6 @@ nv.models.distribution = function() {
return chart;
}
-
nv.models.indentedTree = function() {
//============================================================
@@ -2766,6 +3159,7 @@ nv.models.indentedTree = function() {
, color = nv.utils.defaultColor()
, id = Math.floor(Math.random() * 10000)
, header = true
+ , filterZero = false
, noData = "No Data Available."
, childIndent = 20
, columns = [{key:'key', label: 'Name', type:'text'}] //TODO: consider functions like chart.addColumn, chart.removeColumn, instead of a block like this
@@ -2777,30 +3171,32 @@ nv.models.indentedTree = function() {
//============================================================
+ var idx = 0;
function chart(selection) {
selection.each(function(data) {
- var i = 0,
- depth = 1;
+ var depth = 1,
+ container = d3.select(this);
var tree = d3.layout.tree()
.children(function(d) { return d.values })
.size([height, childIndent]); //Not sure if this is needed now that the result is HTML
- chart.update = function() { selection.transition().call(chart) };
- chart.container = this;
+ chart.update = function() { container.transition().duration(600).call(chart) };
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
-
- if (!data[0].key) data[0].key = noData;
+ if (!data[0]) data[0] = {key: noData};
//------------------------------------------------------------
var nodes = tree.nodes(data[0]);
+ // nodes.map(function(d) {
+ // d.id = i++;
+ // })
//------------------------------------------------------------
// Setup containers and skeleton of chart
@@ -2830,7 +3226,7 @@ nv.models.indentedTree = function() {
var tbody = table.selectAll('tbody')
- .data(function(d) {return d });
+ .data(function(d) { return d });
tbody.enter().append('tbody');
@@ -2842,12 +3238,12 @@ nv.models.indentedTree = function() {
// Update the nodes…
var node = tbody.selectAll('tr')
- .data(function(d) { return d }, function(d) { return d.id || (d.id == ++i)});
+ // .data(function(d) { return d; }, function(d) { return d.id || (d.id == ++i)});
+ .data(function(d) { return d.filter(function(d) { return (filterZero && !d.children) ? filterZero(d) : true; } )}, function(d,i) { return d.id || (d.id || ++idx)});
//.style('display', 'table-row'); //TODO: see if this does anything
node.exit().remove();
-
node.select('img.nv-treeicon')
.attr('src', icon)
.classed('folded', folded);
@@ -2880,22 +3276,24 @@ nv.models.indentedTree = function() {
.text(function(d) { return column.format ? column.format(d) :
(d[column.key] || '-') });
- if (column.showCount)
+ if (column.showCount) {
nodeName.append('span')
- .attr('class', 'nv-childrenCount')
- .text(function(d) {
- return ((d.values && d.values.length) || (d._values && d._values.length)) ?
- '(' + ((d.values && d.values.length) || (d._values && d._values.length)) + ')'
- : ''
- });
+ .attr('class', 'nv-childrenCount');
+ node.selectAll('span.nv-childrenCount').text(function(d) {
+ return ((d.values && d.values.length) || (d._values && d._values.length)) ? //If this is a parent
+ '(' + ((d.values && (d.values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length)) //If children are in values check its children and filter
+ || (d._values && d._values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length) //Otherwise, do the same, but with the other name, _values...
+ || 0) + ')' //This is the catch-all in case there are no children after a filter
+ : '' //If this is not a parent, just give an empty string
+ });
+ }
if (column.click)
nodeName.select('span').on('click', column.click);
});
-
node
.order()
.on('click', function(d) {
@@ -3031,6 +3429,12 @@ nv.models.indentedTree = function() {
return chart;
};
+ chart.filterZero = function(_) {
+ if (!arguments.length) return filterZero;
+ filterZero = _;
+ return chart;
+ };
+
chart.columns = function(_) {
if (!arguments.length) return columns;
columns = _;
@@ -3059,8 +3463,7 @@ nv.models.indentedTree = function() {
return chart;
-}
-nv.models.legend = function() {
+};nv.models.legend = function() {
//============================================================
// Public Variables with Default Settings
@@ -3270,24 +3673,24 @@ nv.models.line = function() {
// Public Variables with Default Settings
//------------------------------------------------------------
+ var scatter = nv.models.scatter()
+ ;
+
var margin = {top: 0, right: 0, bottom: 0, left: 0}
, width = 960
, height = 500
, color = nv.utils.defaultColor() // a function that returns a color
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID incase user doesn't select one
, getX = function(d) { return d.x } // accessor to get the x value from a data point
, getY = function(d) { return d.y } // accessor to get the y value from a data point
- , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continous when it is not defined
+ , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined
, isArea = function(d) { return d.area } // decides if a line is an area or just a line
, clipEdge = false // if true, masks lines within x and y scale
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, interpolate = "linear" // controls the line interpolation
- , scatter = nv.models.scatter()
;
scatter
- .id(id)
.size(16) // default size
.sizeDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
;
@@ -3354,16 +3757,16 @@ nv.models.line = function() {
defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
+ .attr('id', 'nv-edge-clip-' + scatter.id())
.append('rect');
- wrap.select('#nv-edge-clip-' + id + ' rect')
+ wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
.attr('width', availableWidth)
.attr('height', availableHeight);
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
+ g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
scatterWrap
- .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
+ .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
@@ -3474,7 +3877,7 @@ nv.models.line = function() {
chart.dispatch = scatter.dispatch;
chart.scatter = scatter;
- d3.rebind(chart, scatter, 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius');
+ d3.rebind(chart, scatter, 'id', 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius', 'padData');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -3524,12 +3927,6 @@ nv.models.line = function() {
return chart;
};
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
chart.interpolate = function(_) {
if (!arguments.length) return interpolate;
interpolate = _;
@@ -3566,6 +3963,7 @@ nv.models.lineChart = function() {
, legend = nv.models.legend()
;
+//set margin.right to 23 to fit dates on the x-axis within the chart
var margin = {top: 30, right: 20, bottom: 50, left: 60}
, color = nv.utils.defaultColor()
, width = null
@@ -3578,13 +3976,15 @@ nv.models.lineChart = function() {
}
, x
, y
+ , state = {}
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -3637,6 +4037,19 @@ nv.models.lineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -3770,6 +4183,9 @@ nv.models.lineChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -3789,6 +4205,20 @@ nv.models.lineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
});
@@ -3876,6 +4306,18 @@ nv.models.lineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -3917,16 +4359,23 @@ nv.models.linePlusBarChart = function() {
, x
, y1
, y2
+ , state = {}
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
+ bars
+ .padData(true)
+ ;
lines
.clipEdge(false)
+ .padData(true)
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
+ .highlightZero(false)
;
y1Axis
.orient('left')
@@ -3943,14 +4392,15 @@ nv.models.linePlusBarChart = function() {
//------------------------------------------------------------
var showTooltip = function(e, offsetElement) {
- var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
- top = e.pos[1] + ( offsetElement.offsetTop || 0),
- x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
- y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
- content = tooltip(e.series.key, x, y, e, chart);
+ var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
+ top = e.pos[1] + ( offsetElement.offsetTop || 0),
+ x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
+ y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
+ content = tooltip(e.series.key, x, y, e, chart);
- nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
- };
+ nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
+ }
+ ;
//------------------------------------------------------------
@@ -3969,6 +4419,19 @@ nv.models.linePlusBarChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -3997,51 +4460,19 @@ nv.models.linePlusBarChart = function() {
//------------------------------------------------------------
// Setup Scales
- x = xAxis.scale();
- y1 = bars.yScale();
- y2 = lines.yScale();
-
var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
+ //x = xAxis.scale();
+ x = dataLines.filter(function(d) { return !d.disabled; }).length && dataLines.filter(function(d) { return !d.disabled; })[0].values.length ? lines.xScale() : bars.xScale();
+ //x = dataLines.filter(function(d) { return !d.disabled; }).length ? lines.xScale() : bars.xScale(); //old code before change above
+ y1 = bars.yScale();
+ y2 = lines.yScale();
- //TODO: try to remove x scale computation from this layer
-
- var series1 = data.filter(function(d) { return !d.disabled && d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
+ //------------------------------------------------------------
- var series2 = data.filter(function(d) { return !d.disabled && !d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .range([0, availableWidth]);
-
-
-
- /*
- x .domain(d3.extent(d3.merge(data.map(function(d) { return d.values })), getX ))
- .range([0, availableWidth]);
-
- y1 .domain(d3.extent(d3.merge(dataBars), function(d) { return d.y } ))
- .range([availableHeight, 0]);
-
- y2 .domain(d3.extent(d3.merge(dataLines), function(d) { return d.y } ))
- .range([availableHeight, 0]);
- */
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
+ //------------------------------------------------------------
+ // Setup containers and skeleton of chart
var wrap = d3.select(this).selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
@@ -4111,7 +4542,7 @@ nv.models.linePlusBarChart = function() {
.datum(dataBars.length ? dataBars : [{values:[]}])
var linesWrap = g.select('.nv-linesWrap')
- .datum(!dataLines[0].disabled ? dataLines : [{values:[]}] );
+ .datum(dataLines[0] && !dataLines[0].disabled ? dataLines : [{values:[]}] );
//.datum(!dataLines[0].disabled ? dataLines : [{values:dataLines[0].values.map(function(d) { return [d[0], null] }) }] );
d3.transition(barsWrap).call(bars);
@@ -4124,6 +4555,7 @@ nv.models.linePlusBarChart = function() {
// Setup Axes
xAxis
+ .scale(x)
.ticks( availableWidth / 100 )
.tickSize(-availableHeight, 0);
@@ -4150,7 +4582,8 @@ nv.models.linePlusBarChart = function() {
g.select('.nv-y2.nv-axis')
.style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
+ .attr('transform', 'translate(' + availableWidth + ',0)');
+ //.attr('transform', 'translate(' + x.range()[1] + ',0)');
d3.transition(g.select('.nv-y2.nv-axis'))
.call(y2Axis);
@@ -4173,6 +4606,9 @@ nv.models.linePlusBarChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -4180,6 +4616,21 @@ nv.models.linePlusBarChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -4297,6 +4748,18 @@ nv.models.linePlusBarChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -4527,33 +4990,614 @@ nv.models.lineWithFocusChart = function() {
//------------------------------------------------------------
- /*
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
+ /*
+ var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
+ .datum(data.filter(function(d) { return !d.disabled }))
+
+ d3.transition(focusLinesWrap).call(lines);
+ */
+
+
+ //------------------------------------------------------------
+ // Setup Main (Focus) Axes
+
+ xAxis
+ .scale(x)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight1, 0);
+
+ yAxis
+ .scale(y)
+ .ticks( availableHeight1 / 36 )
+ .tickSize( -availableWidth, 0);
+
+ g.select('.nv-focus .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + availableHeight1 + ')');
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Brush
+
+ brush
+ .x(x2)
+ .on('brush', onBrush);
+
+ if (brushExtent) brush.extent(brushExtent);
+
+ var brushBG = g.select('.nv-brushBackground').selectAll('g')
+ .data([brushExtent || brush.extent()])
+
+ var brushBGenter = brushBG.enter()
+ .append('g');
+
+ brushBGenter.append('rect')
+ .attr('class', 'left')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight2);
+
+ brushBGenter.append('rect')
+ .attr('class', 'right')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight2);
+
+ gBrush = g.select('.nv-x.nv-brush')
+ .call(brush);
+ gBrush.selectAll('rect')
+ //.attr('y', -5)
+ .attr('height', availableHeight2);
+ gBrush.selectAll('.resize').append('path').attr('d', resizePath);
+
+ onBrush();
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Secondary (Context) Axes
+
+ x2Axis
+ .scale(x2)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight2, 0);
+
+ g.select('.nv-context .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ d3.transition(g.select('.nv-context .nv-x.nv-axis'))
+ .call(x2Axis);
+
+
+ y2Axis
+ .scale(y2)
+ .ticks( availableHeight2 / 36 )
+ .tickSize( -availableWidth, 0);
+
+ d3.transition(g.select('.nv-context .nv-y.nv-axis'))
+ .call(y2Axis);
+
+ g.select('.nv-context .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+
+ //------------------------------------------------------------
+
+
+ //============================================================
+ // Event Handling/Dispatching (in chart's scope)
+ //------------------------------------------------------------
+
+ legend.dispatch.on('legendClick', function(d,i) {
+ d.disabled = !d.disabled;
+
+ if (!data.filter(function(d) { return !d.disabled }).length) {
+ data.map(function(d) {
+ d.disabled = false;
+ wrap.selectAll('.nv-series').classed('disabled', false);
+ return d;
+ });
+ }
+
+ selection.transition().call(chart);
+ });
+
+ dispatch.on('tooltipShow', function(e) {
+ if (tooltips) showTooltip(e, that.parentNode);
+ });
+
+ //============================================================
+
+
+ //============================================================
+ // Functions
+ //------------------------------------------------------------
+
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = availableHeight2 / 3;
+ return 'M' + (.5 * x) + ',' + y
+ + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
+ + 'V' + (2 * y - 6)
+ + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
+ + 'Z'
+ + 'M' + (2.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8)
+ + 'M' + (4.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8);
+ }
+
+
+ function updateBrushBG() {
+ if (!brush.empty()) brush.extent(brushExtent);
+ brushBG
+ .data([brush.empty() ? x2.domain() : brushExtent])
+ .each(function(d,i) {
+ var leftWidth = x2(d[0]) - x.range()[0],
+ rightWidth = x.range()[1] - x2(d[1]);
+ d3.select(this).select('.left')
+ .attr('width', leftWidth < 0 ? 0 : leftWidth);
+
+ d3.select(this).select('.right')
+ .attr('x', x2(d[1]))
+ .attr('width', rightWidth < 0 ? 0 : rightWidth);
+ });
+ }
+
+
+ function onBrush() {
+ brushExtent = brush.empty() ? null : brush.extent();
+ extent = brush.empty() ? x2.domain() : brush.extent();
+
+
+ dispatch.brush({extent: extent, brush: brush});
+
+
+ updateBrushBG();
+
+ // Update Main (Focus)
+ var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
+ .datum(
+ data
+ .filter(function(d) { return !d.disabled })
+ .map(function(d,i) {
+ return {
+ key: d.key,
+ values: d.values.filter(function(d,i) {
+ return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
+ })
+ }
+ })
+ );
+ d3.transition(focusLinesWrap).call(lines);
+
+
+ // Update Main (Focus) Axes
+ d3.transition(g.select('.nv-focus .nv-x.nv-axis'))
+ .call(xAxis);
+ d3.transition(g.select('.nv-focus .nv-y.nv-axis'))
+ .call(yAxis);
+ }
+
+ //============================================================
+
+
+ });
+
+ return chart;
+ }
+
+
+ //============================================================
+ // Event Handling/Dispatching (out of chart's scope)
+ //------------------------------------------------------------
+
+ lines.dispatch.on('elementMouseover.tooltip', function(e) {
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
+ dispatch.tooltipShow(e);
+ });
+
+ lines.dispatch.on('elementMouseout.tooltip', function(e) {
+ dispatch.tooltipHide(e);
+ });
+
+ dispatch.on('tooltipHide', function() {
+ if (tooltips) nv.tooltip.cleanup();
+ });
+
+ //============================================================
+
+
+ //============================================================
+ // Expose Public Variables
+ //------------------------------------------------------------
+
+ // expose chart's sub-components
+ chart.dispatch = dispatch;
+ chart.legend = legend;
+ chart.lines = lines;
+ chart.lines2 = lines2;
+ chart.xAxis = xAxis;
+ chart.yAxis = yAxis;
+ chart.x2Axis = x2Axis;
+ chart.y2Axis = y2Axis;
+
+ d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
+
+ chart.x = function(_) {
+ if (!arguments.length) return lines.x;
+ lines.x(_);
+ lines2.x(_);
+ return chart;
+ };
+
+ chart.y = function(_) {
+ if (!arguments.length) return lines.y;
+ lines.y(_);
+ lines2.y(_);
+ return chart;
+ };
+
+ chart.margin = function(_) {
+ if (!arguments.length) return margin;
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
+ return chart;
+ };
+
+ chart.margin2 = function(_) {
+ if (!arguments.length) return margin2;
+ margin2 = _;
+ return chart;
+ };
+
+ chart.width = function(_) {
+ if (!arguments.length) return width;
+ width = _;
+ return chart;
+ };
+
+ chart.height = function(_) {
+ if (!arguments.length) return height;
+ height = _;
+ return chart;
+ };
+
+ chart.height2 = function(_) {
+ if (!arguments.length) return height2;
+ height2 = _;
+ return chart;
+ };
+
+ chart.color = function(_) {
+ if (!arguments.length) return color;
+ color =nv.utils.getColor(_);
+ legend.color(color);
+ return chart;
+ };
+
+ chart.showLegend = function(_) {
+ if (!arguments.length) return showLegend;
+ showLegend = _;
+ return chart;
+ };
+
+ chart.tooltips = function(_) {
+ if (!arguments.length) return tooltips;
+ tooltips = _;
+ return chart;
+ };
+
+ chart.tooltipContent = function(_) {
+ if (!arguments.length) return tooltip;
+ tooltip = _;
+ return chart;
+ };
+
+ chart.interpolate = function(_) {
+ if (!arguments.length) return lines.interpolate();
+ lines.interpolate(_);
+ lines2.interpolate(_);
+ return chart;
+ };
+
+ chart.noData = function(_) {
+ if (!arguments.length) return noData;
+ noData = _;
+ return chart;
+ };
+
+ // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
+ chart.xTickFormat = function(_) {
+ if (!arguments.length) return xAxis.tickFormat();
+ xAxis.tickFormat(_);
+ x2Axis.tickFormat(_);
+ return chart;
+ };
+
+ chart.yTickFormat = function(_) {
+ if (!arguments.length) return yAxis.tickFormat();
+ yAxis.tickFormat(_);
+ y2Axis.tickFormat(_);
+ return chart;
+ };
+
+ //============================================================
+
+
+ return chart;
+}
+
+nv.models.linePlusBarWithFocusChart = function() {
+
+ //============================================================
+ // Public Variables with Default Settings
+ //------------------------------------------------------------
+
+ var lines = nv.models.line()
+ , lines2 = nv.models.line()
+ , bars = nv.models.historicalBar()
+ , bars2 = nv.models.historicalBar()
+ , xAxis = nv.models.axis()
+ , x2Axis = nv.models.axis()
+ , y1Axis = nv.models.axis()
+ , y2Axis = nv.models.axis()
+ , y3Axis = nv.models.axis()
+ , y4Axis = nv.models.axis()
+ , legend = nv.models.legend()
+ , brush = d3.svg.brush()
+ ;
+
+ var margin = {top: 30, right: 30, bottom: 30, left: 60}
+ , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
+ , width = null
+ , height = null
+ , height2 = 100
+ , getX = function(d) { return d.x }
+ , getY = function(d) { return d.y }
+ , color = nv.utils.defaultColor()
+ , showLegend = true
+ , extent
+ , brushExtent = null
+ , tooltips = true
+ , tooltip = function(key, x, y, e, graph) {
+ return '<h3>' + key + '</h3>' +
+ '<p>' + y + ' at ' + x + '</p>';
+ }
+ , x
+ , x2
+ , y1
+ , y2
+ , y3
+ , y4
+ , noData = "No Data Available."
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush')
+ ;
+
+ lines
+ .clipEdge(true)
+ ;
+ lines2
+ .interactive(false)
+ ;
+ xAxis
+ .orient('bottom')
+ .tickPadding(5)
+ ;
+ y1Axis
+ .orient('left')
+ ;
+ y2Axis
+ .orient('right')
+ ;
+ x2Axis
+ .orient('bottom')
+ .tickPadding(5)
+ ;
+ y3Axis
+ .orient('left')
+ ;
+ y4Axis
+ .orient('right')
+ ;
+
+ //============================================================
+
+
+ //============================================================
+ // Private Variables
+ //------------------------------------------------------------
+
+ var showTooltip = function(e, offsetElement) {
+ if (extent) {
+ e.pointIndex += Math.ceil(extent[0]);
+ }
+ var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
+ top = e.pos[1] + ( offsetElement.offsetTop || 0),
+ x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
+ y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
+ content = tooltip(e.series.key, x, y, e, chart);
+
+ nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
+ };
+
+ //------------------------------------------------------------
+
+
+
+ function chart(selection) {
+ selection.each(function(data) {
+ var container = d3.select(this),
+ that = this;
+
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
+ - margin.left - margin.right,
+ availableHeight1 = (height || parseInt(container.style('height')) || 400)
+ - margin.top - margin.bottom - height2,
+ availableHeight2 = height2 - margin2.top - margin2.bottom;
+
+ chart.update = function() { chart(selection) };
+ chart.container = this;
+
+
+ //------------------------------------------------------------
+ // Display No Data message if there's nothing to show.
+
+ if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
+ var noDataText = container.selectAll('.nv-noData').data([noData]);
+
+ noDataText.enter().append('text')
+ .attr('class', 'nvd3 nv-noData')
+ .attr('dy', '-.7em')
+ .style('text-anchor', 'middle');
+
+ noDataText
+ .attr('x', margin.left + availableWidth / 2)
+ .attr('y', margin.top + availableHeight1 / 2)
+ .text(function(d) { return d });
+
+ return chart;
+ } else {
+ container.selectAll('.nv-noData').remove();
+ }
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Scales
+
+ var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
+ var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
+
+ x = bars.xScale();
+ x2 = x2Axis.scale();
+ y1 = bars.yScale();
+ y2 = lines.yScale();
+ y3 = bars2.yScale();
+ y4 = lines2.yScale();
+
+ var series1 = data
+ .filter(function(d) { return !d.disabled && d.bar })
+ .map(function(d) {
+ return d.values.map(function(d,i) {
+ return { x: getX(d,i), y: getY(d,i) }
+ })
+ });
+
+ var series2 = data
+ .filter(function(d) { return !d.disabled && !d.bar })
+ .map(function(d) {
+ return d.values.map(function(d,i) {
+ return { x: getX(d,i), y: getY(d,i) }
+ })
+ });
+
+ x .range([0, availableWidth]);
+
+ x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
+ .range([0, availableWidth]);
+
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup containers and skeleton of chart
+
+ var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
+ var g = wrap.select('g');
+
+ gEnter.append('g').attr('class', 'nv-legendWrap');
+
+ var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
+ focusEnter.append('g').attr('class', 'nv-x nv-axis');
+ focusEnter.append('g').attr('class', 'nv-y1 nv-axis');
+ focusEnter.append('g').attr('class', 'nv-y2 nv-axis');
+ focusEnter.append('g').attr('class', 'nv-barsWrap');
+ focusEnter.append('g').attr('class', 'nv-linesWrap');
+
+ var contextEnter = gEnter.append('g').attr('class', 'nv-context');
+ contextEnter.append('g').attr('class', 'nv-x nv-axis');
+ contextEnter.append('g').attr('class', 'nv-y1 nv-axis');
+ contextEnter.append('g').attr('class', 'nv-y2 nv-axis');
+ contextEnter.append('g').attr('class', 'nv-barsWrap');
+ contextEnter.append('g').attr('class', 'nv-linesWrap');
+ contextEnter.append('g').attr('class', 'nv-brushBackground');
+ contextEnter.append('g').attr('class', 'nv-x nv-brush');
+
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Legend
+
+ if (showLegend) {
+ legend.width( availableWidth / 2 );
+
+ g.select('.nv-legendWrap')
+ .datum(data.map(function(series) {
+ series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
+ series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');
+ return series;
+ }))
+ .call(legend);
+
+ if ( margin.top != legend.height()) {
+ margin.top = legend.height();
+ availableHeight1 = (height || parseInt(container.style('height')) || 400)
+ - margin.top - margin.bottom - height2;
+ }
+
+ g.select('.nv-legendWrap')
+ .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
+ }
+
+ //------------------------------------------------------------
+
- d3.transition(focusLinesWrap).call(lines);
- */
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
//------------------------------------------------------------
- // Setup Main (Focus) Axes
+ // Context Components
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight1, 0);
+ bars2
+ .width(availableWidth)
+ .height(availableHeight2)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
- yAxis
- .scale(y)
- .ticks( availableHeight1 / 36 )
- .tickSize( -availableWidth, 0);
+ lines2
+ .width(availableWidth)
+ .height(availableHeight2)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
+
+ var bars2Wrap = g.select('.nv-context .nv-barsWrap')
+ .datum(dataBars.length ? dataBars : [{values:[]}]);
+
+ var lines2Wrap = g.select('.nv-context .nv-linesWrap')
+ .datum(!dataLines[0].disabled ? dataLines : [{values:[]}]);
+
+ g.select('.nv-context')
+ .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
- g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight1 + ')');
+ d3.transition(bars2Wrap).call(bars2);
+ d3.transition(lines2Wrap).call(lines2);
//------------------------------------------------------------
+
//------------------------------------------------------------
// Setup Brush
@@ -4581,51 +5625,60 @@ nv.models.lineWithFocusChart = function() {
.attr('y', 0)
.attr('height', availableHeight2);
- gBrush = g.select('.nv-x.nv-brush')
+ var gBrush = g.select('.nv-x.nv-brush')
.call(brush);
gBrush.selectAll('rect')
//.attr('y', -5)
.attr('height', availableHeight2);
gBrush.selectAll('.resize').append('path').attr('d', resizePath);
- onBrush();
-
//------------------------------------------------------------
-
//------------------------------------------------------------
// Setup Secondary (Context) Axes
x2Axis
- .scale(x2)
.ticks( availableWidth / 100 )
.tickSize(-availableHeight2, 0);
g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ .attr('transform', 'translate(0,' + y3.range()[0] + ')');
d3.transition(g.select('.nv-context .nv-x.nv-axis'))
.call(x2Axis);
- y2Axis
- .scale(y2)
+ y3Axis
+ .scale(y3)
.ticks( availableHeight2 / 36 )
.tickSize( -availableWidth, 0);
- d3.transition(g.select('.nv-context .nv-y.nv-axis'))
- .call(y2Axis);
+ g.select('.nv-context .nv-y1.nv-axis')
+ .style('opacity', dataBars.length ? 1 : 0)
+ .attr('transform', 'translate(0,' + x2.range()[0] + ')');
+
+ d3.transition(g.select('.nv-context .nv-y1.nv-axis'))
+ .call(y3Axis);
+
+
+ y4Axis
+ .scale(y4)
+ .ticks( availableHeight2 / 36 )
+ .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ g.select('.nv-context .nv-y2.nv-axis')
+ .style('opacity', dataLines.length ? 1 : 0)
+ .attr('transform', 'translate(' + x2.range()[1] + ',0)');
+ d3.transition(g.select('.nv-context .nv-y2.nv-axis'))
+ .call(y4Axis);
+
//------------------------------------------------------------
-
//============================================================
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
- legend.dispatch.on('legendClick', function(d,i) {
+ legend.dispatch.on('legendClick', function(d,i) {
d.disabled = !d.disabled;
if (!data.filter(function(d) { return !d.disabled }).length) {
@@ -4636,7 +5689,7 @@ nv.models.lineWithFocusChart = function() {
});
}
- selection.transition().call(chart);
+ selection.call(chart);
});
dispatch.on('tooltipShow', function(e) {
@@ -4672,8 +5725,8 @@ nv.models.lineWithFocusChart = function() {
brushBG
.data([brush.empty() ? x2.domain() : brushExtent])
.each(function(d,i) {
- var leftWidth = x2(d[0]) - x.range()[0],
- rightWidth = x.range()[1] - x2(d[1]);
+ var leftWidth = x2(d[0]) - x2.range()[0],
+ rightWidth = x2.range()[1] - x2(d[1]);
d3.select(this).select('.left')
.attr('width', leftWidth < 0 ? 0 : leftWidth);
@@ -4691,14 +5744,43 @@ nv.models.lineWithFocusChart = function() {
dispatch.brush({extent: extent, brush: brush});
-
updateBrushBG();
- // Update Main (Focus)
+
+ //------------------------------------------------------------
+ // Prepare Main (Focus) Bars and Lines
+
+ bars
+ .width(availableWidth)
+ .height(availableHeight1)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
+
+
+ lines
+ .width(availableWidth)
+ .height(availableHeight1)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
+
+ var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')
+ .datum(!dataBars.length ? [{values:[]}] :
+ dataBars
+ .map(function(d,i) {
+ return {
+ key: d.key,
+ values: d.values.filter(function(d,i) {
+ return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];
+ })
+ }
+ })
+ );
+
var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(
- data
- .filter(function(d) { return !d.disabled })
+ .datum(dataLines[0].disabled ? [{values:[]}] :
+ dataLines
.map(function(d,i) {
return {
key: d.key,
@@ -4707,19 +5789,75 @@ nv.models.lineWithFocusChart = function() {
})
}
})
- );
+ );
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Update Main (Focus) X Axis
+
+ if (dataBars.length) {
+ x = bars.xScale();
+ } else {
+ x = lines.xScale();
+ }
+
+ xAxis
+ .scale(x)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight1, 0);
+
+ xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);
+
+ d3.transition(g.select('.nv-x.nv-axis'))
+ .call(xAxis);
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Update Main (Focus) Bars and Lines
+
+ d3.transition(focusBarsWrap).call(bars);
d3.transition(focusLinesWrap).call(lines);
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup and Update Main (Focus) Y Axes
+
+ g.select('.nv-focus .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y1.range()[0] + ')');
- // Update Main (Focus) Axes
- d3.transition(g.select('.nv-focus .nv-x.nv-axis'))
- .call(xAxis);
- d3.transition(g.select('.nv-focus .nv-y.nv-axis'))
- .call(yAxis);
+ y1Axis
+ .scale(y1)
+ .ticks( availableHeight1 / 36 )
+ .tickSize(-availableWidth, 0);
+
+ g.select('.nv-focus .nv-y1.nv-axis')
+ .style('opacity', dataBars.length ? 1 : 0);
+
+
+ y2Axis
+ .scale(y2)
+ .ticks( availableHeight1 / 36 )
+ .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
+
+ g.select('.nv-focus .nv-y2.nv-axis')
+ .style('opacity', dataLines.length ? 1 : 0)
+ .attr('transform', 'translate(' + x.range()[1] + ',0)');
+
+ d3.transition(g.select('.nv-focus .nv-y1.nv-axis'))
+ .call(y1Axis);
+ d3.transition(g.select('.nv-focus .nv-y2.nv-axis'))
+ .call(y2Axis);
}
//============================================================
+ onBrush();
});
@@ -4740,6 +5878,15 @@ nv.models.lineWithFocusChart = function() {
dispatch.tooltipHide(e);
});
+ bars.dispatch.on('elementMouseover.tooltip', function(e) {
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
+ dispatch.tooltipShow(e);
+ });
+
+ bars.dispatch.on('elementMouseout.tooltip', function(e) {
+ dispatch.tooltipHide(e);
+ });
+
dispatch.on('tooltipHide', function() {
if (tooltips) nv.tooltip.cleanup();
});
@@ -4756,24 +5903,32 @@ nv.models.lineWithFocusChart = function() {
chart.legend = legend;
chart.lines = lines;
chart.lines2 = lines2;
+ chart.bars = bars;
+ chart.bars2 = bars2;
chart.xAxis = xAxis;
- chart.yAxis = yAxis;
chart.x2Axis = x2Axis;
+ chart.y1Axis = y1Axis;
chart.y2Axis = y2Axis;
+ chart.y3Axis = y3Axis;
+ chart.y4Axis = y4Axis;
- d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
+ d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');
+ //TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.
+ //d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
chart.x = function(_) {
- if (!arguments.length) return lines.x;
+ if (!arguments.length) return getX;
+ getX = _;
lines.x(_);
- lines2.x(_);
+ bars.x(_);
return chart;
};
chart.y = function(_) {
- if (!arguments.length) return lines.y;
+ if (!arguments.length) return getY;
+ getY = _;
lines.y(_);
- lines2.y(_);
+ bars.y(_);
return chart;
};
@@ -4786,12 +5941,6 @@ nv.models.lineWithFocusChart = function() {
return chart;
};
- chart.margin2 = function(_) {
- if (!arguments.length) return margin2;
- margin2 = _;
- return chart;
- };
-
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
@@ -4806,7 +5955,7 @@ nv.models.lineWithFocusChart = function() {
chart.color = function(_) {
if (!arguments.length) return color;
- color =nv.utils.getColor(_);
+ color = nv.utils.getColor(_);
legend.color(color);
return chart;
};
@@ -4829,33 +5978,18 @@ nv.models.lineWithFocusChart = function() {
return chart;
};
- chart.interpolate = function(_) {
- if (!arguments.length) return lines.interpolate();
- lines.interpolate(_);
- lines2.interpolate(_);
- return chart;
- };
-
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
return chart;
};
- // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
- chart.xTickFormat = function(_) {
- if (!arguments.length) return xAxis.tickFormat();
- xAxis.tickFormat(_);
- x2Axis.tickFormat(_);
+ chart.brushExtent = function(_) {
+ if (!arguments.length) return brushExtent;
+ brushExtent = _;
return chart;
};
- chart.yTickFormat = function(_) {
- if (!arguments.length) return yAxis.tickFormat();
- yAxis.tickFormat(_);
- y2Axis.tickFormat(_);
- return chart;
- };
//============================================================
@@ -4881,6 +6015,9 @@ nv.models.multiBar = function() {
, clipEdge = true
, stacked = false
, color = nv.utils.defaultColor()
+ , hideable = false
+ , barColor = null // adding the ability to set the color for each rather than the whole group
+ , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
, delay = 1200
, xDomain
, yDomain
@@ -4906,12 +6043,22 @@ nv.models.multiBar = function() {
availableHeight = height - margin.top - margin.bottom,
container = d3.select(this);
+ if(hideable && data.length) hideable = [{
+ values: data[0].values.map(function(d) {
+ return {
+ x: d.x,
+ y: 0,
+ series: d.series,
+ size: 0.01
+ };}
+ )}];
+
if (stacked)
data = d3.layout.stack()
.offset('zero')
.values(function(d){ return d.values })
.y(getY)
- (data);
+ (!data.length && hideable ? hideable : data);
//add series index to each data point for reference
@@ -4925,23 +6072,42 @@ nv.models.multiBar = function() {
//------------------------------------------------------------
+ // HACK for negative value stacking
+ if (stacked)
+ data[0].values.map(function(d,i) {
+ var posBase = 0, negBase = 0;
+ data.map(function(d) {
+ var f = d.values[i]
+ f.size = Math.abs(f.y);
+ if (f.y<0) {
+ f.y1 = negBase;
+ negBase = negBase - f.size;
+ } else
+ {
+ f.y1 = f.size + posBase;
+ posBase = posBase + f.size;
+ }
+ });
+ });
+
+ //------------------------------------------------------------
// Setup Scales
// remap and flatten the data for use in calculating the scales' domains
var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
data.map(function(d) {
return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
+ return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
})
});
x .domain(d3.merge(seriesData).map(function(d) { return d.x }))
.rangeBands([0, availableWidth], .1);
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ //y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y1 : 0) }).concat(forceY)))
+ y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 : d.y1 + d.y ) : d.y }).concat(forceY)))
.range([availableHeight, 0]);
-
// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true;
if (x.domain()[0] === x.domain()[1])
@@ -5013,7 +6179,7 @@ nv.models.multiBar = function() {
var bars = groups.selectAll('rect.nv-bar')
- .data(function(d) { return d.values });
+ .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
bars.exit().remove();
@@ -5079,14 +6245,28 @@ nv.models.multiBar = function() {
bars
.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
+
+ if (barColor) {
+ if (!disabled) disabled = data.map(function() { return true });
+ bars
+ //.style('fill', barColor)
+ //.style('stroke', barColor)
+ //.style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ //.style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
+ .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
+ }
+
+
if (stacked)
d3.transition(bars)
.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('y', function(d,i) {
- return y(getY(d,i) + (stacked ? d.y0 : 0));
+
+ return y((stacked ? d.y1 : 0));
})
.attr('height', function(d,i) {
- return Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0)))
+ return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1);
})
.each('end', function() {
d3.transition(d3.select(this))
@@ -5106,11 +6286,13 @@ nv.models.multiBar = function() {
d3.transition(d3.select(this))
.attr('y', function(d,i) {
return getY(d,i) < 0 ?
- y(0) :
- y(getY(d,i))
- })
- .attr('height', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 :
+ y(getY(d,i)) || 0;
+ })
+ .attr('height', function(d,i) {
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
});
})
@@ -5212,12 +6394,30 @@ nv.models.multiBar = function() {
return chart;
};
+ chart.barColor = function(_) {
+ if (!arguments.length) return barColor;
+ barColor = nv.utils.getColor(_);
+ return chart;
+ };
+
+ chart.disabled = function(_) {
+ if (!arguments.length) return disabled;
+ disabled = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
return chart;
};
+ chart.hideable = function(_) {
+ if (!arguments.length) return hideable;
+ hideable = _;
+ return chart;
+ };
+
chart.delay = function(_) {
if (!arguments.length) return delay;
delay = _;
@@ -5258,8 +6458,11 @@ nv.models.multiBarChart = function() {
}
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
+ , state = { stacked: false }
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = function() { return showControls ? 180 : 0 }
;
multibar
@@ -5267,7 +6470,7 @@ nv.models.multiBarChart = function() {
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
.highlightZero(false)
.showMaxMin(false)
.tickFormat(function(d) { return d })
@@ -5310,7 +6513,19 @@ nv.models.multiBarChart = function() {
chart.update = function() { selection.transition().call(chart) };
chart.container = this;
-
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -5364,7 +6579,12 @@ nv.models.multiBarChart = function() {
// Legend
if (showLegend) {
- legend.width(availableWidth / 2);
+ legend.width(availableWidth - controlWidth());
+
+ if (multibar.barColor())
+ data.forEach(function(series,i) {
+ series.color = d3.rgb('#ccc').darker(i * 1.5).toString();
+ })
g.select('.nv-legendWrap')
.datum(data)
@@ -5377,7 +6597,7 @@ nv.models.multiBarChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -5392,7 +6612,7 @@ nv.models.multiBarChart = function() {
{ key: 'Stacked', disabled: !multibar.stacked() }
];
- controls.width(180).color(['#444', '#444', '#444']);
+ controls.width(controlWidth()).color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
.datum(controlsData)
.attr('transform', 'translate(0,' + (-margin.top) +')')
@@ -5409,6 +6629,7 @@ nv.models.multiBarChart = function() {
// Main Chart Component(s)
multibar
+ .disabled(data.map(function(series) { return series.disabled }))
.width(availableWidth)
.height(availableHeight)
.color(data.map(function(d,i) {
@@ -5453,9 +6674,12 @@ nv.models.multiBarChart = function() {
if(rotateLabels)
xTicks
- .selectAll('text')
- .attr('transform', function(d,i,j) { return 'rotate('+rotateLabels+' 0,0)' })
- .attr('text-transform', rotateLabels > 0 ? 'start' : 'end');
+ .selectAll('text')
+ .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')
+ .attr('text-anchor', rotateLabels > 0 ? 'start' : 'end');
+
+ g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')
+ .style('opacity', 1);
yAxis
.scale(y)
@@ -5484,6 +6708,9 @@ nv.models.multiBarChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -5504,6 +6731,9 @@ nv.models.multiBarChart = function() {
break;
}
+ state.stacked = multibar.stacked();
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -5511,6 +6741,25 @@ nv.models.multiBarChart = function() {
if (tooltips) showTooltip(e, that.parentNode)
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.stacked !== 'undefined') {
+ multibar.stacked(e.stacked);
+ state.stacked = e.stacked;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -5550,7 +6799,7 @@ nv.models.multiBarChart = function() {
chart.xAxis = xAxis;
chart.yAxis = yAxis;
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'stacked', 'delay');
+ d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'stacked', 'delay', 'barColor');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -5622,6 +6871,18 @@ nv.models.multiBarChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -5650,6 +6911,8 @@ nv.models.multiBarHorizontal = function() {
, getY = function(d) { return d.y }
, forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
, color = nv.utils.defaultColor()
+ , barColor = null // adding the ability to set the color for each rather than the whole group
+ , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
, stacked = false
, showValues = false
, valuePadding = 60
@@ -5698,6 +6961,28 @@ nv.models.multiBarHorizontal = function() {
});
+
+ //------------------------------------------------------------
+ // HACK for negative value stacking
+ if (stacked)
+ data[0].values.map(function(d,i) {
+ var posBase = 0, negBase = 0;
+ data.map(function(d) {
+ var f = d.values[i]
+ f.size = Math.abs(f.y);
+ if (f.y<0) {
+ f.y1 = negBase - f.size;
+ negBase = negBase - f.size;
+ } else
+ {
+ f.y1 = posBase;
+ posBase = posBase + f.size;
+ }
+ });
+ });
+
+
+
//------------------------------------------------------------
// Setup Scales
@@ -5705,14 +6990,15 @@ nv.models.multiBarHorizontal = function() {
var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
data.map(function(d) {
return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
+ return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
})
});
x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
.rangeBands([0, availableHeight], .1);
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ //y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY)))
if (showValues && !stacked)
y.range([(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);
@@ -5825,32 +7111,45 @@ nv.models.multiBarHorizontal = function() {
d3.event.stopPropagation();
});
+
+ barsEnter.append('text');
+
if (showValues && !stacked) {
- barsEnter.append('text')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
bars.select('text')
- .attr('y', x.rangeBand() / 2)
- .attr('dy', '-.32em')
+ .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
+ .attr('y', x.rangeBand() / (data.length * 2))
+ .attr('dy', '.32em')
.text(function(d,i) { return valueFormat(getY(d,i)) })
d3.transition(bars)
//.delay(function(d,i) { return i * delay / data[0].values.length })
.select('text')
.attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })
} else {
- bars.selectAll('text').remove();
+ //bars.selectAll('text').remove();
+ bars.selectAll('text').text('');
}
bars
.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
- //.attr('transform', function(d,i,j) {
- //return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + x(getX(d,i)) + ')'
- //})
+
+ if (barColor) {
+ if (!disabled) disabled = data.map(function() { return true });
+ bars
+ //.style('fill', barColor)
+ //.style('stroke', barColor)
+ //.style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ //.style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
+ .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
+ }
+
if (stacked)
d3.transition(bars)
//.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('transform', function(d,i) {
//return 'translate(' + y(d.y0) + ',0)'
- return 'translate(' + y(d.y0) + ',' + x(getX(d,i)) + ')'
+ //return 'translate(' + y(d.y0) + ',' + x(getX(d,i)) + ')'
+ return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'
})
.select('rect')
.attr('width', function(d,i) {
@@ -5873,7 +7172,7 @@ nv.models.multiBarHorizontal = function() {
.select('rect')
.attr('height', x.rangeBand() / data.length )
.attr('width', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)),1)
});
@@ -5968,6 +7267,18 @@ nv.models.multiBarHorizontal = function() {
return chart;
};
+ chart.barColor = function(_) {
+ if (!arguments.length) return barColor;
+ barColor = nv.utils.getColor(_);
+ return chart;
+ };
+
+ chart.disabled = function(_) {
+ if (!arguments.length) return disabled;
+ disabled = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
@@ -6031,8 +7342,11 @@ nv.models.multiBarHorizontalChart = function() {
}
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
+ , state = { stacked: stacked }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = function() { return showControls ? 180 : 0 }
;
multibar
@@ -6083,6 +7397,19 @@ nv.models.multiBarHorizontalChart = function() {
chart.update = function() { selection.transition().call(chart) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -6137,7 +7464,12 @@ nv.models.multiBarHorizontalChart = function() {
// Legend
if (showLegend) {
- legend.width(availableWidth / 2);
+ legend.width(availableWidth - controlWidth());
+
+ if (multibar.barColor())
+ data.forEach(function(series,i) {
+ series.color = d3.rgb('#ccc').darker(i * 1.5).toString();
+ })
g.select('.nv-legendWrap')
.datum(data)
@@ -6150,7 +7482,7 @@ nv.models.multiBarHorizontalChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -6165,7 +7497,7 @@ nv.models.multiBarHorizontalChart = function() {
{ key: 'Stacked', disabled: !multibar.stacked() }
];
- controls.width(180).color(['#444', '#444', '#444']);
+ controls.width(controlWidth()).color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
.datum(controlsData)
.attr('transform', 'translate(0,' + (-margin.top) +')')
@@ -6182,6 +7514,7 @@ nv.models.multiBarHorizontalChart = function() {
// Main Chart Component(s)
multibar
+ .disabled(data.map(function(series) { return series.disabled }))
.width(availableWidth)
.height(availableHeight)
.color(data.map(function(d,i) {
@@ -6244,6 +7577,9 @@ nv.models.multiBarHorizontalChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -6264,6 +7600,9 @@ nv.models.multiBarHorizontalChart = function() {
break;
}
+ state.stacked = multibar.stacked();
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -6271,6 +7610,24 @@ nv.models.multiBarHorizontalChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.stacked !== 'undefined') {
+ multibar.stacked(e.stacked);
+ state.stacked = e.stacked;
+ }
+
+ selection.call(chart);
+ });
//============================================================
@@ -6310,7 +7667,7 @@ nv.models.multiBarHorizontalChart = function() {
chart.xAxis = xAxis;
chart.yAxis = yAxis;
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'delay', 'showValues', 'valueFormat', 'stacked');
+ d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'delay', 'showValues', 'valueFormat', 'stacked', 'barColor');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -6370,6 +7727,18 @@ nv.models.multiBarHorizontalChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -6427,7 +7796,7 @@ nv.models.multiChart = function() {
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
top = e.pos[1] + ( offsetElement.offsetTop || 0),
x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)),
- y = (e.series.bar ? yAxis1 : yAxis2).tickFormat()(lines1.y()(e.point, e.pointIndex)),
+ y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)),
content = tooltip(e.series.key, x, y, e, chart);
nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent);
@@ -6846,6 +8215,7 @@ nv.models.ohlcBar = function() {
, getLow = function(d) { return d.low }
, forceX = []
, forceY = []
+ , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
, clipEdge = true
, color = nv.utils.defaultColor()
, xDomain
@@ -6874,8 +8244,12 @@ nv.models.ohlcBar = function() {
//------------------------------------------------------------
// Setup Scales
- x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ))
- .range([0, availableWidth]);
+ x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
+
+ if (padData)
+ x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
y .domain(yDomain || [
d3.min(data[0].values.map(getLow).concat(forceY)),
@@ -7156,6 +8530,12 @@ nv.models.ohlcBar = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -7179,7 +8559,6 @@ nv.models.ohlcBar = function() {
return chart;
}
-
nv.models.pie = function() {
//============================================================
@@ -7192,13 +8571,19 @@ nv.models.pie = function() {
, getValues = function(d) { return d.values }
, getX = function(d) { return d.x }
, getY = function(d) { return d.y }
+ , getDescription = function(d) { return d.description }
, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
, color = nv.utils.defaultColor()
, valueFormat = d3.format(',.2f')
, showLabels = true
+ , pieLabelsOutside = true
, donutLabelsOutside = false
, labelThreshold = .02 //if slice percentage is under this, don't show label
, donut = false
+ , labelSunbeamLayout = false
+ , startAngle = false
+ , endAngle = false
+ , donutRatio = 0.5
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
;
@@ -7210,6 +8595,7 @@ nv.models.pie = function() {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom,
radius = Math.min(availableWidth, availableHeight) / 2,
+ arcRadius = radius-(radius / 5),
container = d3.select(this);
@@ -7242,10 +8628,11 @@ nv.models.pie = function() {
var arc = d3.svg.arc()
- .outerRadius((radius-(radius / 5)));
-
- if (donut) arc.innerRadius(radius / 2);
+ .outerRadius(arcRadius);
+ if (startAngle) arc.startAngle(startAngle)
+ if (endAngle) arc.endAngle(endAngle);
+ if (donut) arc.innerRadius(radius * donutRatio);
// Setup the Pie chart and choose the data element
var pie = d3.layout.pie()
@@ -7317,10 +8704,11 @@ nv.models.pie = function() {
if (showLabels) {
// This does the normal label
- var labelsArc = arc;
- if (donutLabelsOutside) {
- labelsArc = d3.svg.arc().outerRadius(arc.outerRadius())
- }
+ var labelsArc = d3.svg.arc().innerRadius(0);
+
+ if (pieLabelsOutside){ labelsArc = arc; }
+
+ if (donutLabelsOutside) { labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); }
ae.append("g").classed("nv-label", true)
.each(function(d, i) {
@@ -7328,9 +8716,21 @@ nv.models.pie = function() {
group
.attr('transform', function(d) {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc.centroid(d) + ')'
+ if (labelSunbeamLayout) {
+ d.outerRadius = arcRadius + 10; // Set Outer Coordinate
+ d.innerRadius = arcRadius + 15; // Set Inner Coordinate
+ var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
+ if ((d.startAngle+d.endAngle)/2 < Math.PI) {
+ rotateAngle -= 90;
+ } else {
+ rotateAngle += 90;
+ }
+ return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';
+ } else {
+ d.outerRadius = radius + 10; // Set Outer Coordinate
+ d.innerRadius = radius + 15; // Set Inner Coordinate
+ return 'translate(' + labelsArc.centroid(d) + ')'
+ }
});
group.append('rect')
@@ -7340,7 +8740,7 @@ nv.models.pie = function() {
.attr("ry", 3);
group.append('text')
- .style('text-anchor', 'middle') //center the text on it's origin
+ .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
.style('fill', '#000')
@@ -7348,9 +8748,21 @@ nv.models.pie = function() {
slices.select(".nv-label").transition()
.attr('transform', function(d) {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc.centroid(d) + ')';
+ if (labelSunbeamLayout) {
+ d.outerRadius = arcRadius + 10; // Set Outer Coordinate
+ d.innerRadius = arcRadius + 15; // Set Inner Coordinate
+ var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
+ if ((d.startAngle+d.endAngle)/2 < Math.PI) {
+ rotateAngle -= 90;
+ } else {
+ rotateAngle += 90;
+ }
+ return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';
+ } else {
+ d.outerRadius = radius + 10; // Set Outer Coordinate
+ d.innerRadius = radius + 15; // Set Inner Coordinate
+ return 'translate(' + labelsArc.centroid(d) + ')'
+ }
});
slices.each(function(d, i) {
@@ -7358,6 +8770,7 @@ nv.models.pie = function() {
slice
.select(".nv-label text")
+ .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
.text(function(d, i) {
var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);
return (d.value && percent > labelThreshold) ? getX(d.data) : '';
@@ -7447,24 +8860,60 @@ nv.models.pie = function() {
getY = d3.functor(_);
return chart;
};
+
+ chart.description = function(_) {
+ if (!arguments.length) return getDescription;
+ getDescription = _;
+ return chart;
+ };
chart.showLabels = function(_) {
if (!arguments.length) return showLabels;
showLabels = _;
return chart;
};
+
+ chart.labelSunbeamLayout = function(_) {
+ if (!arguments.length) return labelSunbeamLayout;
+ labelSunbeamLayout = _;
+ return chart;
+ };
chart.donutLabelsOutside = function(_) {
if (!arguments.length) return donutLabelsOutside;
donutLabelsOutside = _;
return chart;
};
+
+ chart.pieLabelsOutside = function(_) {
+ if (!arguments.length) return pieLabelsOutside;
+ pieLabelsOutside = _;
+ return chart;
+ };
chart.donut = function(_) {
if (!arguments.length) return donut;
donut = _;
return chart;
};
+
+ chart.donutRatio = function(_) {
+ if (!arguments.length) return donutRatio;
+ donutRatio = _;
+ return chart;
+ };
+
+ chart.startAngle = function(_) {
+ if (!arguments.length) return startAngle;
+ startAngle = _;
+ return chart;
+ };
+
+ chart.endAngle = function(_) {
+ if (!arguments.length) return endAngle;
+ endAngle = _;
+ return chart;
+ };
chart.id = function(_) {
if (!arguments.length) return id;
@@ -7489,13 +8938,11 @@ nv.models.pie = function() {
labelThreshold = _;
return chart;
};
-
//============================================================
return chart;
}
-
nv.models.pieChart = function() {
//============================================================
@@ -7516,8 +8963,10 @@ nv.models.pieChart = function() {
return '<h3>' + key + '</h3>' +
'<p>' + y + '</p>'
}
+ , state = {}
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
//============================================================
@@ -7528,10 +8977,11 @@ nv.models.pieChart = function() {
//------------------------------------------------------------
var showTooltip = function(e, offsetElement) {
+ var tooltipLabel = pie.description()(e.point) || pie.x()(e.point)
var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ),
top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0),
y = pie.valueFormat()(pie.y()(e.point)),
- content = tooltip(pie.x()(e.point), y, e, chart);
+ content = tooltip(tooltipLabel, y, e, chart);
nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
};
@@ -7544,7 +8994,7 @@ nv.models.pieChart = function() {
var container = d3.select(this),
that = this;
- var availableWidth = (width || parseInt(container.style('width')) || 960)
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
- margin.left - margin.right,
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
@@ -7552,11 +9002,24 @@ nv.models.pieChart = function() {
chart.update = function() { chart(selection); };
chart.container = this;
+ //set state.disabled
+ state.disabled = data[0].map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
- if (!data || !data.length) {
+ if (!data[0] || !data[0].length) {
var noDataText = container.selectAll('.nv-noData').data([noData]);
noDataText.enter().append('text')
@@ -7649,6 +9112,9 @@ nv.models.pieChart = function() {
});
}
+ state.disabled = data[0].map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart)
});
@@ -7656,6 +9122,20 @@ nv.models.pieChart = function() {
dispatch.tooltipHide(e);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data[0].forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -7689,10 +9169,11 @@ nv.models.pieChart = function() {
//------------------------------------------------------------
// expose chart's sub-components
+ chart.legend = legend;
chart.dispatch = dispatch;
chart.pie = pie;
- d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'id', 'showLabels', 'donutLabelsOutside', 'donut', 'labelThreshold');
+ d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'description', 'id', 'showLabels', 'donutLabelsOutside', 'pieLabelsOutside', 'donut', 'donutRatio', 'labelThreshold');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -7741,6 +9222,18 @@ nv.models.pieChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -7759,33 +9252,36 @@ nv.models.scatter = function() {
// Public Variables with Default Settings
//------------------------------------------------------------
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , color = nv.utils.defaultColor() // chooses color
- , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
- , getX = function(d) { return d.x } // accessor to get the x value
- , getY = function(d) { return d.y } // accessor to get the y value
- , getSize = function(d) { return d.size } // accessor to get the point size
- , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
- , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , forceY = [] // List of numbers to Force into the Y scale
- , forceSize = [] // List of numbers to Force into the Size scale
- , interactive = true // If true, plots a voronoi overlay for advanced point interection
- , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
- , clipEdge = false // if true, masks points within x and y scale
- , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
- , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
- , xDomain = null // Override x domain (skips the calculation from data)
- , yDomain = null // Override y domain
- , sizeDomain = null // Override point size domain
- , sizeRange = null
- , singlePoint = false
- , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
- , useVoronoi = true
+ var margin = {top: 0, right: 0, bottom: 0, left: 0}
+ , width = 960
+ , height = 500
+ , color = nv.utils.defaultColor() // chooses color
+ , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
+ , x = d3.scale.linear()
+ , y = d3.scale.linear()
+ , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
+ , getX = function(d) { return d.x } // accessor to get the x value
+ , getY = function(d) { return d.y } // accessor to get the y value
+ , getSize = function(d) { return d.size || 1} // accessor to get the point size
+ , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
+ , onlyCircles = true // Set to false to use shapes
+ , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
+ , forceY = [] // List of numbers to Force into the Y scale
+ , forceSize = [] // List of numbers to Force into the Size scale
+ , interactive = true // If true, plots a voronoi overlay for advanced point intersection
+ , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
+ , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
+ , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding
+ , clipEdge = false // if true, masks points within x and y scale
+ , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
+ , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
+ , xDomain = null // Override x domain (skips the calculation from data)
+ , yDomain = null // Override y domain
+ , sizeDomain = null // Override point size domain
+ , sizeRange = null
+ , singlePoint = false
+ , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
+ , useVoronoi = true
;
//============================================================
@@ -7797,6 +9293,7 @@ nv.models.scatter = function() {
var x0, y0, z0 // used to store previous scales
, timeoutID
+ , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
;
//============================================================
@@ -7831,7 +9328,12 @@ nv.models.scatter = function() {
);
x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x }).concat(forceX)))
- .range([0, availableWidth]);
+
+ if (padData && data[0])
+ x.range([(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
+ //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
.range([availableHeight, 0]);
@@ -7907,45 +9409,109 @@ nv.models.scatter = function() {
);
- if (clipVoronoi) {
- defsEnter.append('clipPath').attr('id', 'nv-points-clip-' + id);
- var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
- .data(vertices);
- pointClips.enter().append('circle')
- .attr('r', clipRadius);
- pointClips.exit().remove();
- pointClips
- .attr('cx', function(d) { return d[0] })
- .attr('cy', function(d) { return d[1] });
+ //inject series and point index for reference into voronoi
+ if (useVoronoi === true) {
+
+ if (clipVoronoi) {
+ var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
+ .data([id])
+ .enter();
+
+ pointClipsEnter.append('clipPath')
+ .attr('class', 'nv-point-clips')
+ .attr('id', 'nv-points-clip-' + id);
+
+ var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
+ .data(vertices);
+ pointClips.enter().append('circle')
+ .attr('r', clipRadius);
+ pointClips.exit().remove();
+ pointClips
+ .attr('cx', function(d) { return d[0] })
+ .attr('cy', function(d) { return d[1] });
+
+ wrap.select('.nv-point-paths')
+ .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
+ }
- wrap.select('.nv-point-paths')
- .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
- }
+ // if(vertices.length < 3) {
+ // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
+ vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);
+ vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);
+ vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
+ vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
+ // }
+
+ var bounds = d3.geom.polygon([
+ [-10,-10],
+ [-10,height + 10],
+ [width + 10,height + 10],
+ [width + 10,-10]
+ ]);
- //inject series and point index for reference into voronoi
- if (useVoronoi === true) {
var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
return {
- 'data': d,
+ 'data': bounds.clip(d),
'series': vertices[i][2],
'point': vertices[i][3]
}
});
+
var pointPaths = wrap.select('.nv-point-paths').selectAll('path')
.data(voronoi);
pointPaths.enter().append('path')
.attr('class', function(d,i) { return 'nv-path-'+i; });
pointPaths.exit().remove();
pointPaths
- .attr('d', function(d) { return 'M' + d.data.join(',') + 'Z'; });
+ .attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
+
+ pointPaths
+ .on('click', function(d) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementClick({
+ point: point,
+ series: series,
+ pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ })
+ .on('mouseover', function(d) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementMouseover({
+ point: point,
+ series: series,
+ pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ })
+ .on('mouseout', function(d, i) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementMouseout({
+ point: point,
+ series: series,
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ });
- eventElements = pointPaths;
} else {
+ /*
// bring data in form needed for click handlers
var dataWithPoints = vertices.map(function(d, i) {
return {
@@ -7954,54 +9520,58 @@ nv.models.scatter = function() {
'point': vertices[i][3]
}
});
+ */
// add event handlers to points instead voronoi paths
- eventElements = wrap.select('.nv-groups').selectAll('.nv-group')
- .selectAll('path.nv-point')
- .data(dataWithPoints)
- .style('pointer-events', 'auto'); // recativate events, disabled by css
- }
+ wrap.select('.nv-groups').selectAll('.nv-group')
+ .selectAll('.nv-point')
+ //.data(dataWithPoints)
+ //.style('pointer-events', 'auto') // recativate events, disabled by css
+ .on('click', function(d,i) {
+ //nv.log('test', d, i);
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- eventElements
- .on('click', function(d) {
- var series = data[d.series],
- point = series.values[d.point];
-
- dispatch.elementClick({
- point: point,
- series: series,
- pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
- seriesIndex: d.series,
- pointIndex: d.point
- });
- })
- .on('mouseover', function(d) {
- var series = data[d.series],
- point = series.values[d.point];
+ dispatch.elementClick({
+ point: point,
+ series: series,
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: i
+ });
+ })
+ .on('mouseover', function(d,i) {
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- dispatch.elementMouseover({
- point: point,
- series: series,
- pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
- seriesIndex: d.series,
- pointIndex: d.point
- });
- })
- .on('mouseout', function(d, i) {
- var series = data[d.series],
- point = series.values[d.point];
+ dispatch.elementMouseover({
+ point: point,
+ series: series,
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: i
+ });
+ })
+ .on('mouseout', function(d,i) {
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- dispatch.elementMouseout({
- point: point,
- series: series,
- seriesIndex: d.series,
- pointIndex: d.point
+ dispatch.elementMouseout({
+ point: point,
+ series: series,
+ seriesIndex: d.series,
+ pointIndex: i
+ });
});
- });
+ }
+ needsUpdate = false;
}
-
+ needsUpdate = true;
var groups = wrap.select('.nv-groups').selectAll('.nv-group')
.data(function(d) { return d }, function(d) { return d.key });
@@ -8022,38 +9592,62 @@ nv.models.scatter = function() {
.style('fill-opacity', .5);
- var points = groups.selectAll('path.nv-point')
- .data(function(d) { return d.values });
- points.enter().append('path')
- .attr('transform', function(d,i) {
- return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
- })
- .attr('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
- points.exit().remove();
- d3.transition(groups.exit().selectAll('path.nv-point'))
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
- })
- .remove();
- points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
- d3.transition(points)
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
- })
- .attr('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
+ if (onlyCircles) {
+
+ var points = groups.selectAll('circle.nv-point')
+ .data(function(d) { return d.values });
+ points.enter().append('circle')
+ .attr('cx', function(d,i) { return x0(getX(d,i)) })
+ .attr('cy', function(d,i) { return y0(getY(d,i)) })
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
+ points.exit().remove();
+ d3.transition(groups.exit().selectAll('path.nv-point'))
+ .attr('cx', function(d,i) { return x(getX(d,i)) })
+ .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .remove();
+ points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
+ d3.transition(points)
+ .attr('cx', function(d,i) { return x(getX(d,i)) })
+ .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
+
+ } else {
+
+ var points = groups.selectAll('path.nv-point')
+ .data(function(d) { return d.values });
+ points.enter().append('path')
+ .attr('transform', function(d,i) {
+ return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
+ })
+ .attr('d',
+ d3.svg.symbol()
+ .type(getShape)
+ .size(function(d,i) { return z(getSize(d,i)) })
+ );
+ points.exit().remove();
+ d3.transition(groups.exit().selectAll('path.nv-point'))
+ .attr('transform', function(d,i) {
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
+ })
+ .remove();
+ points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
+ d3.transition(points)
+ .attr('transform', function(d,i) {
+ //nv.log(d,i,getX(d,i), x(getX(d,i)));
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
+ })
+ .attr('d',
+ d3.svg.symbol()
+ .type(getShape)
+ .size(function(d,i) { return z(getSize(d,i)) })
+ );
+ }
// Delay updating the invisible interactive layer for smoother animation
clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
- timeoutID = setTimeout(updateInteractiveLayer, 1000);
+ timeoutID = setTimeout(updateInteractiveLayer, 300);
+ //updateInteractiveLayer();
//store old scales for use in transitions on update
x0 = x.copy();
@@ -8202,6 +9796,18 @@ nv.models.scatter = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
+ chart.padDataOuter = function(_) {
+ if (!arguments.length) return padDataOuter;
+ padDataOuter = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -8241,6 +9847,12 @@ nv.models.scatter = function() {
return chart;
};
+ chart.onlyCircles = function(_) {
+ if (!arguments.length) return onlyCircles;
+ onlyCircles = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
@@ -8274,7 +9886,7 @@ nv.models.scatterChart = function() {
, distY = nv.models.distribution()
;
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 75}
, width = null
, height = null
, color = nv.utils.defaultColor()
@@ -8293,7 +9905,9 @@ nv.models.scatterChart = function() {
, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }
//, tooltip = function(key, x, y) { return '<h3>' + key + '</h3>' }
, tooltip = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , state = {}
+ , defaultState = null
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
, noData = "No Data Available."
;
@@ -8365,6 +9979,19 @@ nv.models.scatterChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -8405,10 +10032,10 @@ nv.models.scatterChart = function() {
var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
var gEnter = wrapEnter.append('g');
- var g = wrap.select('g')
+ var g = wrap.select('g');
// background for pointer events
- gEnter.append('rect').attr('class', 'nvd3 nv-background')
+ gEnter.append('rect').attr('class', 'nvd3 nv-background');
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
@@ -8417,8 +10044,6 @@ nv.models.scatterChart = function() {
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
//------------------------------------------------------------
@@ -8459,6 +10084,9 @@ nv.models.scatterChart = function() {
//------------------------------------------------------------
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+
+
//------------------------------------------------------------
// Main Chart Component(s)
@@ -8493,7 +10121,7 @@ nv.models.scatterChart = function() {
xAxis
.scale(x)
- .ticks( xAxis.ticks() ? xAxis.ticks() : availableWidth / 100 )
+ .ticks( xAxis.ticks() && xAxis.ticks().length ? xAxis.ticks() : availableWidth / 100 )
.tickSize( -availableHeight , 0);
g.select('.nv-x.nv-axis')
@@ -8503,7 +10131,7 @@ nv.models.scatterChart = function() {
yAxis
.scale(y)
- .ticks( yAxis.ticks() ? yAxis.ticks() : availableHeight / 36 )
+ .ticks( yAxis.ticks() && yAxis.ticks().length ? yAxis.ticks() : availableHeight / 36 )
.tickSize( -availableWidth, 0);
g.select('.nv-y.nv-axis')
@@ -8623,6 +10251,9 @@ nv.models.scatterChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
chart(selection);
});
@@ -8652,6 +10283,20 @@ nv.models.scatterChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -8797,6 +10442,18 @@ nv.models.scatterChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -8824,7 +10481,7 @@ nv.models.scatterPlusLineChart = function() {
, distY = nv.models.distribution()
;
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 75}
, width = null
, height = null
, color = nv.utils.defaultColor()
@@ -8839,9 +10496,12 @@ nv.models.scatterPlusLineChart = function() {
, tooltips = true
, tooltipX = function(key, x, y) { return '<strong>' + x + '</strong>' }
, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }
- //, tooltip = function(key, x, y) { return '<h3>' + key + '</h3>' }
- , tooltip = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , tooltip = function(key, x, y, date) { return '<h3>' + key + '</h3>'
+ + '<p>' + date + '</p>' }
+ //, tooltip = null
+ , state = {}
+ , defaultState = null
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
, noData = "No Data Available."
;
@@ -8890,7 +10550,7 @@ nv.models.scatterPlusLineChart = function() {
if( tooltipY != null )
nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip');
if( tooltip != null )
- nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);
+ nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);
};
var controlsData = [
@@ -8913,6 +10573,19 @@ nv.models.scatterPlusLineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -9187,6 +10860,9 @@ nv.models.scatterPlusLineChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
chart(selection);
});
@@ -9216,6 +10892,20 @@ nv.models.scatterPlusLineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -9349,6 +11039,18 @@ nv.models.scatterPlusLineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -9429,15 +11131,32 @@ nv.models.sparkline = function() {
// TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
var points = wrap.selectAll('circle.nv-point')
- .data(function(d) { return d.filter(function(p,i) { return y.domain().indexOf(getY(p,i)) != -1 || getX(p,i) == x.domain()[1] }) });
- points.enter().append('circle').attr('class', 'nv-point');
+ .data(function(data) {
+ var yValues = data.map(function(d, i) { return getY(d,i); });
+ function pointIndex(index) {
+ if (index != -1) {
+ var result = data[index];
+ result.pointIndex = index;
+ return result;
+ } else {
+ return null;
+ }
+ }
+ var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),
+ minPoint = pointIndex(yValues.indexOf(y.domain()[0])),
+ currentPoint = pointIndex(yValues.length - 1);
+ return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});
+ });
+ points.enter().append('circle');
points.exit().remove();
points
- .attr('cx', function(d,i) { return x(getX(d,i)) })
- .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })
+ .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })
.attr('r', 2)
- .style('stroke', function(d,i) { return d.x == x.domain()[1] ? '#444' : d.y == y.domain()[0] ? '#d62728' : '#2ca02c' })
- .style('fill', function(d,i) { return d.x == x.domain()[1] ? '#444' : d.y == y.domain()[0] ? '#d62728' : '#2ca02c' });
+ .attr('class', function(d,i) {
+ return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
+ getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
+ });
});
return chart;
@@ -9531,16 +11250,18 @@ nv.models.sparklinePlus = function() {
var sparkline = nv.models.sparkline();
- var margin = {top: 15, right: 40, bottom: 3, left: 40}
+ var margin = {top: 15, right: 100, bottom: 10, left: 50}
, width = null
, height = null
, x
, y
- , color = nv.utils.defaultColor()
- , index
+ , index = []
, paused = false
, xTickFormat = d3.format(',r')
, yTickFormat = d3.format(',.2f')
+ , showValue = true
+ , alignValue = true
+ , rightAlignValue = false
, noData = "No Data Available."
;
@@ -9556,6 +11277,7 @@ nv.models.sparklinePlus = function() {
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
+ var currentValue = sparkline.y()(data[data.length-1], data.length-1);
chart.update = function() { chart(selection) };
chart.container = this;
@@ -9604,6 +11326,7 @@ nv.models.sparklinePlus = function() {
var g = wrap.select('g');
gEnter.append('g').attr('class', 'nv-sparklineWrap');
+ gEnter.append('g').attr('class', 'nv-valueWrap');
gEnter.append('g').attr('class', 'nv-hoverArea');
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
@@ -9621,81 +11344,99 @@ nv.models.sparklinePlus = function() {
.height(availableHeight);
sparklineWrap
- .style('stroke', function(d, i){ return d.color || color(d, i) })
.call(sparkline);
//------------------------------------------------------------
+ var valueWrap = g.select('.nv-valueWrap');
+
+ var value = valueWrap.selectAll('.nv-currentValue')
+ .data([currentValue]);
+
+ value.enter().append('text').attr('class', 'nv-currentValue')
+ .attr('dx', rightAlignValue ? -8 : 8)
+ .attr('dy', '.9em')
+ .style('text-anchor', rightAlignValue ? 'end' : 'start');
+
+ value
+ .attr('x', availableWidth + (rightAlignValue ? margin.right : 0))
+ .attr('y', alignValue ? function(d) { return y(d) } : 0)
+ .style('fill', sparkline.color()(data[data.length-1], data.length-1))
+ .text(yTickFormat(currentValue));
+
+
gEnter.select('.nv-hoverArea').append('rect')
.on('mousemove', sparklineHover)
.on('click', function() { paused = !paused })
- .on('mouseout', function() { index = null; updateValueLine(); });
+ .on('mouseout', function() { index = []; updateValueLine(); });
+ //.on('mouseout', function() { index = null; updateValueLine(); });
g.select('.nv-hoverArea rect')
.attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })
.attr('width', availableWidth + margin.left + margin.right)
.attr('height', availableHeight + margin.top);
- // if index is not set, default to last point
- //index = typeof index == 'undefined' ? data.length - 1 : index;
- // if index is not set, default to null
- index = typeof index == 'undefined' ? null : index;
- var hoverValue = g.selectAll('.nv-hoverValue').data([index]);
- var hoverG = hoverValue.enter().append('g').attr('class', 'nv-hoverValue');
+ function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way
+ if (paused) return;
- var hoverLine = hoverG.append('line')
- .attr('x1', 0)
- .attr('y1', -margin.top)
- .attr('x2', 0)
- .attr('y2', availableHeight);
+ var hoverValue = g.selectAll('.nv-hoverValue').data(index)
- var hoverX = hoverG.append('text').attr('class', 'nv-xValue')
- .attr('x', -6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'end')
- .attr('dy', '.9em');
+ var hoverEnter = hoverValue.enter()
+ .append('g').attr('class', 'nv-hoverValue')
+ .style('stroke-opacity', 0)
+ .style('fill-opacity', 0);
- var hoverY = hoverG.append('text').attr('class', 'nv-yValue')
- .attr('x', 6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'start')
- .attr('dy', '.9em');
+ hoverValue.exit()
+ .transition().duration(250)
+ .style('stroke-opacity', 0)
+ .style('fill-opacity', 0)
+ .remove();
- updateValueLine();
+ hoverValue
+ .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
+ .transition().duration(250)
+ .style('stroke-opacity', 1)
+ .style('fill-opacity', 1);
+ if (!index.length) return;
- function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way
- if (paused) return;
+ hoverEnter.append('line')
+ .attr('x1', 0)
+ .attr('y1', -margin.top)
+ .attr('x2', 0)
+ .attr('y2', availableHeight);
- hoverValue.data([index])
- //d3.transition(hoverValue)
- hoverValue
- .transition().duration(250)
- .style('stroke-opacity', function(d) { return d === null ? 0 : 1 })
- .style('fill-opacity', function(d) { return d === null ? 0 : 1 });
+ hoverEnter.append('text').attr('class', 'nv-xValue')
+ .attr('x', -6)
+ .attr('y', -margin.top)
+ .attr('text-anchor', 'end')
+ .attr('dy', '.9em')
- if (index == null) return;
- hoverValue
- .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
+ g.select('.nv-hoverValue .nv-xValue')
+ .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));
+
+ hoverEnter.append('text').attr('class', 'nv-yValue')
+ .attr('x', 6)
+ .attr('y', -margin.top)
+ .attr('text-anchor', 'start')
+ .attr('dy', '.9em')
- hoverValue.select('.nv-xValue')
- .text(xTickFormat(sparkline.x()(data[index], index)));
+ g.select('.nv-hoverValue .nv-yValue')
+ .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));
- hoverValue.select('.nv-yValue')
- .text(yTickFormat(sparkline.y()(data[index], index)));
}
function sparklineHover() {
if (paused) return;
- var pos = d3.event.offsetX - margin.left;
+ var pos = d3.mouse(this)[0] - margin.left;
function getClosestIndex(data, x) {
var distance = Math.abs(sparkline.x()(data[0], 0) - x);
@@ -9709,7 +11450,7 @@ nv.models.sparklinePlus = function() {
return closestIndex;
}
- index = getClosestIndex(data, Math.round(x.invert(pos)));
+ index = [getClosestIndex(data, Math.round(x.invert(pos)))];
updateValueLine();
}
@@ -9727,7 +11468,7 @@ nv.models.sparklinePlus = function() {
// expose chart's sub-components
chart.sparkline = sparkline;
- d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale');
+ d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale', 'color');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -9762,6 +11503,24 @@ nv.models.sparklinePlus = function() {
return chart;
};
+ chart.showValue = function(_) {
+ if (!arguments.length) return showValue;
+ showValue = _;
+ return chart;
+ };
+
+ chart.alignValue = function(_) {
+ if (!arguments.length) return alignValue;
+ alignValue = _;
+ return chart;
+ };
+
+ chart.rightAlignValue = function(_) {
+ if (!arguments.length) return rightAlignValue;
+ rightAlignValue = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -9800,7 +11559,7 @@ nv.models.stackedArea = function() {
scatter
.size(2.2) // default size
- .sizeDomain([2.2]) // all the same size by default
+ .sizeDomain([2.2,2.2]) // all the same size by default
;
/************************************
@@ -9891,7 +11650,8 @@ nv.models.stackedArea = function() {
var scatterWrap = g.select('.nv-scatterWrap')
.datum(data.filter(function(d) { return !d.disabled }))
- d3.transition(scatterWrap).call(scatter);
+ //d3.transition(scatterWrap).call(scatter);
+ scatterWrap.call(scatter);
@@ -9953,13 +11713,15 @@ nv.models.stackedArea = function() {
seriesIndex: i
});
})
- d3.transition(path.exit())
+ //d3.transition(path.exit())
+ path.exit()
.attr('d', function(d,i) { return zeroArea(d.values,i) })
.remove();
path
.style('fill', function(d,i){ return d.color || color(d, i) })
.style('stroke', function(d,i){ return d.color || color(d, i) });
- d3.transition(path)
+ //d3.transition(path)
+ path
.attr('d', function(d,i) { return area(d.values,i) })
@@ -10134,13 +11896,16 @@ nv.models.stackedAreaChart = function() {
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, yAxisTickFormat = d3.format(',.2f')
+ , state = { style: stacked.style() }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = 250
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -10185,6 +11950,20 @@ nv.models.stackedAreaChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
+
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -10239,7 +12018,7 @@ nv.models.stackedAreaChart = function() {
if (showLegend) {
legend
- .width( availableWidth * 2 / 3 );
+ .width( availableWidth - controlWidth );
g.select('.nv-legendWrap')
.datum(data)
@@ -10252,7 +12031,7 @@ nv.models.stackedAreaChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + ( availableWidth * 1 / 3 ) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -10269,7 +12048,7 @@ nv.models.stackedAreaChart = function() {
];
controls
- .width( Math.min(280, availableWidth * 1 / 3) )
+ .width( controlWidth )
.color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
@@ -10303,7 +12082,8 @@ nv.models.stackedAreaChart = function() {
var stackedWrap = g.select('.nv-stackedWrap')
.datum(data);
- d3.transition(stackedWrap).call(stacked);
+ //d3.transition(stackedWrap).call(stacked);
+ stackedWrap.call(stacked);
//------------------------------------------------------------
@@ -10318,7 +12098,9 @@ nv.models.stackedAreaChart = function() {
g.select('.nv-x.nv-axis')
.attr('transform', 'translate(0,' + availableHeight + ')');
- d3.transition(g.select('.nv-x.nv-axis'))
+ //d3.transition(g.select('.nv-x.nv-axis'))
+ g.select('.nv-x.nv-axis')
+ .transition().duration(0)
.call(xAxis);
yAxis
@@ -10327,7 +12109,9 @@ nv.models.stackedAreaChart = function() {
.tickSize(-availableWidth, 0)
.setTickFormat(stacked.offset() == 'expand' ? d3.format('%') : yAxisTickFormat);
- d3.transition(g.select('.nv-y.nv-axis'))
+ //d3.transition(g.select('.nv-y.nv-axis'))
+ g.select('.nv-y.nv-axis')
+ .transition().duration(0)
.call(yAxis);
//------------------------------------------------------------
@@ -10349,7 +12133,11 @@ nv.models.stackedAreaChart = function() {
return d
});
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
legend.dispatch.on('legendClick', function(d,i) {
@@ -10362,7 +12150,11 @@ nv.models.stackedAreaChart = function() {
});
}
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
controls.dispatch.on('legendClick', function(d,i) {
@@ -10386,13 +12178,35 @@ nv.models.stackedAreaChart = function() {
break;
}
- selection.transition().call(chart);
+ state.style = stacked.style();
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
dispatch.on('tooltipShow', function(e) {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.style !== 'undefined') {
+ stacked.style(e.style);
+ }
+
+ selection.call(chart);
+ });
+
});
@@ -10502,6 +12316,18 @@ nv.models.stackedAreaChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -10509,6 +12335,7 @@ nv.models.stackedAreaChart = function() {
};
yAxis.setTickFormat = yAxis.tickFormat;
+
yAxis.tickFormat = function(_) {
if (!arguments.length) return yAxisTickFormat;
yAxisTickFormat = _;
commit d81ef0a6ec22ddc6ce32eeb2a47754a6f9abb01b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 3 13:42:29 2013 -0700
[BZ 958938] - Dashboard graphs need refresh when switching View/Edit portlet modes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
index 779c795..9c310ca 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
@@ -784,6 +784,7 @@ public class DashboardView extends EnhancedVLayout {
}
this.editForm.markForRedraw();
this.portalLayout.show();
+ redraw();
this.portalLayout.markForRedraw();
}
commit 8737595774416a54383483fdd1678a436226af05
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 3 16:38:56 2013 +0200
Bug 911321 - [EAP 6.1] Reload operation fails in standalone mode
EAP can close the management http connection when receiving a reload operation request. In this case, we will set a specific error message in ASConnection which BaseServerComponent code will be able to detect.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
index 729201f..662d6ef 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
@@ -33,6 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
+import org.apache.http.NoHttpResponseException;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
@@ -82,6 +83,8 @@ public class ASConnection {
@Deprecated
public static final String MANAGEMENT = MANAGEMENT_URI;
+ static final String FAILURE_NO_RESPONSE = "The server closed the connection before sending the response";
+
private static final Log LOG = LogFactory.getLog(ASConnection.class);
private static final int MAX_POOLED_CONNECTIONS = 10;
@@ -367,6 +370,16 @@ public class ASConnection {
return operationResult;
+ } catch (NoHttpResponseException e) {
+ // For some operations like reload or shutdown, the server closes the connection before sending the
+ // response. We use a specific description here so that callers can write code to decide what to do
+ // in this situation.
+ Result failure = new Result();
+ failure.setFailureDescription(FAILURE_NO_RESPONSE);
+ failure.setOutcome("failure");
+ failure.setRhqThrowable(e);
+ JsonNode ret = mapper.valueToTree(failure);
+ return ret;
} catch (IOException e) {
Result failure = new Result();
failure.setFailureDescription(e.getMessage());
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 6d889c5..b80a39a 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,13 +13,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
-import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
@@ -54,6 +53,7 @@ import org.rhq.core.system.ProcessExecutionResults;
import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.util.PropertiesFileUpdate;
+import org.rhq.core.util.StringUtil;
import org.rhq.modules.plugins.jbossas7.helper.HostConfiguration;
import org.rhq.modules.plugins.jbossas7.helper.HostPort;
import org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration;
@@ -492,26 +492,23 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return operationResult;
}
- if (name.equals("shutdown") || name.equals("restart")) {
+ if (name.equals("shutdown") || name.equals("restart") || name.equals("reload")) {
/*
- * Shutdown needs a special treatment, because after sending the operation, if shutdown succeeds,
- * the server connection is closed and we can't read from it. So if we get connection refused for
- * reading, this is a good sign.
+ * Shutdown, restart and reload need a special treatment, because after sending the operation, event if
+ * it succeeds, the server connection is sometimes closed and we can't read from it.
*/
if (!res.isSuccess()) {
- if (res.getRhqThrowable() != null
- && (res.getRhqThrowable() instanceof ConnectException || res.getRhqThrowable().getMessage()
- .equals("Connection refused"))) {
+ if (StringUtil.isNotBlank(res.getFailureDescription())
+ && res.getFailureDescription().startsWith(ASConnection.FAILURE_NO_RESPONSE)) {
operationResult.setSimpleResult("Success");
- log.debug("Got a ConnectionRefused for operation "
- + name
- + " this is considered ok, as the remote server sometimes closes the communications channel before sending a reply");
- }
- if (res.getFailureDescription().contains("Socket closed")) { // See https://issues.jboss.org/browse/AS7-4192
- operationResult.setSimpleResult("Success");
- log.debug("Got a 'Socket closed' result from AS for operation " + name);
- } else
+ if (log.isDebugEnabled()) {
+ log.debug("Got no response for operation '" + name + "'. "
+ + "This is considered ok, as the remote server sometimes closes the communications "
+ + "channel before sending a reply");
+ }
+ } else {
operationResult.setErrorMessage(res.getFailureDescription());
+ }
} else {
operationResult.setSimpleResult("Success");
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 778d127..d399d1b 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7;
@@ -213,7 +213,9 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
count++;
}
- log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+ if (log.isDebugEnabled()) {
+ log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+ }
return reloaded;
}
commit 1ad9d648c0c90774d4a3379d54802c7ecd771b97
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 3 10:44:30 2013 +0200
as7plugin: LD_LIBRARY_PATH is not necessarily discovered in Linux environment
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
index 7aa92b6..f34a554 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest;
@@ -205,14 +205,6 @@ public abstract class AbstractServerComponentTest extends AbstractJBossAS7Plugin
String[] pathElements = path.split(File.pathSeparator);
Assert.assertTrue(pathElements.length >= 1);
Assert.assertTrue(new File(pathElements[0]).isDirectory());
-
- if (File.separatorChar == '/') {
- String ldLibraryPath = env.get("LD_LIBRARY_PATH");
- Assert.assertNotNull(ldLibraryPath);
- String[] ldLibraryPathElements = ldLibraryPath.split(File.pathSeparator);
- Assert.assertTrue(ldLibraryPathElements.length >= 1);
- Assert.assertTrue(new File(ldLibraryPathElements[0]).isDirectory());
- }
}
protected abstract String getBindAddressSystemPropertyName();
commit 059c8c96f82bf1c20863fde8ba334b95b5a98687
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 2 11:46:26 2013 -0700
[BZ 958734] - Add autogroup metric to dashboard fails for d3 graphs. Turned off the autogroups right click menu to create dashboard graphs from resource tree as the full fix for this is risky given we are releasing 4.7 straightaway.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
index 87c73c2..0fe3cd9 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
@@ -247,156 +247,161 @@ public class ResourceGroupContextMenu extends Menu {
addItem(operations);
// Metric graph addition menu
- addItem(buildMetricsMenu(resourceType));
+ addItem(buildMetricsMenu(resourceType, group));
}
- private MenuItem buildMetricsMenu(final ResourceType type) {
+ private MenuItem buildMetricsMenu(final ResourceType type, final ResourceGroup resourceGroup) {
MenuItem measurements = new MenuItem(MSG.view_tree_common_contextMenu_measurements());
final Menu measurementsSubMenu = new Menu();
DashboardCriteria criteria = new DashboardCriteria();
- GWTServiceLookup.getDashboardService().findDashboardsByCriteria(criteria,
- new AsyncCallback<PageList<Dashboard>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_dashboards(),
- caught);
- }
-
- public void onSuccess(PageList<Dashboard> result) {
-
- if (type.getMetricDefinitions() != null) {
- //sort the display items alphabetically
- TreeSet<String> ordered = new TreeSet<String>();
- Map<String, MeasurementDefinition> definitionMap = new HashMap<String, MeasurementDefinition>();
- for (MeasurementDefinition m : type.getMetricDefinitions()) {
- ordered.add(m.getDisplayName());
- definitionMap.put(m.getDisplayName(), m);
- }
-
- for (String displayName : ordered) {
- final MeasurementDefinition def = definitionMap.get(displayName);
- //only add menu items for Measurement
- if (def.getDataType().equals(DataType.MEASUREMENT)) {
- MenuItem defItem = new MenuItem(def.getDisplayName());
- measurementsSubMenu.addItem(defItem);
- Menu defSubItem = new Menu();
- defItem.setSubmenu(defSubItem);
-
- for (final Dashboard d : result) {
- MenuItem addToDBItem = new MenuItem(MSG
- .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
- defSubItem.addItem(addToDBItem);
-
- addToDBItem.addClickHandler(new ClickHandler() {
- public void onClick(MenuItemClickEvent menuItemClickEvent) {
-
- DashboardPortlet p = new DashboardPortlet(MSG
- .view_tree_common_contextMenu_groupGraph(),
- ResourceGroupD3GraphPortlet.KEY, 250);
- p.getConfiguration().put(
- new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
- group.getId()));
- p.getConfiguration().put(
- new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
- .getId()));
-
- d.addPortlet(p);
-
- GWTServiceLookup.getDashboardService().storeDashboard(d,
- new AsyncCallback<Dashboard>() {
- public void onFailure(Throwable caught) {
- CoreGUI
- .getErrorHandler()
- .handleError(
- MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
- caught);
- }
-
- public void onSuccess(Dashboard result) {
- String msg = MSG
- .view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
- .getName());
- CoreGUI.getMessageCenter().notify(
- new Message(msg, Message.Severity.Info));
- }
- });
-
- }
- });
-
- //add new menu item for adding current graphable element to view if on Monitor/Graphs tab
- String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/NewGraphs") > -1) {
- MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
- defSubItem.addItem(addGraphItem);
+ final EntityContext context = EntityContext.forGroup(resourceGroup);
+ if(!context.isAutoGroup()){
+
+ GWTServiceLookup.getDashboardService().findDashboardsByCriteria(criteria,
+ new AsyncCallback<PageList<Dashboard>>() {
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_dashboards(),
+ caught);
+ }
- addGraphItem.addClickHandler(new ClickHandler() {
+ public void onSuccess(PageList<Dashboard> result) {
+
+ if (type.getMetricDefinitions() != null) {
+ //sort the display items alphabetically
+ TreeSet<String> ordered = new TreeSet<String>();
+ Map<String, MeasurementDefinition> definitionMap = new HashMap<String, MeasurementDefinition>();
+ for (MeasurementDefinition m : type.getMetricDefinitions()) {
+ ordered.add(m.getDisplayName());
+ definitionMap.put(m.getDisplayName(), m);
+ }
+
+ for (String displayName : ordered) {
+ final MeasurementDefinition def = definitionMap.get(displayName);
+ //only add menu items for Measurement
+ if (def.getDataType().equals(DataType.MEASUREMENT)) {
+ MenuItem defItem = new MenuItem(def.getDisplayName());
+ measurementsSubMenu.addItem(defItem);
+ Menu defSubItem = new Menu();
+ defItem.setSubmenu(defSubItem);
+
+ for (final Dashboard d : result) {
+
+ MenuItem addToDBItem = new MenuItem(MSG
+ .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
+ defSubItem.addItem(addToDBItem);
+
+ addToDBItem.addClickHandler(new ClickHandler() {
public void onClick(MenuItemClickEvent menuItemClickEvent) {
- //generate javascript to call out to.
- //Ex. menuLayers.hide();addMetric('${metric.resourceId},${metric.scheduleId}')
- String grpGraphElements = "";
- if (isAutoGroup) {
- grpGraphElements += "ag,";
- } else {
- grpGraphElements += "cg,";
- }
- grpGraphElements += group.getId() + "," + def.getId();
- if (isAutoGroup) {//need to postpend the resource type as third element
- grpGraphElements += "," + group.getResourceType().getId();
- }
- //construct portal.war url to access
- String baseUrl = "/resource/common/monitor/visibility/IndicatorCharts.do";
- //No need to rebuild the autogroup url as everything handled as a compatible group now
- // if (isAutoGroup) {
- // //Ex. ?parent=10001&ctype=1013&view=Default
- // baseUrl += "?parent=" + group.getAutoGroupParentResource().getId()
- // + "&ctype="
- // + group.getResourceType().getId();
- // jsCode = "ag," + group.getAutoGroupParentResource().getId() + ","
- // + def.getId() + ","
- // + group.getResourceType().getId();
- // } else {
- //Ex. ?groupId=10001&view=Default
- baseUrl += "?groupId=" + group.getId();
- baseUrl += "&view=Default";
- baseUrl += "&action=addChart&metric=" + grpGraphElements;
- baseUrl += "&view=Default";
- final String url = baseUrl;
- //initiate HTTP request
- final RequestBuilder b = new RequestBuilder(RequestBuilder.GET, baseUrl);
-
- try {
- b.setCallback(new RequestCallback() {
- public void onResponseReceived(final Request request,
- final Response response) {
- Log.trace("Successfully submitted request to add graph to view:"
- + url);
-
- //kick off a page reload.
- String currentViewPath = History.getToken();
- CoreGUI.goToView(currentViewPath, true);
+
+ DashboardPortlet p = new DashboardPortlet(MSG
+ .view_tree_common_contextMenu_groupGraph(),
+ ResourceGroupD3GraphPortlet.KEY, 250);
+ p.getConfiguration().put(
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
+ group.getId()));
+ p.getConfiguration().put(
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
+ .getId()));
+
+ d.addPortlet(p);
+
+ GWTServiceLookup.getDashboardService().storeDashboard(d,
+ new AsyncCallback<Dashboard>() {
+ public void onFailure(Throwable caught) {
+ CoreGUI
+ .getErrorHandler()
+ .handleError(
+ MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
+ caught);
}
- @Override
- public void onError(Request request, Throwable t) {
- Log.trace("Error adding Metric:" + url, t);
+ public void onSuccess(Dashboard result) {
+ String msg = MSG
+ .view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
+ .getName());
+ CoreGUI.getMessageCenter().notify(
+ new Message(msg, Message.Severity.Info));
}
});
- b.send();
- } catch (RequestException e) {
- Log.trace("Error adding Metric:" + url, e);
- }
- }//end of onClick definition
- });//end of onClick Handler definition
- }//end of Monitoring/Graphs view check
- }//end of dashabord iteration
- }//end of check for Measurement
- }//end of metric definition iteration
- }
- }
- });
+ }
+ });
+
+ //add new menu item for adding current graphable element to view if on Monitor/Graphs tab
+ String currentViewPath = History.getToken();
+ if (currentViewPath.contains("Monitoring/NewGraphs")) {
+ MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
+ defSubItem.addItem(addGraphItem);
+
+ addGraphItem.addClickHandler(new ClickHandler() {
+ public void onClick(MenuItemClickEvent menuItemClickEvent) {
+ //generate javascript to call out to.
+ //Ex. menuLayers.hide();addMetric('${metric.resourceId},${metric.scheduleId}')
+ String grpGraphElements = "";
+ if (isAutoGroup) {
+ grpGraphElements += "ag,";
+ } else {
+ grpGraphElements += "cg,";
+ }
+ grpGraphElements += group.getId() + "," + def.getId();
+ if (isAutoGroup) {//need to postpend the resource type as third element
+ grpGraphElements += "," + group.getResourceType().getId();
+ }
+ //construct portal.war url to access
+ String baseUrl = "/resource/common/monitor/visibility/IndicatorCharts.do";
+ //No need to rebuild the autogroup url as everything handled as a compatible group now
+ // if (isAutoGroup) {
+ // //Ex. ?parent=10001&ctype=1013&view=Default
+ // baseUrl += "?parent=" + group.getAutoGroupParentResource().getId()
+ // + "&ctype="
+ // + group.getResourceType().getId();
+ // jsCode = "ag," + group.getAutoGroupParentResource().getId() + ","
+ // + def.getId() + ","
+ // + group.getResourceType().getId();
+ // } else {
+ //Ex. ?groupId=10001&view=Default
+ baseUrl += "?groupId=" + group.getId();
+ baseUrl += "&view=Default";
+ baseUrl += "&action=addChart&metric=" + grpGraphElements;
+ baseUrl += "&view=Default";
+ final String url = baseUrl;
+ //initiate HTTP request
+ final RequestBuilder b = new RequestBuilder(RequestBuilder.GET, baseUrl);
+
+ try {
+ b.setCallback(new RequestCallback() {
+ public void onResponseReceived(final Request request,
+ final Response response) {
+ Log.trace("Successfully submitted request to add graph to view:"
+ + url);
+
+ //kick off a page reload.
+ String currentViewPath = History.getToken();
+ CoreGUI.goToView(currentViewPath, true);
+ }
+
+ @Override
+ public void onError(Request request, Throwable t) {
+ Log.trace("Error adding Metric:" + url, t);
+ }
+ });
+ b.send();
+ } catch (RequestException e) {
+ Log.trace("Error adding Metric:" + url, e);
+ }
+ }//end of onClick definition
+ });//end of onClick Handler definition
+ }//end of Monitoring/Graphs view check
+ }//end of dashabord iteration
+ }//end of check for Measurement
+ }//end of metric definition iteration
+ }
+
+ }
+ });
+ }
measurements.setSubmenu(measurementsSubMenu);
return measurements;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index 72a46a8..071f831 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -757,7 +757,7 @@ public class ResourceTreeView extends EnhancedVLayout {
defItem.setSubmenu(defSubItem);
for (final Dashboard d : result) {
- MenuItem addToDBItem = new MenuItem("d3-"+MSG
+ MenuItem addToDBItem = new MenuItem(MSG
.view_tree_common_contextMenu_addChartToDashboard(d.getName()));
defSubItem.addItem(addToDBItem);
@@ -802,7 +802,7 @@ public class ResourceTreeView extends EnhancedVLayout {
//add new menu item for adding current graphable element to view if on Monitor/Graphs tab
String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/Graphs") > -1) {
+ if (currentViewPath.contains("Monitoring/NewGraphs")) {
MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
defSubItem.addItem(addGraphItem);
commit d6ff5eb184fb65c358c2af40e42d0156f69c1475
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 2 07:47:04 2013 -0700
[BZ 924300] - Time range start date and the date picker disappears on clicking 'Advanced' button on time range selector.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
index 406a4fe..328112f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
@@ -257,7 +257,7 @@ public abstract class AbstractMeasurementRangeEditor extends DynamicForm impleme
protected void update() {
if (advanced) {
advancedSimpleButton.setTitle(MSG.view_measureRange_simple());
- showItem(ADVANCED_END_ITEM);
+ showItem(ADVANCED_START_ITEM);
showItem(ADVANCED_END_ITEM);
hideItem(SIMPLE_VALUE_ITEM);
hideItem(SIMPLE_UNIT_ITEM);
commit 8e62d50b8edd576ca3b53ecb9c198d9df288b35d
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Thu May 2 12:55:57 2013 +0200
Bug 952652 - Unable to delete a user who has saved searches objects in the database
Now deleting saved searches prior to deleting the user.
Merged delete methods.
Fail fast if caller tries to delete a superuser.
Added itest for the BZ
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
index 4b17dc5..9f204dd 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.auth.test;
@@ -41,6 +41,8 @@ import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.SubjectCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
@@ -50,6 +52,7 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.PermissionException;
import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.search.SavedSearchManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -70,12 +73,14 @@ public class SubjectManagerBeanTest extends AbstractEJB3Test {
private SubjectManagerLocal subjectManager;
private AuthorizationManagerLocal authorizationManager;
private RoleManagerLocal roleManager;
+ private SavedSearchManagerLocal savedSearchManager;
@Override
protected void beforeMethod() {
subjectManager = LookupUtil.getSubjectManager();
authorizationManager = LookupUtil.getAuthorizationManager();
roleManager = LookupUtil.getRoleManager();
+ savedSearchManager = LookupUtil.getSavedSearchManager();
createITestSubject();
}
@@ -756,4 +761,24 @@ public class SubjectManagerBeanTest extends AbstractEJB3Test {
}
});
}
-}
\ No newline at end of file
+
+ public void shouldBeAbleToDeleteASubjectWhoOwnsASavedSearch() {
+ // See https://bugzilla.redhat.com/show_bug.cgi?id=952652
+ SavedSearch savedSearch = new SavedSearch(SearchSubsystem.GROUP, "fake saved search", "pipo", subjectManager.getSubjectByName(ITEST_USER));
+ Integer savedSearchId = savedSearchManager.createSavedSearch(subjectManager.getOverlord(), savedSearch);
+ boolean subjectDeleted = false;
+ try {
+ deleteITestSubject();
+ subjectDeleted = true;
+ } catch (Exception e) {
+ LOG.error("Failed to delete a subject who owns a saved search", e);
+ fail("Failed to delete a subject who owns a saved search");
+ } finally {
+ // This is only necessary if we failed to delete subject
+ if (!subjectDeleted) {
+ savedSearchManager.deleteSavedSearch(subjectManager.getOverlord(), savedSearchId);
+ }
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
index c78a1bd..43d955f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.auth;
@@ -59,8 +59,10 @@ import org.rhq.core.domain.common.composite.SystemSettings;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.RoleCriteria;
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
import org.rhq.core.domain.criteria.SubjectCriteria;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.search.SavedSearch;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -75,6 +77,7 @@ import org.rhq.enterprise.server.core.CustomJaasDeploymentServiceMBean;
import org.rhq.enterprise.server.exception.LoginException;
import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.search.SavedSearchManagerLocal;
import org.rhq.enterprise.server.system.SystemManagerLocal;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
@@ -117,6 +120,9 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
//@IgnoreDependency
private RepoManagerLocal repoManager;
+ @EJB
+ private SavedSearchManagerLocal savedSearchManager;
+
@Resource
private TimerService timerService;
@@ -661,6 +667,10 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
throw new PermissionException("You cannot remove yourself: " + doomedSubject.getName());
}
+ if (authorizationManager.isSystemSuperuser(doomedSubject)) {
+ throw new PermissionException("You cannot delete a system root user - they must always exist");
+ }
+
Set<Role> roles = doomedSubject.getRoles();
doomedSubject.setRoles(new HashSet<Role>()); // clean out roles
@@ -694,7 +704,20 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
}
}
- deleteSubject(doomedSubject);
+ // Delete searches saved by this user
+ SavedSearchCriteria savedSearchCriteria = new SavedSearchCriteria();
+ savedSearchCriteria.addFilterSubjectId(doomedSubjectId);
+ savedSearchCriteria.clearPaging();
+ PageList<SavedSearch> savedSearches = savedSearchManager.findSavedSearchesByCriteria(subject, savedSearchCriteria);
+ for (SavedSearch savedSearch : savedSearches) {
+ savedSearchManager.deleteSavedSearch(subject, savedSearch.getId());
+ }
+
+ alertNotificationManager.cleanseAlertNotificationBySubject(doomedSubject.getId());
+
+ repoManager.removeOwnershipOfSubject(doomedSubject.getId());
+
+ entityManager.remove(doomedSubject);
}
return;
@@ -709,27 +732,6 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
}
/**
- * Deletes the given {@link Subject} from the database.
- *
- *
- * @param doomedSubject identifies the subject to delete
- *
- * @throws PermissionException if caller tried to delete a system superuser
- */
- private void deleteSubject(Subject doomedSubject) throws PermissionException {
- if (authorizationManager.isSystemSuperuser(doomedSubject)) {
- throw new PermissionException("You cannot delete a system root user - they must always exist");
- }
-
- alertNotificationManager.cleanseAlertNotificationBySubject(doomedSubject.getId());
- repoManager.removeOwnershipOfSubject(doomedSubject.getId());
-
- entityManager.remove(doomedSubject);
-
- return;
- }
-
- /**
* Delete a user's principal from the internal database.
*
*
@@ -883,4 +885,4 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
return;
}
-}
\ No newline at end of file
+}
commit 248cb85b93eadfe328fc4f8e0ab708239a813610
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 16:50:11 2013 -0700
Javascript console object is not valid under IE8 removing console.log statement.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
index 7390349..75ce6e3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
@@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
/**
* Contains the javascript chart definition for an IE8 d3 Stacked Bar graph chart.
+ * Curr
*
* @author Mike Thompson
*/
@@ -39,8 +40,7 @@ public final class StackedBarMetricGraphIE8Impl extends StackedBarMetricGraphImp
*/
@Override
public native void drawJsniChart() /*-{
- console.log("Using StackedBarMetricGraphIE8Impl for IE8.");
-
+ // no-op implementation for ie8
}-*/;
}
commit 339eb402b41277d45bb32b8b6da837cb02c2f38e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 14:59:58 2013 -0700
Fix to keep IE9 from behaving like IE8 with respect to charting.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index d682a24..d942b8c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -38,8 +38,8 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
* and User Preferences pickers for the date range.
*/
public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh {
- protected static int SINGLE_CHART_HEIGHT = 225;
- protected static int MULTI_CHART_HEIGHT = 195;
+ protected final static int SINGLE_CHART_HEIGHT = 225;
+ protected final static int MULTI_CHART_HEIGHT = 195;
protected List<Availability> availabilityList;
protected List<ResourceGroupAvailability> groupAvailabilityList;
protected AvailabilityD3Graph availabilityGraph;
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index f3c93be..d5ae804 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -36,6 +36,10 @@
</any>
</replace-with>
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
+ </replace-with>
+
<replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphIE8Impl">
<when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
<when-property-is name="user.agent" value="ie8"/>
commit 93a7c3264c30a6ea08d2c767fa6f087a3a86aa1d
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 07:54:40 2013 -0700
Fix IE issues with "Move jquery(1.7.2) library out of CoreGUI.gwt.xml now that we don't have GFlot dependency (GFlot was removed with addition of d3 charts)."
This reverts commit 8c54ef01abaa6790f49f96c492fe6649a0245a6f.
Revert "UI Performance - Move non-essential javascripts (like charting) out of CoreGUI.gwt.xml to CoreGUI.html and add the 'defer' script evaluation attribute for faster page load time. Also moved stylesheets to load ahead of javascripts as they load faster and provide less blocking time than the external javascripts. This shaved about 0.5 sec on my box will probably save more on slower hardware/connection/mobile. The *.gwt.xml prevents race conditions at the expense of speed so moving out increases startup speed."
This commit has unintended consequences for IE9 browser. Javascript
libraries that are supposed to be loaded are not (although this works in
other browsers).
This reverts commit e4ac4b1b628ae5e577510045ead7967a603d4c1c.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 7d50e87..f3c93be 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,6 +46,17 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
+ <!-- External javascript libraries -->
+ <!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
+ embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
+ the version of jquery (1.7.2).
+ -->
+ <script src="/coregui/js/jquery-1.7.2.min.js"/>
+ <script src="/coregui/js/jquery.sparkline-2.1.min.js"/>
+ <script src="/coregui/js/d3.v3.js"/>
+ <script src="/coregui/js/nv.d3.js"/>
+ <script src="/coregui/js/jquery.tipsy.js"/>
+
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 1b69b53..206b586 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -10,19 +10,7 @@
<!-- support internationalized characters -->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
- <link rel="stylesheet" href="CoreGUI.css">
- <link rel="stylesheet" href="css/nv.d3.css">
- <link rel="stylesheet" href="css/tipsy.css">
- <link rel="stylesheet" href="css/charts.css">
-
- <script defer="defer" type="text/javascript" src="/coregui/js/rhq.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/d3.v3.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/nv.d3.js"></script>
- <!-- jquery dependent js libs -->
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery-1.7.2.min.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.tipsy.js"></script>
-
+ <script type="text/javascript" src="js/rhq.js"></script>
<script type="text/javascript">
var search = location.search;
// only do this if you have not specified locale as query param
@@ -42,6 +30,12 @@
var isomorphicDir = "org.rhq.enterprise.gui.coregui.CoreGUI/sc/";
</script>
+
+ <link rel="stylesheet" href="CoreGUI.css">
+ <link rel="stylesheet" href="css/nv.d3.css">
+ <link rel="stylesheet" href="css/tipsy.css">
+ <link rel="stylesheet" href="css/charts.css">
+
</head>
<body>
commit 4c50679d28c84c2d0057c2438bb985c562fc8ac5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 1 12:14:40 2013 -0400
BZ 893609 - remove temp workaround code now that we are on a newer EAP that doesn't have the bad issues anymore
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 9a766f4..8cef6e1 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -46,6 +46,29 @@ public class CoreJBossASClient extends JBossASClient {
}
/**
+ * Given a string with possible ${x} expressions in it, this will resolve that expression
+ * using system property values that are set within the AS JVM itself. If the string
+ * to resolve has no expressions, or has no expressions that are resolveable, the expression
+ * string itself is returned as-is (this includes if <code>expression</code> is <code>null</code>).
+ *
+ * @param expression string containing zero, one or more ${x} expressions to be resolved
+ * @return the expression with the expressions resolved using system properties of the AS JVM
+ * @throws Exception if failed to resolve the expression.
+ */
+ public String resolveExpression(String expression) throws Exception {
+ if (expression == null || expression.length() == 0) {
+ return expression;
+ }
+ final ModelNode request = createRequest("resolve-expression", Address.root());
+ request.get("expression").set(expression);
+ final ModelNode response = execute(request);
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return getResults(response).asString();
+ }
+
+ /**
* This returns the system properties that are set in the AS JVM. This is not the system properties
* in the JVM of this client object - it is actually the system properties in the remote
* JVM of the AS instance that the client is talking to.
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
index babe373..ee7466e 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
@@ -72,7 +72,7 @@ public class LoggingJBossASClient extends JBossASClient {
final ModelNode request;
if (isLogger(loggerName)) {
- request = createWriteAttributeRequest("level", level.toUpperCase(), addr);
+ request = createWriteAttributeRequest("level", level, addr);
} else {
final String dmrTemplate = "" //
+ "{" //
@@ -80,7 +80,7 @@ public class LoggingJBossASClient extends JBossASClient {
+ ", \"level\" => \"%s\" " //
+ ", \"use-parent-handlers\" => \"true\" " //
+ "}";
- final String dmr = String.format(dmrTemplate, loggerName, level.toUpperCase());
+ final String dmr = String.format(dmrTemplate, loggerName, level);
request = ModelNode.fromString(dmr);
request.get(OPERATION).set(ADD);
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
index f977f0a..5caa45e 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
@@ -26,6 +26,7 @@ import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
/**
* Provides convenience methods associated with security domain management.
@@ -71,49 +72,6 @@ public class SecurityDomainJBossASClient extends JBossASClient {
* Create a new security domain using the SecureIdentity authentication method.
* This is used when you want to obfuscate a database password in the configuration.
*
- * @param securityDomainName the name of the new security domain
- * @param username the username associated with the security domain
- * @param password the value of the password to store in the configuration (e.g. the obfuscated password itself)
- *
- * @throws Exception if failed to create security domain
- */
- public void createNewSecureIdentitySecurityDomain71(String securityDomainName, String username, String password)
- throws Exception {
-
- Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN, securityDomainName);
- ModelNode addTopNode = createRequest(ADD, addr);
- addTopNode.get(CACHE_TYPE).set("default");
-
- ModelNode addAuthNode = createRequest(ADD, addr.clone().add(AUTHENTICATION, CLASSIC));
- ModelNode loginModulesNode = addAuthNode.get(LOGIN_MODULES);
- ModelNode loginModule = new ModelNode();
- loginModule.get(CODE).set("SecureIdentity");
- loginModule.get(FLAG).set("required");
- ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
- moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
- loginModulesNode.add(loginModule);
-
- ModelNode batch = createBatchRequest(addTopNode, addAuthNode);
-
- System.err.println("== security domain ==> " + batch.toJSONString(false));
-
- ModelNode results = execute(batch);
- if (!isSuccess(results)) {
- throw new FailureException(results, "Failed to create security domain [" + securityDomainName + "]");
- }
-
- return;
- }
-
- /**
- * Create a new security domain using the SecureIdentity authentication method.
- * This is used when you want to obfuscate a database password in the configuration.
- *
* This is the version for as7.2+ (e.g. eap 6.1)
*
* @param securityDomainName the name of the new security domain
@@ -139,11 +97,8 @@ public class SecurityDomainJBossASClient extends JBossASClient {
loginModule.get(FLAG).set("required");
ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
+ addPossibleExpression(moduleOptions, USERNAME, username);
+ addPossibleExpression(moduleOptions, PASSWORD, password);
ModelNode batch = createBatchRequest(addTopNode, addAuthNode, loginModule);
@@ -178,11 +133,8 @@ public class SecurityDomainJBossASClient extends JBossASClient {
loginModule.get(FLAG).set("required");
ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
+ addPossibleExpression(moduleOptions, USERNAME, username);
+ addPossibleExpression(moduleOptions, PASSWORD, password);
// login modules attribute must be a list - we only have one item in it, the loginModule
ModelNode loginModuleList = new ModelNode();
@@ -202,6 +154,14 @@ public class SecurityDomainJBossASClient extends JBossASClient {
return;
}
+ private void addPossibleExpression(ModelNode node, String name, String value) {
+ if (value != null && value.contains("${")) {
+ node.add(name, new ModelNode(ModelType.EXPRESSION).setExpression(value));
+ } else {
+ node.add(name, value);
+ }
+ }
+
/**
* Given the name of an existing security domain that uses the SecureIdentity authentication method,
* this returns the module options for that security domain authentication method. This includes
@@ -231,49 +191,6 @@ public class SecurityDomainJBossASClient extends JBossASClient {
/**
* Create a new security domain using the database server authentication method.
* This is used when you want to directly authenticate against a db entry.
- *
- * @param securityDomainName the name of the new security domain
- * @param dsJndiName the jndi name for the datasource to query against
- * @param principalsQuery the SQL query for selecting password info for a principal
- * @param rolesQuery the SQL query for selecting role info for a principal
- * @param hashAlgorithm if null defaults to "MD5"
- * @param hashEncoding if null defaults to "base64"
- * @throws Exception if failed to create security domain
- */
- public void createNewDatabaseServerSecurityDomain71(String securityDomainName, String dsJndiName,
- String principalsQuery, String rolesQuery, String hashAlgorithm,
- String hashEncoding) throws Exception {
-
- Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN, securityDomainName);
- ModelNode addTopNode = createRequest(ADD, addr);
- addTopNode.get(CACHE_TYPE).set("default");
-
- ModelNode addAuthNode = createRequest(ADD, addr.clone().add(AUTHENTICATION, CLASSIC));
- ModelNode loginModulesNode = addAuthNode.get(LOGIN_MODULES);
- ModelNode loginModule = new ModelNode();
- loginModule.get(CODE).set("Database");
- loginModule.get(FLAG).set("required");
- ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
- moduleOptions.setEmptyList();
- moduleOptions.add(DS_JNDI_NAME, dsJndiName);
- moduleOptions.add(PRINCIPALS_QUERY, principalsQuery);
- moduleOptions.add(ROLES_QUERY, rolesQuery);
- moduleOptions.add(HASH_ALGORITHM, (null == hashAlgorithm ? "MD5" : hashAlgorithm));
- moduleOptions.add(HASH_ENCODING, (null == hashEncoding ? "base64" : hashEncoding));
- loginModulesNode.add(loginModule);
-
- ModelNode batch = createBatchRequest(addTopNode, addAuthNode);
- ModelNode results = execute(batch);
- if (!isSuccess(results)) {
- throw new FailureException(results, "Failed to create security domain [" + securityDomainName + "]");
- }
-
- return;
- }
-
- /**
- * Create a new security domain using the database server authentication method.
- * This is used when you want to directly authenticate against a db entry.
* This is for AS 7.2+ (e.g. EAP 6.1) and works around https://issues.jboss.org/browse/AS7-6527
*
* @param securityDomainName the name of the new security domain
diff --git a/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh b/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
index fbbc397..5369ab2 100755
--- a/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
+++ b/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
@@ -18,8 +18,6 @@ do
eval ${_INSTALLER_SCRIPT}
if [ "$?" -eq "0" ]; then
echo Installer finished
- # most times, the installation was already done, but see if changes to rhq-server.properties requires a reconfiguration
- eval ${_INSTALLER_SCRIPT} --reconfig
break;
elif [ "$?" -eq "1" ]; then
echo The installer has been disabled - please fix rhq-server.properties
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 20ff84b..05619cb 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -495,16 +495,17 @@ rhq.communications.multicast-detector.port=16162
# Server-side SSL Security Configuration for HTTPS thru Tomcat
# These are used for browser https access and
# for incoming messages from agents over sslservlet transport.
-# Relative filenames are relative to jboss.server.config.dir.
-# [you cannot use ${x} variables in these rhq.server.tomcat settings]
+# [Due to issue https://issues.jboss.org/browse/WFLY-1177, you cannot change
+# rhq.server.tomcat.security.keystore.file or rhq.server.tomcat.security.truststore.file
+# after you install RHQ. If you need to change those again, you must manually do so in standalone-full.xml.]
rhq.server.tomcat.security.client-auth-mode=false
rhq.server.tomcat.security.secure-socket-protocol=TLS
rhq.server.tomcat.security.algorithm=SunX509
rhq.server.tomcat.security.keystore.alias=RHQ
-rhq.server.tomcat.security.keystore.file=rhq.keystore
+rhq.server.tomcat.security.keystore.file=${jboss.server.config.dir}/rhq.keystore
rhq.server.tomcat.security.keystore.password=RHQManagement
rhq.server.tomcat.security.keystore.type=JKS
-rhq.server.tomcat.security.truststore.file=rhq.truststore
+rhq.server.tomcat.security.truststore.file=${jboss.server.config.dir}/rhq.truststore
rhq.server.tomcat.security.truststore.password=RHQManagement
rhq.server.tomcat.security.truststore.type=JKS
@@ -637,32 +638,11 @@ rhq.sync.endpoint-address=false
</replace>
</target>
- <!-- This is so we can work around all the issues due to https://issues.jboss.org/browse/AS7-6120
- so once that is fixed, we don't have to run the installer "reconfig" automatically on startup of the server.
- Note that if we predeploy (i.e. are doing a dev build), rather than jump through more hoops for this,
- just assume the developer knows that if they change rhq-server.properties, they have to reconfig the server.
- We don't do anything in this target if we are building a dev build. -->
- <target name="add-auto-reconfig" unless="predeploy">
- <echo>Add auto-reconfig to rhq-server scripts so users don't have to when changing rhq-server.properties</echo>
- <replace file="${project.build.outputDirectory}/bin/rhq-server.sh">
- <replacefilter>
- <replacetoken># START SERVER</replacetoken>
- <replacevalue><![CDATA[export RHQ_SERVER_HOME; ${RHQ_SERVER_HOME}/bin/rhq-installer.sh --reconfig &]]></replacevalue>
- </replacefilter>
- </replace>
- <replace file="${project.build.outputDirectory}/bin/rhq-server.bat">
- <replacefilter>
- <replacetoken>rem START SERVER</replacetoken>
- <replacevalue><![CDATA[start /B %RHQ_SERVER_HOME%\bin\rhq-installer.bat --reconfig < nul > nul]]></replacevalue>
- </replacefilter>
- </replace>
- </target>
<target name="prepare-release"
description="If this is a release build, make sure it is properly prepared."
depends="initialize,
developer-release-message,
copy-dev-resources,
- add-auto-reconfig,
fix-perms,
deploy-postgres-ds,
deploy-oracle-ds">
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
index 26bc2f6..36da859 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
@@ -47,7 +47,7 @@ public class Installer {
private InstallerConfiguration installerConfig;
private enum WhatToDo {
- DISPLAY_USAGE, DO_NOTHING, RECONFIGURE, TEST, SETUPDB, LIST_SERVERS, INSTALL
+ DISPLAY_USAGE, DO_NOTHING, TEST, SETUPDB, LIST_SERVERS, INSTALL
}
public static void main(String[] args) {
@@ -108,20 +108,6 @@ public class Installer {
}
continue;
}
- case RECONFIGURE: {
- try {
- final InstallerService installerService = new InstallerServiceImpl(installerConfig);
- final HashMap<String, String> serverProperties = installerService.getServerProperties();
- final boolean reconfigured = installerService.reconfigure(serverProperties);
- if (reconfigured) {
- LOG.info("Reconfiguration is complete.");
- }
- } catch (Exception e) {
- LOG.error(ThrowableUtil.getAllMessages(e));
- System.exit(EXIT_CODE_INSTALLATION_ERROR);
- }
- continue;
- }
case INSTALL: {
try {
final InstallerService installerService = new InstallerServiceImpl(installerConfig);
@@ -159,28 +145,25 @@ public class Installer {
usage.append("\t--force, -f: force the installer to try to install everything").append("\n");
usage.append("\t--listservers, -l: show list of known installed servers (install not performed)").append("\n");
usage.append("\t--setupdb, -b: only perform database schema creation or update").append("\n");
- usage.append("\t--reconfig, -r: resets some configuration settings in an installed server").append("\n");
usage.append("\t--dbpassword, -d: encodes a DB password for rhq-server.properties (install not performed)")
.append("\n");
LOG.info(usage);
}
private WhatToDo[] processArguments(String[] args) throws Exception {
- String sopts = "-:HD:h:p:d:bflrt";
+ String sopts = "-:HD:h:p:d:bflt";
LongOpt[] lopts = { new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'H'),
new LongOpt("host", LongOpt.REQUIRED_ARGUMENT, null, 'h'),
new LongOpt("port", LongOpt.REQUIRED_ARGUMENT, null, 'p'),
new LongOpt("dbpassword", LongOpt.REQUIRED_ARGUMENT, null, 'd'),
new LongOpt("setupdb", LongOpt.NO_ARGUMENT, null, 'b'),
new LongOpt("listservers", LongOpt.NO_ARGUMENT, null, 'l'),
- new LongOpt("reconfig", LongOpt.NO_ARGUMENT, null, 'r'),
new LongOpt("force", LongOpt.NO_ARGUMENT, null, 'f'),
new LongOpt("test", LongOpt.NO_ARGUMENT, null, 't') };
boolean test = false;
boolean listservers = false;
boolean setupdb = false;
- boolean reconfig = false;
String dbpassword = null;
Getopt getopt = new Getopt("installer", args, sopts, lopts);
@@ -267,11 +250,6 @@ public class Installer {
break; // don't return, we need to allow more args to be processed, like -p or -h
}
- case 'r': {
- reconfig = true;
- break; // don't return, we need to allow more args to be processed, like -p or -h
- }
-
case 't': {
test = true;
break; // don't return, we need to allow more args to be processed, like -p or -h
@@ -286,10 +264,6 @@ public class Installer {
return new WhatToDo[] { WhatToDo.DO_NOTHING };
}
- if (reconfig) {
- return new WhatToDo[] { WhatToDo.RECONFIGURE };
- }
-
if (test || setupdb || listservers) {
ArrayList<WhatToDo> whatToDo = new ArrayList<WhatToDo>();
if (test) {
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
index c1ffa48..6eff4b7 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
@@ -121,23 +121,6 @@ public interface InstallerService {
String existingSchemaOption) throws Exception;
/**
- * This will take server properties and reconfigure an already-installed server
- * with those values if the settings were previously hardcoded to old values (as opposed to being
- * set to expressions that allow them to be overridden with system property settings).
- * Note that is function is here only to workaround various bugs in AS7
- * that force us to not be able to use expressions in certain app server subsystem attribute
- * settings - see https://issues.jboss.org/browse/AS7-6120. Once this issues are fixed, this
- * method will go away.
- *
- * @param serverProperties the new server properties
- * @return true if the reconfigure was at least attempted; false if the server isn't ready to be reconfigured
- * such as when it hasn't been fully installed yet
- * @throws Exception
- */
- @Deprecated
- boolean reconfigure(HashMap<String, String> serverProperties) throws Exception;
-
- /**
* Returns a list of all registered servers in the database.
*
* @param connectionUrl
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 95b4bc3..8173e68 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -563,81 +563,6 @@ public class InstallerServiceImpl implements InstallerService {
return map;
}
- // This is here only to help users workaround https://issues.jboss.org/browse/AS7-6120.
- // It will go away once all the issues with expression support in AS7 are fixed.
- // Notice in this method we only reconfigure some things - only the subsystems/services
- // that didn't support expressions in their attributes are reconfigured here since it
- // is those whose values are hardcoded and we must alter to pick up changes to
- // rhq-server.properties. All other services can pick up the property value changes
- // make to rhq-server.properties on restart (since rhq-server.properties are system
- // properties set in the AS7 instance via -P option to AS7).
- @Override
- public boolean reconfigure(HashMap<String, String> serverProperties) throws Exception {
-
- // make sure we can connect using our configuration
- testModelControllerClient(serverProperties, 30);
-
- if (null == getInstallationResults()) {
- log("Run the installer on this server.");
- return false;
- }
-
- String appServerConfigDir = getAppServerConfigDir();
- ModelControllerClient mcc = null;
-
- try {
- mcc = getModelControllerClient();
-
- // Before we do anything, let's first make sure we really do need to reconfigure something.
- // Check to see if everything that didn't use expressions is still the same. If so,
- // just skip everything else and return immediate since there is nothing to do. We don't
- // even need to reload/restart the server in this case.
- try {
- if (ServerInstallUtil.isSameDatasourceSecurityDomainExisting(mcc, serverProperties)) {
- if (ServerInstallUtil.isSameMailServiceExisting(mcc, serverProperties)) {
- if (ServerInstallUtil.isSameWebConnectorsExisting(mcc, appServerConfigDir, serverProperties)) {
- if (ServerInstallUtil.isSameLoggingExisting(mcc, serverProperties)) {
- log("Nothing in the configuration changed that requires a reconfig - everything looks OK");
- return true; // nothing to do, return immediately
- }
- }
- }
- }
- } catch (Exception e) {
- log("Cannot determine if the config is the same, will reconfigure just in case", e);
- }
-
- // first, put the server in admin-only mode so we can start changing things around
- CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- coreClient.reload(true);
-
- // not sure if we have to, but see if we need to wait for the reload to finish
- testModelControllerClient(30);
-
- mcc = getModelControllerClient(); // get a new controller
-
- // create the security domain needed by the datasources
- ServerInstallUtil.createDatasourceSecurityDomain(mcc, serverProperties);
-
- // setup the email service
- ServerInstallUtil.setupMailService(mcc, serverProperties);
-
- // setup the secure Tomcat web connectors
- ServerInstallUtil.setupWebConnectors(mcc, appServerConfigDir, serverProperties);
-
- // setup the logging level
- ServerInstallUtil.configureLogging(mcc, serverProperties);
-
- // now restart - don't just reload, some of our stuff won't restart properly if we just reload
- coreClient = new CoreJBossASClient(mcc);
- coreClient.restart();
- } finally {
- safeClose(mcc);
- }
-
- return true;
- }
-
/**
* Makes sure the data is at least in the correct format (booleans are true/false, integers are valid numbers).
*
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
index 687e496..d6e0d10 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
@@ -167,7 +167,7 @@ public class ServerInstallUtil {
LoggingJBossASClient client = new LoggingJBossASClient(mcc);
// we want to create our own category
- String val = buildExpression(ServerProperties.PROP_LOG_LEVEL, serverProperties, false); // enable when AS7-5321 is fixed
+ String val = buildExpression(ServerProperties.PROP_LOG_LEVEL, serverProperties, true);
client.setLoggerLevel("org.rhq", val);
LOG.info("Logging category org.rhq set to [" + val + "]");
}
@@ -209,7 +209,7 @@ public class ServerInstallUtil {
throws Exception {
String fromAddressExpr = buildExpression(ServerProperties.PROP_EMAIL_FROM_ADDRESS, serverProperties, true);
- String smtpHostExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_HOST, serverProperties, false); // enable when AS7-5321 is fixed
+ String smtpHostExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_HOST, serverProperties, true);
String smtpPortExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_PORT, serverProperties, true);
// Tweek the mail configuration that comes out of box. Setup a batch request to write the proper attributes.
@@ -283,19 +283,13 @@ public class ServerInstallUtil {
public static void createDatasourceSecurityDomain(ModelControllerClient mcc,
HashMap<String, String> serverProperties) throws Exception {
- final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
- final String obfuscatedPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+ final String dbUsername = buildExpression(ServerProperties.PROP_DATABASE_USERNAME, serverProperties, true);
+ final String obfuscatedPassword = buildExpression(ServerProperties.PROP_DATABASE_PASSWORD, serverProperties,
+ true);
final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- String asVersion = coreClient.getAppServerVersion();
final String securityDomain = RHQ_DS_SECURITY_DOMAIN;
if (!client.isSecurityDomain(securityDomain)) {
- if (asVersion.startsWith("7.2")) {
- client.createNewSecureIdentitySecurityDomain72(securityDomain, dbUsername, obfuscatedPassword);
- }
- else {
- client.createNewSecureIdentitySecurityDomain71(securityDomain, dbUsername, obfuscatedPassword);
- }
+ client.createNewSecureIdentitySecurityDomain72(securityDomain, dbUsername, obfuscatedPassword);
LOG.info("Security domain [" + securityDomain + "] created");
} else {
LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
@@ -384,21 +378,12 @@ public class ServerInstallUtil {
throws Exception {
final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- String asRelase = coreClient.getAppServerVersion();
final String securityDomain = RHQ_REST_SECURITY_DOMAIN;
if (!client.isSecurityDomain(securityDomain)) {
String dsJndiName = "java:jboss/datasources/" + RHQ_DATASOURCE_NAME_XA;
- if (asRelase.startsWith("7.2")) {
- client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- }
- else {
- client.createNewDatabaseServerSecurityDomain71(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- }
+ client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
+ "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
+ "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
LOG.info("Security domain [" + securityDomain + "] created");
} else {
LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
@@ -1256,15 +1241,24 @@ public class ServerInstallUtil {
LOG.info("Creating https connector...");
ConnectorConfiguration connector = buildSecureConnectorConfiguration(configDirStr, serverProperties);
- // verify that we have a truststore file - if user is relying on our self-signed certs, we'll have to create one for them
+ // https://issues.jboss.org/browse/WFLY-1177 - we need to resolve the paths right now. the user won't be able
+ // to change these again in the future unless they go directly into standalone.xml and change it manually
String truststoreFileString = connector.getSslConfiguration().getCaCertificateFile();
+ truststoreFileString = resolveExpression(mcc, truststoreFileString);
+ connector.getSslConfiguration().setCaCertificateFile(truststoreFileString);
+
+ String keystoreFileString = connector.getSslConfiguration().getCertificateKeyFile();
+ keystoreFileString = resolveExpression(mcc, keystoreFileString);
+ connector.getSslConfiguration().setCertificateKeyFile(keystoreFileString);
+
+ // verify that we have a truststore file - if user is relying on our self-signed certs, we'll have to create one for them
if (truststoreFileString == null) {
LOG.warn("Missing a valid truststore location - you must specify a valid truststore location!");
} else {
File truststoreFile = new File(truststoreFileString);
if (!truststoreFile.exists()) {
// user didn't provide a truststore file, copy the keystore and use it as the truststore; tell the user about this
- File keystoreFile = new File(connector.getSslConfiguration().getCertificateKeyFile());
+ File keystoreFile = new File(keystoreFileString);
if (!keystoreFile.isFile()) {
LOG.warn("Missing both keystore [" + keystoreFile + "] and truststore [" + truststoreFile + "]");
} else {
@@ -1283,41 +1277,64 @@ public class ServerInstallUtil {
LOG.info("https connector created.");
if (client.isConnector(connectorName)) {
+ client.changeConnector(connectorName, "max-connections",
+ buildExpression("rhq.server.startup.web.max-connections", serverProperties, true));
client.changeConnector(connectorName, "redirect-port",
- buildExpression("rhq.server.socket.binding.port.https", serverProperties, false));
+ buildExpression("rhq.server.socket.binding.port.https", serverProperties, true));
} else {
LOG.warn("There doesn't appear to be a http connector configured already - this is strange.");
}
}
+ private static String resolveExpression(ModelControllerClient mcc, String expression) {
+ if (expression == null) {
+ return null;
+ }
+
+ CoreJBossASClient client = new CoreJBossASClient(mcc);
+ String resolvedExpression;
+ try {
+ resolvedExpression = client.resolveExpression(expression);
+
+ // https://issues.jboss.org/browse/WFLY-1177 - app server doesn't do recursive resolving, we have to do it here
+ while (resolvedExpression != null && resolvedExpression.contains("${")
+ && !resolvedExpression.equals(expression)) {
+ expression = resolvedExpression;
+ resolvedExpression = client.resolveExpression(expression);
+ }
+ } catch (Exception e) {
+ LOG.warn("Cannot resolve expression [" + expression + "]; will use it as-is but errors may occur later.");
+ resolvedExpression = expression;
+ }
+ return resolvedExpression;
+ }
+
private static ConnectorConfiguration buildSecureConnectorConfiguration(String configDirStr,
HashMap<String, String> serverProperties) {
SSLConfiguration ssl = new SSLConfiguration();
// truststore
- ssl.setCaCertificateFile(getAbsoluteFileLocation("rhq.server.tomcat.security.truststore.file",
- serverProperties, configDirStr)); // this cannot be an expression - AS7 doesn't support that now
+ ssl.setCaCertificateFile(buildExpression("rhq.server.tomcat.security.truststore.file", serverProperties, true));
ssl.setCaCertificationPassword(buildExpression("rhq.server.tomcat.security.truststore.password",
- serverProperties, false));
- ssl.setTruststoreType(buildExpression("rhq.server.tomcat.security.truststore.type", serverProperties, false));
+ serverProperties, true));
+ ssl.setTruststoreType(buildExpression("rhq.server.tomcat.security.truststore.type", serverProperties, true));
// keystore
- ssl.setCertificateKeyFile(getAbsoluteFileLocation("rhq.server.tomcat.security.keystore.file", serverProperties,
- configDirStr)); // this cannot be an expression - AS7 doesn't support that now
- ssl.setPassword(buildExpression("rhq.server.tomcat.security.keystore.password", serverProperties, false));
- ssl.setKeyAlias(buildExpression("rhq.server.tomcat.security.keystore.alias", serverProperties, false));
- ssl.setKeystoreType(buildExpression("rhq.server.tomcat.security.keystore.type", serverProperties, false));
+ ssl.setCertificateKeyFile(buildExpression("rhq.server.tomcat.security.keystore.file", serverProperties, true));
+ ssl.setPassword(buildExpression("rhq.server.tomcat.security.keystore.password", serverProperties, true));
+ ssl.setKeyAlias(buildExpression("rhq.server.tomcat.security.keystore.alias", serverProperties, true));
+ ssl.setKeystoreType(buildExpression("rhq.server.tomcat.security.keystore.type", serverProperties, true));
// SSL protocol config
- ssl.setProtocol(buildExpression("rhq.server.tomcat.security.secure-socket-protocol", serverProperties, false));
- ssl.setVerifyClient(buildExpression("rhq.server.tomcat.security.client-auth-mode", serverProperties, false));
+ ssl.setProtocol(buildExpression("rhq.server.tomcat.security.secure-socket-protocol", serverProperties, true));
+ ssl.setVerifyClient(buildExpression("rhq.server.tomcat.security.client-auth-mode", serverProperties, true));
// note: there doesn't appear to be a way for AS7 to support algorithm, like SunX509 or IbmX509
// so I think it just uses the JVM's default. This means "rhq.server.tomcat.security.algorithm" is unused
ConnectorConfiguration connector = new ConnectorConfiguration();
- connector.setMaxConnections(buildExpression("rhq.server.startup.web.max-connections", serverProperties, false));
+ connector.setMaxConnections(buildExpression("rhq.server.startup.web.max-connections", serverProperties, true));
connector.setScheme("https");
connector.setSocketBinding("https");
connector.setSslConfiguration(ssl);
@@ -1502,159 +1519,4 @@ public class ServerInstallUtil {
}
}
}
-
- /**
- * This checks to see if the logging settings have the same values as those found in the given properties.
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the logging settings
- * @return true if the logging settings have the same values
- * @throws Exception
- */
- public static boolean isSameLoggingExisting(ModelControllerClient mcc, HashMap<String, String> serverProperties) {
- try {
- LoggingJBossASClient client = new LoggingJBossASClient(mcc);
- String currentLevel = client.getLoggerLevel("org.rhq");
- String newLevel = serverProperties.get(ServerProperties.PROP_LOG_LEVEL);
- return !isEmpty(currentLevel) && currentLevel.equalsIgnoreCase(newLevel);
- } catch (Exception e) {
- return false; // assume they aren't the same - this may be due to the category org.rhq just missing
- }
- }
-
- /**
- * This checks to see if the mail service already exists
- * and has the same settings as those found in the given properties.
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the mail service settings
- * @return true if the mail service exists with the same settings
- * @throws Exception
- */
- public static boolean isSameMailServiceExisting(ModelControllerClient mcc, HashMap<String, String> serverProperties)
- throws Exception {
- // we know the only problem attribute we care about is the smtp host - that's the only
- // one we use that doesn't support expressions. So we only need to check this one
- Address addr = Address.root().add("socket-binding-group", "standard-sockets",
- "remote-destination-outbound-socket-binding", "mail-smtp");
- JBossASClient client = new JBossASClient(mcc);
- String currentHost = client.getStringAttribute("host", addr);
- String host = serverProperties.get(ServerProperties.PROP_EMAIL_SMTP_HOST);
- return !isEmpty(currentHost) && currentHost.equals(host);
- }
-
- /**
- * This checks to see if the security domain for the datasources already exists
- * and has the same username/password as those found in the given properties
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the obfuscated password and username to compare
- * @return true if the domain exists with the same username and password
- * @throws Exception
- */
- public static boolean isSameDatasourceSecurityDomainExisting(ModelControllerClient mcc,
- HashMap<String, String> serverProperties) throws Exception {
-
- final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
- final String obfuscatedPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
- final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final String securityDomain = RHQ_DS_SECURITY_DOMAIN;
- boolean sameUsernamePassword = false;
- if (client.isSecurityDomain(securityDomain)) {
- boolean sameUsername = false;
- boolean samePassword = false;
- ModelNode opts;
- opts = client.getSecureIdentitySecurityDomainModuleOptions(securityDomain);
- if (opts != null) {
- List<ModelNode> optsList = opts.asList();
- for (ModelNode opt : optsList) {
- if (opt.has(SecurityDomainJBossASClient.USERNAME)) {
- sameUsername = dbUsername.equals(opt.get(SecurityDomainJBossASClient.USERNAME).asString());
- }
- if (opt.has(SecurityDomainJBossASClient.PASSWORD)) {
- samePassword = obfuscatedPassword.equals(opt.get(SecurityDomainJBossASClient.PASSWORD)
- .asString());
- }
- }
- }
- sameUsernamePassword = sameUsername & samePassword;
- }
- return sameUsernamePassword;
- }
-
- /**
- * This checks to see if the web connectors already exist
- * and have the same settings as those found in the given properties
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param configDirStr location of a configuration directory where the keystore is to be stored
- * @param serverProperties contains the obfuscated password and username to compare
- * @return true if the domain exists with the same username and password
- * @throws Exception
- */
- public static boolean isSameWebConnectorsExisting(ModelControllerClient mcc, String appServerConfigDir,
- HashMap<String, String> serverProperties) throws Exception {
-
- HashMap<String, String> settingsToCheck = new HashMap<String, String>();
- WebJBossASClient client = new WebJBossASClient(mcc);
-
- // FIRST check the https connector
- ModelNode httpsNode = client.getConnector("https");
-
- ConnectorConfiguration connectorConfig = buildSecureConnectorConfiguration(appServerConfigDir, serverProperties);
- SSLConfiguration sslConfig = connectorConfig.getSslConfiguration();
-
- // check the https connector's main config
- settingsToCheck.clear();
- settingsToCheck.put("max-connections", connectorConfig.getMaxConnections());
- for (Map.Entry<String, String> propToCheck : settingsToCheck.entrySet()) {
- if (!httpsNode.get(propToCheck.getKey()).asString().equals(propToCheck.getValue())) {
- return false; // something is different, no need to check further, return false to say we are different
- }
- }
-
- // now check the https connector's ssl config
- ModelNode sslNode = httpsNode.get("ssl").get("configuration");
- settingsToCheck.clear();
- settingsToCheck.put("ca-certificate-file", sslConfig.getCaCertificateFile());
- settingsToCheck.put("ca-certificate-password", sslConfig.getCaCertificatePassword());
- settingsToCheck.put("certificate-key-file", sslConfig.getCertificateKeyFile());
- settingsToCheck.put("key-alias", sslConfig.getKeyAlias());
- settingsToCheck.put("keystore-type", sslConfig.getKeystoreType());
- settingsToCheck.put("password", sslConfig.getPassword());
- settingsToCheck.put("protocol", sslConfig.getProtocol());
- settingsToCheck.put("truststore-type", sslConfig.getTruststoreType());
- settingsToCheck.put("verify-client", sslConfig.getVerifyClient());
- for (Map.Entry<String, String> propToCheck : settingsToCheck.entrySet()) {
- if (!sslNode.get(propToCheck.getKey()).asString().equals(propToCheck.getValue())) {
- return false; // something is different, no need to check further, return false to say we are different
- }
- }
-
- // SECOND check the http connector
- ModelNode httpNode = client.getConnector("http");
- String nodeString = httpNode.get("redirect-port").asString();
- String propString = serverProperties.get("rhq.server.socket.binding.port.https");
- if (!nodeString.equals(propString)) {
- return false; // something is different, no need to check further, return false to say we are different
- }
-
- return true;
- }
}
commit c430d28ff07adb87cccc8823a3b24d598867c462
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 14:47:27 2013 -0700
[BZ 950701] Fix SVG text fonts in d3 graphs so that they dont look fuzzy.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index 2693772..d9a4205 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -31,13 +31,6 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
public StackedBarMetricGraphImpl() {
super();
}
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
-// public StackedBarMetricGraphImpl(MetricGraphData metricGraphData) {
-// setMetricGraphData(metricGraphData);
-// }
/**
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 099f23a..8728026 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -27,11 +27,11 @@
}
.y.axis text, .x.axis text {
- font-family: 'Liberation Sans', Arial, Helvetica, sans-serif;
+ font-family: Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: normal;
font-style: normal;
- stroke: #50505a;
+ fill: #50505a;
text-rendering: optimize-legibility;
}
@@ -47,8 +47,8 @@
.minLabel, .avgLabel, .highLabel {
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
+ font-weight: bold;
text-anchor: start;
- stroke: #003168;
fill: #003168;
text-rendering: optimize-legibility;
}
@@ -57,7 +57,6 @@
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
text-anchor: start;
- stroke: #003168;
fill: #003168;
text-rendering: optimize-legibility;
}
commit 813c49855969171406f638a9d32112b722b99d19
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 13:37:35 2013 -0700
[BZ 955760] Syntax fix for gzip compression enablement.
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
index 29a6d76..4e90c62 100755
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
@@ -348,7 +348,7 @@ fi
# Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
# Note that the double equals for the policy file specification IS INTENTIONAL
-_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on org.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on -Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_HTTP_COMPRESSION} ${_JBOSS_DEBUG_LOGGING}"
debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
commit 8c54ef01abaa6790f49f96c492fe6649a0245a6f
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 09:06:23 2013 -0700
Move jquery(1.7.2) library out of CoreGUI.gwt.xml now that we don't have GFlot dependency (GFlot was removed with addition of d3 charts).
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 3d5ae84..7d50e87 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,14 +46,6 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
- <!-- External javascript libraries -->
- <!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
- embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
- the version of jquery (1.7.2).
- -->
- <script src="/coregui/js/jquery-1.7.2.min.js"/>
-
-
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 8722614..1b69b53 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -15,10 +15,12 @@
<link rel="stylesheet" href="css/tipsy.css">
<link rel="stylesheet" href="css/charts.css">
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/rhq.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/d3.v3.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/nv.d3.js"></script>
+ <!-- jquery dependent js libs -->
+ <script defer="defer" type="text/javascript" src="/coregui/js/jquery-1.7.2.min.js"></script>
+ <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/jquery.tipsy.js"></script>
<script type="text/javascript">
commit bcda4cd317f159f335aa544604ed9a0b0b3842a8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 15:41:46 2013 -0400
BZ 955760 - pass in the http compression sysprops to the RHQ Server at startup
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
index 42c8e45..29a6d76 100755
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
@@ -348,7 +348,8 @@ fi
# Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
# Note that the double equals for the policy file specification IS INTENTIONAL
-RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_JBOSS_DEBUG_LOGGING}"
+_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on org.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_HTTP_COMPRESSION} ${_JBOSS_DEBUG_LOGGING}"
debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
debug_msg "RHQ_SERVER_ADDITIONAL_JAVA_OPTS: $RHQ_SERVER_ADDITIONAL_JAVA_OPTS"
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
index 3780f90..c5afd1b 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
@@ -82,11 +82,14 @@ wrapper.java.additional.18=-Dsun.lang.ClassLoader.allowArraySyntax=true
wrapper.java.additional.19=-Djava.security.manager
# the double equals for the policy file specification IS INTENTIONAL
wrapper.java.additional.20="-Djava.security.policy==%RHQ_SERVER_HOME%/bin/rhq-server.security-policy"
+wrapper.java.additional.21="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on"
+wrapper.java.additional.22="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+
# use these if your JVM supports it
-#wrapper.java.additional.21=-XX:+TieredCompilation
-#wrapper.java.additional.22=-XX:+UseCompressedOops
+#wrapper.java.additional.23=-XX:+TieredCompilation
+#wrapper.java.additional.24=-XX:+UseCompressedOops
# Don't need these now, but this is commented out in case we need to add an endorsed dir in the future
-#wrapper.java.additional.23="-Djava.endorsed.dirs=%RHQ_SERVER_HOME%/jbossas/lib/endorsed"
+#wrapper.java.additional.25="-Djava.endorsed.dirs=%RHQ_SERVER_HOME%/jbossas/lib/endorsed"
# We want to make sure the Server starts in the JBossAS bin directory
wrapper.working.dir=%RHQ_SERVER_HOME%/jbossas/bin
diff --git a/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc b/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
index b76cd2f..8094241 100644
--- a/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
+++ b/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
@@ -4,12 +4,12 @@
#
# enable remote debugging
-wrapper.java.additional.9=-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n
+wrapper.java.additional.23=-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n
# enable jprofiler
#set.PATH=%PATH%;<jprofiler-install-dir>\bin\windows
-#wrapper.java.additional.10=-agentlib:jprofilerti=port=8849
-#wrapper.java.additional.11=-Xbootclasspath/a:<jprofiler-install-dir>\bin\agent.jar
+#wrapper.java.additional.23=-agentlib:jprofilerti=port=8849
+#wrapper.java.additional.24=-Xbootclasspath/a:<jprofiler-install-dir>\bin\agent.jar
# disable JVM startup timeout
wrapper.startup.timeout=0
commit 9a4c406425741f4dc3ecc546c27aec5d558fa37b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 14:25:36 2013 -0400
BZ 917085 fix test to hopefully run on windows
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index f0605a2..76742e8 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -530,8 +530,21 @@ public class AntBundlePluginComponentTest {
assert winDirs.size() == 1 : "should only have 1 ext backup dir on windows: " + winDirs;
backupDir = winDirs.values().iterator().next().getAbsoluteFile();
}
- File file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
- File file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+
+ File file3Backup;
+ File file4Backup;
+ boolean isWindows = (File.separatorChar == '\\');
+ if (isWindows) {
+ StringBuilder file3AbsPath = new StringBuilder(file3Dest.getAbsolutePath());
+ StringBuilder file4AbsPath = new StringBuilder(file4Dest.getAbsolutePath());
+ FileUtil.stripDriveLetter(file3AbsPath);
+ FileUtil.stripDriveLetter(file4AbsPath);
+ file3Backup = new File(backupDir, file3AbsPath.toString());
+ file4Backup = new File(backupDir, file4AbsPath.toString());
+ } else {
+ file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
+ file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+ }
assert file3Backup.isFile() : "should have been backed up: " + file3Backup;
assert file4Backup.isFile() : "should have been backed up: " + file4Backup;
assert (TEST3 + "modified").equals(readFile(file3Backup)) : "bad backup file: " + file3Backup;
commit 03caa3d61d59d2e041750b0581a31098acf61f10
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 09:47:25 2013 -0400
these methods' @TranAttrib annotations are unused. Also, spoke to lukas, he said these methods should be made private
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
index bfe9f32..6689de5 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
@@ -21,8 +21,6 @@
package org.rhq.enterprise.server.test;
import javax.ejb.Singleton;
-import javax.ejb.TransactionAttribute;
-import javax.ejb.TransactionAttributeType;
import org.rhq.enterprise.server.core.StartupBean;
import org.rhq.enterprise.server.naming.NamingHack;
@@ -34,8 +32,7 @@ import org.rhq.enterprise.server.naming.NamingHack;
@Singleton
public class StrippedDownStartupBean {
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public void secureNaming() {
+ private void secureNaming() {
NamingHack.bruteForceInitialContextFactoryBuilder();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index 5b5aa8c..90ffbaf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -146,11 +146,8 @@ public class StartupBean implements StartupLocal {
/**
* Modifies the naming subsystem to be able to check for Java security permissions on JNDI lookup.
- * <p>
- * Made public so that this can be reused in tests.
*/
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public void secureNaming() {
+ private void secureNaming() {
NamingHack.bruteForceInitialContextFactoryBuilder();
}
commit c923c9a9951f9ee1bc352c65a6178f64225c14b3
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Apr 29 14:06:22 2013 -0700
[BZ 956875] - Remove old charts now that they have been validated with new d3 charts. Eliminates the confusing second set of charts. Also removed GFlot charting library from codebase as it is no longer needed.
diff --git a/.classpath b/.classpath
index 9ff8db2..aa4c157 100644
--- a/.classpath
+++ b/.classpath
@@ -279,7 +279,6 @@
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-user/2.5.0/gwt-user-2.5.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-dev/2.5.0/gwt-dev-2.5.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/smartgwt/smartgwt/3.0/smartgwt-3.0.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/com/googlecode/gflot/gflot/2.4.2/gflot-2.4.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/jcraft/jsch/0.1.29/jsch-0.1.29.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-jxpath/commons-jxpath/1.3/commons-jxpath-1.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/dbunit/dbunit/2.4.8/dbunit-2.4.8.jar"/>
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
index cea3bc0..f7dd822 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
@@ -39,11 +39,9 @@ import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupOobs
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupOperationsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupPkgHistoryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.queue.AutodiscoveryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.FavoriteResourcesPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.platform.PlatformSummaryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.recent.alerts.RecentAlertsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.recent.imported.RecentlyAddedResourcesPortlet;
@@ -100,9 +98,7 @@ public class PortletFactory {
globalPortletFactoryMap.put(PlatformSummaryPortlet.KEY, PlatformSummaryPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(AutodiscoveryPortlet.KEY, AutodiscoveryPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(RecentAlertsPortlet.KEY, RecentAlertsPortlet.Factory.INSTANCE);
- globalPortletFactoryMap.put(ResourceGraphPortlet.KEY, ResourceGraphPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(ResourceD3GraphPortlet.KEY, ResourceD3GraphPortlet.Factory.INSTANCE);
- globalPortletFactoryMap.put(ResourceGroupGraphPortlet.KEY, ResourceGroupGraphPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(ResourceGroupD3GraphPortlet.KEY, ResourceGroupD3GraphPortlet.Factory.INSTANCE);
//conditionally add tags. Defaults to true, not available in JON builds.
if (CoreGUI.isTagsEnabledForUI()) {
@@ -123,9 +119,7 @@ public class PortletFactory {
globalPortletNameMap.put(PlatformSummaryPortlet.NAME, PlatformSummaryPortlet.KEY);
globalPortletNameMap.put(AutodiscoveryPortlet.NAME, AutodiscoveryPortlet.KEY);
globalPortletNameMap.put(RecentAlertsPortlet.NAME, RecentAlertsPortlet.KEY);
- globalPortletNameMap.put(ResourceGraphPortlet.NAME, ResourceGraphPortlet.KEY);
globalPortletNameMap.put(ResourceD3GraphPortlet.NAME, ResourceD3GraphPortlet.KEY);
- globalPortletNameMap.put(ResourceGroupGraphPortlet.NAME, ResourceGroupGraphPortlet.KEY);
globalPortletNameMap.put(ResourceGroupD3GraphPortlet.NAME, ResourceGroupD3GraphPortlet.KEY);
//conditionally add tags. Defaults to true, not available in JON builds.
if (CoreGUI.isTagsEnabledForUI()) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
index 013332c..ed59f8b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
@@ -371,8 +371,8 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
}
}
DynamicForm row = new DynamicForm();
- row.setNumCols(4);
- row.setColWidths(65, "*", 20, 100);
+ row.setNumCols(3);
+ row.setColWidths(65, "*", 100);
row.setWidth100();
row.setAutoHeight();
row.setOverflow(Overflow.VISIBLE);
@@ -418,31 +418,7 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
link.disable();
}
- //@todo: this goes away once we have validated the new d3 charts
- final String destination = "/resource/common/monitor/Visibility.do?mode=chartSingleMetricMultiResource&groupId="
- + groupId + "&m=" + md.getId();
- LinkItem oldLink = AbstractActivityView.newLinkItem("*",
- destination);
- oldLink.setTooltip("Link to Old Charts");
- oldLink.setTitleVAlign(VerticalAlignment.TOP);
- oldLink.setAlign(Alignment.LEFT);
- oldLink.setClipValue(true);
- oldLink.setWrap(true);
- oldLink.setHeight(26);
- oldLink.setWidth("100%");
-
- oldLink.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- ChartViewWindow window = new ChartViewWindow(title);
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- // .extendLocatorId("View"),
- // AbstractActivityView.iframeLink(destination));
- window.addItem(iframe);
- window.show();
- }
- });
+
//Value
String convertedValue = AbstractActivityView
.convertLastValueForDisplay(lastValue, md);
@@ -452,7 +428,7 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
value.setAlign(Alignment.RIGHT);
value.setWidth("100%");
- row.setItems(graphContainer, link, oldLink, value);
+ row.setItems(graphContainer, link, value);
row.setWidth100();
//if graph content returned
if ((!md.getName().trim().contains("Trait."))
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
index 856a177..1416b9d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
@@ -80,7 +80,7 @@ public class ResourceGroupD3GraphPortlet extends MetricD3GraphView implements Au
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceGroupMetricD3";
// A default displayed, persisted name for the portlet
- public static final String NAME = "d3-" + MSG.view_portlet_defaultName_groupMetric();
+ public static final String NAME = MSG.view_portlet_defaultName_groupMetric();
// set on initial configuration, the window for this portlet view.
private PortletWindow portletWindow;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
deleted file mode 100644
index 6a728c7..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph;
-
-import com.smartgwt.client.data.Criteria;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.types.TitleOrientation;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
-import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpacerItem;
-
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.dashboard.DashboardPortlet;
-import org.rhq.core.domain.resource.group.GroupCategory;
-import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
-import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedEvent;
-import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedHandler;
-import org.rhq.enterprise.gui.coregui.client.dashboard.CustomSettingsPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.Portlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
-import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.ResourceGroupMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourceGroupSelector;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceGroupD3GraphPortlet
- */
-@Deprecated
-public class ResourceGroupGraphPortlet extends ResourceGroupMetricGraphView implements CustomSettingsPortlet {
-
- // A non-displayed, persisted identifier for the portlet
- public static final String KEY = "ResourceGroupMetric";
- // A default displayed, persisted name for the portlet
- public static final String NAME = MSG.view_portlet_defaultName_groupMetric();
-
- // set on initial configuration, the window for this portlet view.
- private PortletWindow portletWindow;
-
- public static final String CFG_RESOURCE_GROUP_ID = "resourceGroupId";
- public static final String CFG_DEFINITION_ID = "definitionId";
-
- public ResourceGroupGraphPortlet() {
- super();
- setOverflow(Overflow.HIDDEN);
- }
-
- public void configure(PortletWindow portletWindow, DashboardPortlet storedPortlet) {
-
- if (null == this.portletWindow && null != portletWindow) {
- this.portletWindow = portletWindow;
- }
-
- if ((null == storedPortlet) || (null == storedPortlet.getConfiguration())) {
- return;
- }
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID).getIntegerValue();
- if (integerValue != null)
- setEntityId(integerValue);
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null)
- setDefinitionId(propertySimple.getIntegerValue());
- }
- }
-
- public Canvas getHelpCanvas() {
- return new HTMLFlow(MSG.view_portlet_help_graph());
- }
-
- @Override
- protected void onDraw() {
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- removeMembers(getMembers());
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- super.onDraw();
- }
- }
-
- public DynamicForm getCustomSettingsForm() {
- final DynamicForm form = new DynamicForm();
- form.setWidth(750);
- form.setNumCols(1);
-
- final CanvasItem selectorItem = new CanvasItem();
- selectorItem.setTitleOrientation(TitleOrientation.TOP);
- selectorItem.setShowTitle(false);
-
- final SingleResourceGroupSelector resourceGroupSelector = new SingleResourceGroupSelector(
- GroupCategory.COMPATIBLE, false);
- resourceGroupSelector.setWidth(700);
- resourceGroupSelector.setHeight(300);
- //TODO, would probaby be nice to find a way to seed assigned with the current group
- //ListGridRecord rec = new ListGridRecord();
- //rec.setAttribute("id", getEntityId());
- //rec.setAttribute("name", "current");
- //resourceGroupSelector.setAssigned(new ListGridRecord[] { rec });
-
- final SelectItem metric = new SortedSelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
- @Override
- protected Criteria getPickListFilterCriteria() {
- Criteria criteria = new Criteria();
-
- if (resourceGroupSelector.getSelectedItems().size() == 1) {
- int groupId = resourceGroupSelector.getSelectedItems().iterator().next().getId();
- criteria.addCriteria(CFG_RESOURCE_GROUP_ID, groupId);
- form.setValue(CFG_RESOURCE_GROUP_ID, groupId);
- }
- return criteria;
- }
- };
- metric.setWidth(300);
- metric.setTitleOrientation(TitleOrientation.TOP);
- metric.setValueField("id");
- metric.setDisplayField("displayName");
- metric.setOptionDataSource(new ResourceScheduledMetricDatasource());
-
- resourceGroupSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() {
-
- public void onSelectionChanged(AssignedItemsChangedEvent event) {
-
- if (resourceGroupSelector.getSelectedItems().size() == 1) {
- metric.fetchData();
- form.clearValue(CFG_DEFINITION_ID);
- }
- }
- });
-
- final DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID).getIntegerValue();
- if (integerValue != null)
- form.setValue(CFG_RESOURCE_GROUP_ID, integerValue);
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null)
- form.setValue(CFG_DEFINITION_ID, propertySimple.getIntegerValue());
- }
-
- selectorItem.setCanvas(resourceGroupSelector);
- form.setFields(selectorItem, metric, new SpacerItem());
-
- form.addSubmitValuesHandler(new SubmitValuesHandler() {
- public void onSubmitValues(SubmitValuesEvent submitValuesEvent) {
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_RESOURCE_GROUP_ID, form.getValue(CFG_RESOURCE_GROUP_ID)));
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_DEFINITION_ID, form.getValue(CFG_DEFINITION_ID)));
-
- configure(portletWindow, storedPortlet);
-
- redraw();
- }
- });
-
- return form;
- }
-
- @Override
- public void redraw() {
- super.redraw();
-
- removeMembers(getMembers());
-
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID);
- if (simple == null | simple.getIntegerValue() == null) {
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- renderGraph();
- }
- }
-
- public static final class Factory implements PortletViewFactory {
- public static PortletViewFactory INSTANCE = new Factory();
-
- public final Portlet getInstance(EntityContext context) {
-
- return new ResourceGroupGraphPortlet();
- }
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
index d706da9..0d6bcfd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
@@ -75,7 +75,7 @@ public class ResourceD3GraphPortlet extends MetricD3GraphView implements AutoRef
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceMetricD3";
// A default displayed, persisted name for the portlet
- public static final String NAME = "d3-" + MSG.view_portlet_defaultName_resourceMetric();
+ public static final String NAME = MSG.view_portlet_defaultName_resourceMetric();
public static final String CFG_RESOURCE_ID = "resourceId";
public static final String CFG_DEFINITION_ID = "definitionId";
// set on initial configuration, the window for this portlet view.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java
deleted file mode 100644
index 5f38301..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph;
-
-import com.smartgwt.client.data.Criteria;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
-import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
-
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.dashboard.DashboardPortlet;
-import org.rhq.enterprise.gui.coregui.client.components.lookup.ResourceLookupComboBoxItem;
-import org.rhq.enterprise.gui.coregui.client.dashboard.CustomSettingsPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.Portlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceD3GraphPortlet
- */
-@Deprecated
-public class ResourceGraphPortlet extends ResourceMetricGraphView implements CustomSettingsPortlet {
-
- // A non-displayed, persisted identifier for the portlet
- public static final String KEY = "ResourceMetric";
- // A default displayed, persisted name for the portlet
- public static final String NAME = MSG.view_portlet_defaultName_resourceMetric();
-
- // set on initial configuration, the window for this portlet view.
- private PortletWindow portletWindow;
-
- public static final String CFG_RESOURCE_ID = "resourceId";
- public static final String CFG_DEFINITION_ID = "definitionId";
-
- public ResourceGraphPortlet() {
- super();
- setOverflow(Overflow.HIDDEN);
- }
-
- public void configure(PortletWindow portletWindow, DashboardPortlet storedPortlet) {
-
- if (null == this.portletWindow && null != portletWindow) {
- this.portletWindow = portletWindow;
- }
-
- if ((null == storedPortlet) || (null == storedPortlet.getConfiguration())) {
- return;
- }
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID) != null) {
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (propertySimple != null) {
- Integer integerValue = propertySimple.getIntegerValue();
- if (integerValue != null)
- setEntityId(integerValue);
- }
- propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null) {
-
- Integer integerValue = propertySimple.getIntegerValue();
- if (integerValue != null)
- setDefinitionId(integerValue);
- }
- }
- }
-
- public Canvas getHelpCanvas() {
- return new HTMLFlow(MSG.view_portlet_help_graph());
- }
-
- @Override
- protected void onDraw() {
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- removeMembers(getMembers());
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- super.onDraw();
- }
- }
-
- public DynamicForm getCustomSettingsForm() {
- final DynamicForm form = new DynamicForm();
-
- final ResourceLookupComboBoxItem resourceLookupComboBoxItem = new ResourceLookupComboBoxItem(CFG_RESOURCE_ID,
- MSG.common_title_resource());
- resourceLookupComboBoxItem.setWidth(300);
-
- final SelectItem metric = new SelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
- @Override
- protected Criteria getPickListFilterCriteria() {
- Criteria criteria = new Criteria();
-
- if (resourceLookupComboBoxItem.getValue() != null) {
- int resourceId = (Integer) resourceLookupComboBoxItem.getValue();
- criteria.addCriteria(CFG_RESOURCE_ID, resourceId);
- }
- return criteria;
- }
- };
-
- final DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- metric.setWidth(300);
- metric.setValueField("id");
- metric.setDisplayField("displayName");
- metric.setOptionDataSource(new ResourceScheduledMetricDatasource());
-
- resourceLookupComboBoxItem
- .addChangedHandler(new com.smartgwt.client.widgets.form.fields.events.ChangedHandler() {
- public void onChanged(ChangedEvent event) {
-
- if (form.getValue(CFG_RESOURCE_ID) instanceof Integer) {
- metric.fetchData();
- form.clearValue(CFG_DEFINITION_ID);
- }
- }
- });
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID).getIntegerValue();
- if (integerValue != null) {
- form.setValue(CFG_RESOURCE_ID, integerValue);
- }
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null) {
- form.setValue(CFG_DEFINITION_ID, propertySimple.getIntegerValue());
- }
- }
-
- form.setFields(resourceLookupComboBoxItem, metric);
-
- form.addSubmitValuesHandler(new SubmitValuesHandler() {
- public void onSubmitValues(SubmitValuesEvent submitValuesEvent) {
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_RESOURCE_ID, form.getValue(CFG_RESOURCE_ID)));
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_DEFINITION_ID, form.getValue(CFG_DEFINITION_ID)));
-
- configure(portletWindow, storedPortlet);
-
- redraw();
- }
- });
-
- return form;
- }
-
- @Override
- public void redraw() {
- super.redraw();
-
- removeMembers(getMembers());
-
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- renderGraph();
- }
- }
-
- public static final class Factory implements PortletViewFactory {
- public static PortletViewFactory INSTANCE = new Factory();
-
- @Override
- public final Portlet getInstance(EntityContext context) {
-
- return new ResourceGraphPortlet();
- }
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index 62afc42..39ce5bd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -243,8 +243,8 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
}
}
DynamicForm row = new DynamicForm();
- row.setNumCols(4);
- row.setColWidths(65, "*", 20, 100);
+ row.setNumCols(3);
+ row.setColWidths(65, "*", 100);
row.setWidth100();
row.setAutoHeight();
row.setOverflow(Overflow.VISIBLE);
@@ -297,31 +297,6 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
link.disable();
}
- //@todo: this goes away once we have validated charts
- final String chartTitle = md.getDisplayName();
- final String destination = "/resource/common/monitor/Visibility.do?mode=chartSingleMetricSingleResource&id="
- + resourceId + "&m=" + md.getId();
-
- //have link launch modal window on click
- LinkItem oldLink = AbstractActivityView.newLinkItem("*",
- destination);
- oldLink.setTooltip("Link to test Old Chart");
- oldLink.setTitleVAlign(VerticalAlignment.TOP);
- oldLink.setAlign(Alignment.LEFT);
- oldLink.setClipValue(true);
- oldLink.setWrap(true);
- oldLink.setHeight(26);
- oldLink.setWidth("100%");
- oldLink.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- ChartViewWindow window = new ChartViewWindow(chartTitle);
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- window.addItem(iframe);
- window.show();
- }
- });
//Value
String convertedValue;
@@ -332,7 +307,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
value.setVAlign(VerticalAlignment.TOP);
value.setAlign(Alignment.RIGHT);
- row.setItems(sparklineContainer, link, oldLink, value);
+ row.setItems(sparklineContainer, link, value);
row.setWidth100();
//if graph content returned
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
deleted file mode 100644
index c921acf..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common;
-
-import java.util.Date;
-import java.util.List;
-
-import ca.nanometrics.gflot.client.Axis;
-import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.SeriesHandler;
-import ca.nanometrics.gflot.client.SimplePlot;
-import ca.nanometrics.gflot.client.event.PlotHoverListener;
-import ca.nanometrics.gflot.client.event.PlotItem;
-import ca.nanometrics.gflot.client.event.PlotPosition;
-import ca.nanometrics.gflot.client.jsni.Plot;
-import ca.nanometrics.gflot.client.options.AxisOptions;
-import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
-import ca.nanometrics.gflot.client.options.GridOptions;
-import ca.nanometrics.gflot.client.options.LineSeriesOptions;
-import ca.nanometrics.gflot.client.options.PlotOptions;
-import ca.nanometrics.gflot.client.options.PointsSeriesOptions;
-import ca.nanometrics.gflot.client.options.TickFormatter;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
-import com.smartgwt.client.types.AnimationEffect;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.WidgetCanvas;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated this code will go away once D3 graphs have been validated.
- */
-@Deprecated
-public abstract class AbstractMetricGraphView extends EnhancedVLayout {
-
- private static final String INSTRUCTIONS = MSG.view_resource_monitor_graph_instructions();
-
- /*
- private static final String[] MONTH_NAMES = { MSG.common_calendar_january_short(),
- MSG.common_calendar_february_short(), MSG.common_calendar_march_short(), MSG.common_calendar_april_short(),
- MSG.common_calendar_may_short(), MSG.common_calendar_june_short(), MSG.common_calendar_july_short(),
- MSG.common_calendar_august_short(), MSG.common_calendar_september_short(), MSG.common_calendar_october_short(),
- MSG.common_calendar_november_short(), MSG.common_calendar_december_short() };
- */
-
- private final Label selectedPointLabel = new Label(INSTRUCTIONS);
- private final Label positionLabel = new Label();
- private final Label hoverLabel = new Label();
-
- private HTMLFlow resourceTitle;
-
- private int entityId;
- private int definitionId;
-
- private MeasurementDefinition definition;
- private List<MeasurementDataNumericHighLowComposite> data;
-
- public AbstractMetricGraphView() {
- super();
- }
-
- public AbstractMetricGraphView(int entityId, int definitionId) {
- this.entityId = entityId;
- this.definitionId = definitionId;
-
- // Should this not also set H+W=100?
- }
-
- public AbstractMetricGraphView(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- this.entityId = entityId;
- this.definition = def;
- this.data = data;
- setHeight100();
- setWidth100();
- }
-
- public abstract AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data);
-
- protected abstract void renderGraph();
-
- protected HTMLFlow getEntityTitle(){
- return resourceTitle;
- }
-
- public int getEntityId() {
- return this.entityId;
- }
-
- public void setEntityId(int entityId) {
- this.entityId = entityId;
- this.definition = null;
- }
-
- public int getDefinitionId() {
- return definitionId;
- }
-
- public void setDefinitionId(int definitionId) {
- this.definitionId = definitionId;
- this.definition = null;
- }
-
- public MeasurementDefinition getDefinition() {
- return definition;
- }
-
- public void setDefinition(MeasurementDefinition definition) {
- this.definition = definition;
- }
-
- public List<MeasurementDataNumericHighLowComposite> getData() {
- return data;
- }
-
- public void setData(List<MeasurementDataNumericHighLowComposite> data) {
- this.data = data;
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- renderGraph();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- renderGraph();
- }
-
- protected void drawGraph() {
-
- HLayout titleHLayout = new EnhancedHLayout();
-
- if (definition != null) {
- titleHLayout.setAutoHeight();
- titleHLayout.setWidth100();
-
- HTMLFlow entityTitle = getEntityTitle();
- if (null != entityTitle) {
- entityTitle.setWidth("*");
- titleHLayout.addMember(entityTitle);
- }
-
- if (supportsLiveGraphViewDialog()) {
- Img liveGraph = new Img("subsystems/monitor/Monitor_16.png", 16, 16);
- liveGraph.setTooltip(MSG.view_resource_monitor_graph_live_tooltip());
-
- liveGraph.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- displayLiveGraphViewDialog();
- }
- });
- titleHLayout.addMember(liveGraph);
- }
-
- addMember(titleHLayout);
-
- HTMLFlow title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
- title.setWidth100();
- title.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- displayAsDialog();
- }
- });
- addMember(title);
- }
-
- PlotModel model = new PlotModel();
- PlotOptions plotOptions = new PlotOptions();
- GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
- globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- globalSeriesOptions.setShadowSize(0);
- plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
-
- // You need make the grid hoverable <<<<<<<<<
- plotOptions
- .setGridOptions(new GridOptions().setHoverable(true).setMouseActiveRadius(10).setAutoHighlight(true));
-
- // create a series
- if (definition != null && data != null) {
- loadData(model, plotOptions);
- }
-
- // create the plot
- SimplePlot plot = new SimplePlot(model, plotOptions);
- plot.setSize(String.valueOf(getInnerContentWidth()),
- String.valueOf(getInnerContentHeight() - titleHLayout.getHeight() - 50));
- // "80%","80%");
-
- // add hover listener
- plot.addHoverListener(new PlotHoverListener() {
- public void onPlotHover(Plot plot, PlotPosition position, PlotItem item) {
- if (position != null) {
- positionLabel.setContents("position: (" + position.getX() + "," + position.getY() + ")");
- }
- if (item != null) {
- hoverLabel.setContents(getHover(item));
-
- hoverLabel.animateShow(AnimationEffect.FADE);
- if (hoverLabel.getLeft() > 0 || hoverLabel.getTop() > 0) {
- hoverLabel.animateMove(item.getPageX() + 10, item.getPageY() - 35);
- } else {
- hoverLabel.moveTo(item.getPageX() + 10, item.getPageY() - 35);
- }
- hoverLabel.redraw();
-
- selectedPointLabel.setContents("x: " + item.getDataPoint().getX() + ", y: "
- + item.getDataPoint().getY());
- } else {
- hoverLabel.animateHide(AnimationEffect.FADE);
- selectedPointLabel.setContents(INSTRUCTIONS);
- }
- }
- }, false);
-
- addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- hoverLabel.animateHide(AnimationEffect.FADE);
- }
- });
-
- hoverLabel.setOpacity(80);
- hoverLabel.setWrap(false);
- hoverLabel.setHeight(25);
- hoverLabel.setBackgroundColor("yellow");
- hoverLabel.setBorder("1px solid orange");
- hoverLabel.hide();
-
- if (hoverLabel.isDrawn())
- hoverLabel.redraw();
- else
- hoverLabel.draw();
-
- // put it on a panel
-
- addMember(new WidgetCanvas(plot));
-
- plot.setSize(String.valueOf(getInnerContentWidth()),
- String.valueOf(getInnerContentHeight() - titleHLayout.getHeight() - 50));
-
- }
-
- protected boolean supportsLiveGraphViewDialog() {
- return false;
- }
-
- protected void displayLiveGraphViewDialog() {
- return;
- }
-
- @Override
- public void destroy() {
- hoverLabel.destroy();
- super.destroy();
- }
-
- @Override
- public void hide() {
- super.hide();
- hoverLabel.hide();
- }
-
- protected String getHover(PlotItem item) {
- if (definition != null) {
- com.google.gwt.i18n.client.DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return definition.getDisplayName() + ": "
- + MeasurementConverterClient.format(item.getDataPoint().getY(), definition.getUnits(), true) + "<br/>"
- + df.format(new Date((long) item.getDataPoint().getX()));
- } else {
- return "x: " + item.getDataPoint().getX() + ", y: " + item.getDataPoint().getY();
- }
- }
-
- protected void loadData(PlotModel model, PlotOptions plotOptions) {
- SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
-
- for (MeasurementDataNumericHighLowComposite d : data) {
- if (!Double.isNaN(d.getValue())) {
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
- }
- }
-
- plotOptions.addYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
- .setTickFormatter(new TickFormatter() {
- public String formatTickValue(double v, Axis axis) {
- return MeasurementConverterClient.format(v, definition.getUnits(), true);
- }
- }));
-
- int xTicks = getDefaultWidth() / 140;
-
- plotOptions.addXAxisOptions(new AxisOptions().setTicks(xTicks).setTickFormatter(new TickFormatter() {
- public String formatTickValue(double tickValue, Axis axis) {
- com.google.gwt.i18n.client.DateTimeFormat dateFormat = DateTimeFormat
- .getFormat(PredefinedFormat.DATE_TIME_SHORT);
- return dateFormat.format(new Date((long) tickValue));
- // return String.valueOf(new Date((long) tickValue));
- // return MONTH_NAMES[(int) (tickValue - 1)];
- }
- }));
-
- }
-
- private void displayAsDialog() {
- AbstractMetricGraphView graph = getInstance(entityId, definition, data);
- Window graphPopup = new Window();
- graphPopup.setTitle(MSG.view_resource_monitor_detailed_graph_label());
- graphPopup.setWidth(800);
- graphPopup.setHeight(400);
- graphPopup.setIsModal(true);
- graphPopup.setShowModalMask(true);
- graphPopup.setCanDragResize(true);
- graphPopup.centerInPage();
- graphPopup.addItem(graph);
- graphPopup.show();
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
index ca6d9f1..87c73c2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
@@ -59,7 +59,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupGraphPortlet;
+import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupD3GraphPortlet;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceDetailView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceTreeDatasource.AutoGroupTreeNode;
@@ -248,69 +248,8 @@ public class ResourceGroupContextMenu extends Menu {
// Metric graph addition menu
addItem(buildMetricsMenu(resourceType));
-
- /* TODO: We don't support group factory create
- // Create Menu
- MenuItem createChildMenu = new MenuItem("Create Child");
- Menu createChildSubMenu = new Menu();
- for (final ResourceType childType : resourceType.getChildResourceTypes()) {
- if (childType.isCreatable()) {
- MenuItem createItem = new MenuItem(childType.getName());
- createChildSubMenu.addItem(createItem);
- createItem.addClickHandler(new ClickHandler() {
- public void onClick(MenuItemClickEvent event) {
- ResourceFactoryCreateWizard.showCreateWizard(resource, childType);
- }
- });
-
- }
- }
- createChildMenu.setSubmenu(createChildSubMenu);
- createChildMenu.setEnabled(createChildSubMenu.getItems().length > 0);
- contextMenu.addItem(createChildMenu);*/
-
- /*
- // TODO We don't group manual import
- // Manually Add Menu
- MenuItem importChildMenu = new MenuItem("Import");
- Menu importChildSubMenu = new Menu();
- for (ResourceType childType : resourceType.getChildResourceTypes()) {
- if (childType.isSupportsManualAdd()) {
- importChildSubMenu.addItem(new MenuItem(childType.getName()));
- }
- }
- if (resourceType.getCategory() == ResourceCategory.PLATFORM) {
- loadManuallyAddServersToPlatforms(importChildSubMenu);
- }
- importChildMenu.setSubmenu(importChildSubMenu);
- importChildMenu.setEnabled(importChildSubMenu.getItems().length > 0);
- addItem(importChildMenu);
- */
}
- /*
- private void loadManuallyAddServersToPlatforms(final Menu manuallyAddMenu) {
- ResourceTypeGWTServiceAsync rts = GWTServiceLookup.getResourceTypeGWTService();
-
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterSupportsManualAdd(true);
- criteria.fetchParentResourceTypes(true);
- rts.findResourceTypesByCriteria(criteria, new AsyncCallback<PageList<ResourceType>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_children(), caught);
- }
-
- public void onSuccess(PageList<ResourceType> result) {
- for (ResourceType type : result) {
- if (type.getParentResourceTypes() == null || type.getParentResourceTypes().isEmpty()) {
- MenuItem item = new MenuItem(type.getName());
- manuallyAddMenu.addItem(item);
- }
- }
- }
- });
- }
- */
private MenuItem buildMetricsMenu(final ResourceType type) {
MenuItem measurements = new MenuItem(MSG.view_tree_common_contextMenu_measurements());
@@ -354,12 +293,12 @@ public class ResourceGroupContextMenu extends Menu {
DashboardPortlet p = new DashboardPortlet(MSG
.view_tree_common_contextMenu_groupGraph(),
- ResourceGroupGraphPortlet.KEY, 250);
+ ResourceGroupD3GraphPortlet.KEY, 250);
p.getConfiguration().put(
- new PropertySimple(ResourceGroupGraphPortlet.CFG_RESOURCE_GROUP_ID,
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
group.getId()));
p.getConfiguration().put(
- new PropertySimple(ResourceGroupGraphPortlet.CFG_DEFINITION_ID, def
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
.getId()));
d.addPortlet(p);
@@ -388,7 +327,7 @@ public class ResourceGroupContextMenu extends Menu {
//add new menu item for adding current graphable element to view if on Monitor/Graphs tab
String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/Graphs") > -1) {
+ if (currentViewPath.indexOf("Monitoring/NewGraphs") > -1) {
MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
defSubItem.addItem(addGraphItem);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
index b695b4f..07622e3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
@@ -55,7 +55,6 @@ import org.rhq.enterprise.gui.coregui.client.components.view.ViewName;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.AbstractTwoLevelTabSetView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.monitoring.IFrameWithMeasurementRangeEditorView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.event.EventCompositeHistoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration.GroupResourceConfigurationEditView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration.HistoryGroupResourceConfigurationView;
@@ -101,7 +100,6 @@ public class ResourceGroupDetailView extends
// subtabs
private SubTab summaryActivity;
private SubTab summaryTimeline;
- private SubTab monitorGraphs;
private SubTab monitorNewGraphs;
private SubTab monitorTables;
private SubTab monitorTraits;
@@ -193,14 +191,13 @@ public class ResourceGroupDetailView extends
monitoringTab = new TwoLevelTab(new ViewName("Monitoring", MSG.view_tabs_common_monitoring()),
IconEnum.SUSPECT_METRICS);
- monitorGraphs = new SubTab(monitoringTab, new ViewName("Graphs", MSG.view_tabs_common_graphs()), null);
- monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", "d3 Graphs"), null);
+ monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorGraphs, monitorNewGraphs, monitorTables, monitorTraits, monitorSched,
+ monitoringTab.registerSubTabs( monitorNewGraphs, monitorTables, monitorTraits, monitorSched,
monitorCallTime);
tabs.add(monitoringTab);
@@ -273,25 +270,19 @@ public class ResourceGroupDetailView extends
if (updateTab(this.monitoringTab, visible, true)) {
final EntityContext groupContext = EntityContext.forGroup(groupComposite.getResourceGroup());
visible = hasMetricsOfType(this.groupComposite, DataType.MEASUREMENT);
- viewFactory = (!visible) ? null : new ViewFactory() {
- @Override
- public Canvas createView() {
- String url = "/rhq/group/monitor/graphs-plain.xhtml?groupId=" + groupId;
-
- if (groupContext.isAutoGroup()) {
- url += "&parent=" + groupContext.parentResourceId + "&type=" + groupContext.resourceTypeId
- + "&groupType=auto";
- } else if (groupContext.isAutoCluster()) {
- url += "&groupType=cluster";
- }
- return new IFrameWithMeasurementRangeEditorView(url);
+ boolean showOnPage;
+
+ if(BrowserUtility.isBrowserPreIE9()){
+ showOnPage = false;
+ }else{
+ if(visible) {
+ showOnPage = true;
+ }else {
+ showOnPage = false;
}
- };
- updateSubTab(this.monitoringTab, this.monitorGraphs, visible, true, viewFactory);
-
- boolean visibleToIE8 = BrowserUtility.isBrowserPreIE9();
+ }
- viewFactory = (!visibleToIE8) ? null : new ViewFactory() {
+ viewFactory = (!showOnPage) ? null : new ViewFactory() {
@Override
public Canvas createView() {
return createD3GraphListView();
@@ -493,10 +484,8 @@ public class ResourceGroupDetailView extends
@Override
public void onSuccess(Subject result) {
- if (Log.isDebugEnabled()) {
- Log.debug("Updated recently viewed resource groups for " + result
+ Log.debug("Updated recently viewed resource groups for " + result
+ " with resourceGroupId [" + groupId + "]");
- }
}
});
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java
deleted file mode 100644
index 4fa0164..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring;
-
-import java.util.EnumSet;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.core.domain.criteria.ResourceGroupCriteria;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.group.ResourceGroup;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceGroupD3MetricGraphView
- */
-@Deprecated
-public class ResourceGroupMetricGraphView extends AbstractMetricGraphView {
-
- private HTMLFlow resourceGroupTitle;
-
- public ResourceGroupMetricGraphView() {
- super();
- }
-
- public ResourceGroupMetricGraphView(int groupId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- super(groupId, def, data);
- }
-
- @Override
- protected HTMLFlow getEntityTitle() {
- return resourceGroupTitle;
- }
-
- @Override
- protected void renderGraph() {
- if (null == getDefinition()) {
- ResourceGroupGWTServiceAsync groupService = GWTServiceLookup.getResourceGroupService();
-
- ResourceGroupCriteria criteria = new ResourceGroupCriteria();
- criteria.addFilterId(getEntityId());
- criteria.fetchResourceType(true);
- groupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_lookupFailed(), caught);
- }
-
- @Override
- public void onSuccess(PageList<ResourceGroup> result) {
- if (result.isEmpty()) {
- return;
- }
-
- final ResourceGroup group = result.get(0);
- String url = LinkManager.getResourceGroupLink(group);
- resourceGroupTitle = new HTMLFlow(LinkManager.getHref(url, group.getName()));
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(group.getResourceType().getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(final ResourceType type) {
-
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getId() == getDefinitionId()) {
- setDefinition(def);
-
- GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroupForLast(
- getEntityId(), new int[] { getDefinitionId() }, 8,
- MeasurementUtility.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(
- List<List<MeasurementDataNumericHighLowComposite>> result) {
- setData(result.get(0));
-
- drawGraph();
- }
- });
- }
- }
- }
- });
- }
- });
-
- } else {
-
- drawGraph();
- }
- }
-
- @Override
- public AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- return new ResourceGroupMetricGraphView(entityId, def, data);
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
index 824e201..46e51c0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
@@ -40,7 +40,6 @@ public final class CompositeGroupMultiLineGraphListView extends CompositeGroupD3
var chartId = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getChartId()(),
chartHandle = "#mChart-"+chartId,
chartSelection = chartHandle + " svg",
- // yAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getYAxisTitle()(),
yAxisUnits = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getYAxisUnits()(),
xAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getXAxisTitle()(),
displayDayOfWeek = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::shouldDisplayDayOfWeekInXAxisLabel()(),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index 0b67c63..a68170a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -102,8 +102,6 @@ public class ResourceDetailView extends
}
public static class DriftSubTab {
- //public static final String HISTORY = "History";
- //public static final String SNAPSHOTS = "Snapshots";
public static final String DEFINITIONS = "Definitions";
}
@@ -130,7 +128,6 @@ public class ResourceDetailView extends
private SubTab summaryActivity;
private SubTab summaryTimeline;
- private SubTab monitorGraphs;
private SubTab monitorNewGraphs;
private SubTab monitorTables;
private SubTab monitorTraits;
@@ -150,7 +147,6 @@ public class ResourceDetailView extends
private SubTab configCurrent;
private SubTab configHistory;
private SubTab eventHistory;
- //private SubTab driftHistory;
private SubTab driftDefinitions;
private SubTab contentDeployed;
private SubTab contentNew;
@@ -198,9 +194,8 @@ public class ResourceDetailView extends
monitoringTab = new TwoLevelTab(new ViewName("Monitoring", MSG.view_tabs_common_monitoring()),
IconEnum.SUSPECT_METRICS);
- monitorGraphs = new SubTab(monitoringTab, new ViewName("Graphs", MSG.view_tabs_common_graphs()), null);
- monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", "d3 Graphs"), null);
+ monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
@@ -208,7 +203,7 @@ public class ResourceDetailView extends
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorTables, monitorGraphs, monitorNewGraphs, monitorTraits, monitorAvail,
+ monitoringTab.registerSubTabs(monitorTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
@@ -393,16 +388,7 @@ public class ResourceDetailView extends
private void updateMonitoringTabContent(final Resource resource, Set<ResourceTypeFacet> facets) {
boolean visible = hasMetricsOfType(this.resourceComposite, DataType.MEASUREMENT);
-
- ViewFactory viewFactory = (!visible) ? null : new ViewFactory() {
- @Override
- public Canvas createView() {
- return new IFrameWithMeasurementRangeEditorView("/rhq/resource/monitor/graphs-plain.xhtml?id="
- + resource.getId());
- }
-
- };
- updateSubTab(this.monitoringTab, this.monitorGraphs, visible, true, viewFactory);
+ ViewFactory viewFactory;
boolean visibleToIE8 = !BrowserUtility.isBrowserPreIE9();
@@ -520,15 +506,6 @@ public class ResourceDetailView extends
private void updateDriftTabContent(final ResourceComposite resourceComposite, Set<ResourceTypeFacet> facets) {
if (updateTab(this.driftTab, facets.contains(ResourceTypeFacet.DRIFT), true)) {
- // TODO: Experimenting with not shoing a drift history tab and having all resource level drift viewing
- // go through the comprehensive drift carousel view. Leave it in, but commented, in case we want it back.
- //updateSubTab(this.driftTab, this.driftHistory, true, true, new ViewFactory() {
- // @Override
- // public Canvas createView() {
- // return ResourceDriftHistoryView.get(resourceComposite);
- // }
- //});
-
updateSubTab(this.driftTab, this.driftDefinitions, true, true, new ViewFactory() {
@Override
public Canvas createView() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index fa5d904..72a46a8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -87,7 +87,6 @@ import org.rhq.enterprise.gui.coregui.client.ViewId;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.components.tree.EnhancedTreeNode;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
@@ -797,46 +796,7 @@ public class ResourceTreeView extends EnhancedVLayout {
}
});
- //@todo: Remove once we have verified the charts
- // now add the old menu items
- MenuItem addOldItemToDBItem = new MenuItem(MSG
- .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
- defSubItem.addItem(addOldItemToDBItem);
- addOldItemToDBItem.addClickHandler(new ClickHandler() {
-
- public void onClick(MenuItemClickEvent menuItemClickEvent) {
- DashboardPortlet p = new DashboardPortlet(MSG
- .view_tree_common_contextMenu_resourceGraph(), ResourceGraphPortlet.KEY,
- 250);
- p.getConfiguration().put(
- new PropertySimple(ResourceGraphPortlet.CFG_RESOURCE_ID, resource.getId()));
- p.getConfiguration().put(
- new PropertySimple(ResourceGraphPortlet.CFG_DEFINITION_ID, def.getId()));
-
- d.addPortlet(p);
-
- GWTServiceLookup.getDashboardService().storeDashboard(d,
- new AsyncCallback<Dashboard>() {
-
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
- caught);
- }
-
- public void onSuccess(Dashboard result) {
- CoreGUI
- .getMessageCenter()
- .notify(
- new Message(
- MSG.view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
- .getName()), Message.Severity.Info));
- }
- });
-
- }
- });
}//end dashboard iteration
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java
deleted file mode 100644
index 9e93072..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.Label;
-
-import org.rhq.core.domain.measurement.DataType;
-import org.rhq.core.domain.measurement.DisplayType;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.composite.ResourceComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityBarView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
-
-/**
- * @author Greg Hinkle
- */
-@Deprecated
-public class GraphListView extends EnhancedVLayout implements ResourceSelectListener {
-
- private Resource resource;
- private Label loadingLabel = new Label(MSG.common_msg_loading());
-
- public GraphListView(Resource resource) {
- super();
-
- this.resource = resource;
- setOverflow(Overflow.AUTO);
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
-
- destroyMembers();
-
- addMember(new AvailabilityBarView(resource));
-
- // addMember(loadingLabel);
-
- addMember(new UserPreferencesMeasurementRangeEditor());
-
- if (resource != null) {
- buildGraphs();
- }
- }
-
- private void buildGraphs() {
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(final ResourceType type) {
-
- final ArrayList<MeasurementDefinition> measurementDefinitions = new ArrayList<MeasurementDefinition>();
-
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getDataType() == DataType.MEASUREMENT && def.getDisplayType() == DisplayType.SUMMARY) {
- measurementDefinitions.add(def);
- }
- }
-
- Collections.sort(measurementDefinitions, new Comparator<MeasurementDefinition>() {
- public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
- return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
- }
- });
-
- int[] measDefIdArray = new int[measurementDefinitions.size()];
- for (int i = 0; i < measDefIdArray.length; i++) {
- measDefIdArray[i] = measurementDefinitions.get(i).getId();
- }
-
- GWTServiceLookup.getMeasurementDataService().findDataForResourceForLast(resource.getId(),
- measDefIdArray, 8, MeasurementUtils.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_loadFailed(),
- caught);
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_loadFailed());
- }
-
- public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> result) {
- if (result.isEmpty()) {
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
- } else {
- loadingLabel.hide();
- int i = 0;
- for (List<MeasurementDataNumericHighLowComposite> data : result) {
- buildGraph(measurementDefinitions.get(i++), data);
- }
- }
- }
- });
-
- }
- });
- }
-
- private void buildGraph(MeasurementDefinition def, List<MeasurementDataNumericHighLowComposite> data) {
- ResourceMetricGraphView graph = new ResourceMetricGraphView(resource.getId(), def, data);
- graph.setWidth("95%");
- graph.setHeight(220);
-
- addMember(graph);
- }
-
- public void onResourceSelected(ResourceComposite resourceComposite) {
- this.resource = resourceComposite.getResource();
-
- buildGraphs();
- markForRedraw();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
deleted file mode 100644
index f71e307..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Set;
-
-import ca.nanometrics.gflot.client.Axis;
-import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.PlotModelStrategy;
-import ca.nanometrics.gflot.client.SeriesHandler;
-import ca.nanometrics.gflot.client.SimplePlot;
-import ca.nanometrics.gflot.client.event.PlotHoverListener;
-import ca.nanometrics.gflot.client.event.PlotItem;
-import ca.nanometrics.gflot.client.event.PlotPosition;
-import ca.nanometrics.gflot.client.jsni.Plot;
-import ca.nanometrics.gflot.client.options.AxisOptions;
-import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
-import ca.nanometrics.gflot.client.options.GridOptions;
-import ca.nanometrics.gflot.client.options.LineSeriesOptions;
-import ca.nanometrics.gflot.client.options.PlotOptions;
-import ca.nanometrics.gflot.client.options.PointsSeriesOptions;
-import ca.nanometrics.gflot.client.options.TickFormatter;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.AnimationEffect;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.WidgetCanvas;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-
-import org.rhq.core.domain.measurement.MeasurementData;
-import org.rhq.core.domain.measurement.MeasurementDataNumeric;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.MeasurementDataGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * @author Greg Hinkle
- */
-@Deprecated
-public class LiveGraphView extends EnhancedVLayout {
-
- private static final String INSTRUCTIONS = MSG.view_resource_monitor_graph_instructions();
-
- private final Label selectedPointLabel = new Label(INSTRUCTIONS);
- private final Label positionLabel = new Label();
-
- private final Label hoverLabel = new Label();
-
- private int resourceId;
- private MeasurementDefinition definition;
-
- private SimplePlot plot;
- private Timer dataLoader;
- @SuppressWarnings("unused")
- private long min, max;
-
- public LiveGraphView() {
- super();
- }
-
- public LiveGraphView(int resourceId, MeasurementDefinition def) {
- super();
- this.resourceId = resourceId;
- this.definition = def;
- setHeight100();
- setWidth100();
- }
-
- public String getName() {
- return "PlotHoverListener";
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
-
- for (Canvas c : getChildren()) {
- c.destroy();
- }
-
- drawGraph();
- }
-
- @Override
- protected void onDetach() {
- super.onDetach(); // TODO: Implement this method.
- }
-
- @Override
- protected void onUnload() {
- super.onUnload(); // TODO: Implement this method.
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- onDraw();
- }
-
- private void drawGraph() {
-
- PlotModel model = new PlotModel();
- PlotOptions plotOptions = new PlotOptions();
- GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
- globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- globalSeriesOptions.setShadowSize(0);
- plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
-
- // You need make the grid hoverable <<<<<<<<<
- plotOptions
- .setGridOptions(new GridOptions().setHoverable(true).setMouseActiveRadius(10).setAutoHighlight(true));
-
- // create a series
- loadData(model, plotOptions);
-
- // create the plot
- plot = new SimplePlot(model, plotOptions);
- plot.setSize(String.valueOf(getInnerContentWidth()), String.valueOf(getInnerContentHeight() - 20));
-
- // add hover listener
- plot.addHoverListener(new PlotHoverListener() {
- public void onPlotHover(Plot plot, PlotPosition position, PlotItem item) {
- if (position != null) {
- positionLabel.setContents("position: (" + position.getX() + "," + position.getY() + ")");
- }
- if (item != null) {
- hoverLabel.setContents(getHover(item));
-
- hoverLabel.animateShow(AnimationEffect.FADE);
- if (hoverLabel.getLeft() > 0 || hoverLabel.getTop() > 0) {
- hoverLabel.animateMove(item.getPageX() + 5, item.getPageY() + 5);
- } else {
- hoverLabel.moveTo(item.getPageX() + 5, item.getPageY() + 5);
- }
- hoverLabel.redraw();
-
- selectedPointLabel.setContents("x: " + item.getDataPoint().getX() + ", y: "
- + item.getDataPoint().getY());
- } else {
- hoverLabel.animateHide(AnimationEffect.FADE);
- selectedPointLabel.setContents(INSTRUCTIONS);
- }
- }
- }, false);
-
- addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- hoverLabel.animateHide(AnimationEffect.FADE);
- }
- });
-
- hoverLabel.setOpacity(80);
- hoverLabel.setWrap(false);
- hoverLabel.setHeight(25);
- hoverLabel.setBackgroundColor("yellow");
- hoverLabel.setBorder("1px solid orange");
- hoverLabel.hide();
-
- hoverLabel.draw();
-
- // put it on a panel
-
- if (definition != null) {
-
- HTMLFlow title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
- title.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- // displayAsDialog();
- }
- });
-
- addMember(title);
- }
-
- addMember(new WidgetCanvas(plot));
- }
-
- private String getHover(PlotItem item) {
- if (definition != null) {
- DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return definition.getDisplayName() + ": "
- + MeasurementConverterClient.format(item.getDataPoint().getY(), definition.getUnits(), true) + "<br/>"
- + df.format(new Date((long) item.getDataPoint().getX()));
- } else {
- return "x: " + item.getDataPoint().getX() + ", y: " + item.getDataPoint().getY();
- }
- }
-
- private void loadData(final PlotModel model, final PlotOptions plotOptions) {
- final SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
-
- model.setStrategy(PlotModelStrategy.slidingWindowStrategy(60));
- final MeasurementDataGWTServiceAsync dataService = GWTServiceLookup.getMeasurementDataService();
-
- dataLoader = new Timer() {
- @Override
- public void run() {
- dataService.findLiveData(resourceId, new int[] { definition.getId() },
- new AsyncCallback<Set<MeasurementData>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler()
- .handleError(MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- public void onSuccess(Set<MeasurementData> result) {
- Iterator<MeasurementData> i = result.iterator();
- if (!i.hasNext()) {
- return;
- }
-
- MeasurementDataNumeric d = (MeasurementDataNumeric) i.next();
-
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
- plot.redraw();
- }
- });
- }
- };
-
- dataLoader.scheduleRepeating(1000);
-
- plotOptions.addYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
- .setTickFormatter(new TickFormatter() {
- public String formatTickValue(double v, Axis axis) {
- return MeasurementConverterClient.format(v, definition.getUnits(), true);
- }
- }));
-
- plotOptions.addXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
- public String formatTickValue(double tickValue, Axis axis) {
- DateTimeFormat dateFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return dateFormat.format(new Date((long) tickValue));
- }
- }));
-
- }
-
- public static void displayAsDialog(int resourceId, MeasurementDefinition def) {
- final LiveGraphView graph = new LiveGraphView(resourceId, def);
- final Window graphPopup = new Window();
- graphPopup.setTitle(MSG.view_resource_monitor_detailed_graph_label());
- graphPopup.setWidth(800);
- graphPopup.setHeight(400);
- graphPopup.setIsModal(true);
- graphPopup.setShowModalMask(true);
- graphPopup.setCanDragResize(true);
- graphPopup.centerInPage();
- graphPopup.addItem(graph);
- graphPopup.show();
-
- graphPopup.addCloseClickHandler(new CloseClickHandler() {
- public void onCloseClick(CloseClickEvent closeClientEvent) {
- graph.stop();
- graphPopup.destroy();
- }
- });
- }
-
- protected void stop() {
- hoverLabel.destroy();
- dataLoader.cancel();
- }
-
- @Override
- protected void onDestroy() {
- stop();
- super.onDestroy();
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java
deleted file mode 100644
index 6db0d56..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
-
-/**
- * @deprecated should be replaced with new d3 graph views
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- */
-@Deprecated
-public class ResourceMetricGraphView extends AbstractMetricGraphView {
-
- private HTMLFlow resourceTitle;
-
- public ResourceMetricGraphView() {
- super();
- }
-
- public ResourceMetricGraphView(int resourceId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- super(resourceId, def, data);
- }
-
- @Override
- protected HTMLFlow getEntityTitle() {
- return resourceTitle;
- }
-
- @Override
- protected void renderGraph() {
- if (null == getDefinition()) {
-
- ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
-
- ResourceCriteria resourceCriteria = new ResourceCriteria();
- resourceCriteria.addFilterId(getEntityId());
- resourceService.findResourcesByCriteria(resourceCriteria, new AsyncCallback<PageList<Resource>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_lookupFailed(), caught);
- }
-
- @Override
- public void onSuccess(PageList<Resource> result) {
- if (result.isEmpty()) {
- return;
- }
-
- final Resource resource = result.get(0);
- HashSet<Integer> typesSet = new HashSet<Integer>();
- typesSet.add(resource.getResourceType().getId());
- HashSet<String> ancestries = new HashSet<String>();
- ancestries.add(resource.getAncestry());
- // In addition to the types of the result resources, get the types of their ancestry
- typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(
- typesSet.toArray(new Integer[typesSet.size()]),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypesLoadedCallback() {
-
- public void onTypesLoaded(Map<Integer, ResourceType> types) {
- String url = LinkManager.getResourceLink(resource.getId());
- resourceTitle = new HTMLFlow(LinkManager.getHref(url, resource.getName()));
- resourceTitle.setTooltip(AncestryUtil.getAncestryHoverHTMLForResource(resource, types,
- 0));
-
- ResourceType type = types.get(resource.getResourceType().getId());
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getId() == getDefinitionId()) {
- setDefinition(def);
-
- GWTServiceLookup.getMeasurementDataService().findDataForResourceForLast(
- getEntityId(), new int[] { getDefinitionId() }, 8,
- MeasurementUtils.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(
- List<List<MeasurementDataNumericHighLowComposite>> result) {
- setData(result.get(0));
-
- drawGraph();
- }
- });
- }
- }
- }
- });
- }
- });
-
- } else {
- drawGraph();
- }
- }
-
- @Override
- protected boolean supportsLiveGraphViewDialog() {
- return true;
- }
-
- @Override
- protected void displayLiveGraphViewDialog() {
- LiveGraphView.displayAsDialog(getEntityId(), getDefinition());
- }
-
- @Override
- public AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- return new ResourceMetricGraphView(entityId, def, data);
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java
deleted file mode 100644
index 5d40b1b..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-import com.smartgwt.client.widgets.events.MouseOverEvent;
-import com.smartgwt.client.widgets.events.MouseOverHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-
-import org.rhq.core.domain.criteria.AvailabilityCriteria;
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.core.domain.util.PageOrdering;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.ImageManager;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * This is a potential replacement to the JSF "Christmas Tree". Unused at the moment but something to
- * consider when we replace JSF completely.
- *
- * @author Greg Hinkle
- */
-@Deprecated
-public class AvailabilityBarView extends HLayout {
-
- Messages MSG = CoreGUI.getMessages();
-
- private Resource resource;
-
- public AvailabilityBarView(Resource resource) {
- this.resource = resource;
- setHeight(28);
- setWidth100();
- setMargin(10);
- }
-
- @Override
- protected void onInit() {
- super.onInit();
-
- AvailabilityCriteria c = new AvailabilityCriteria();
- c.addFilterResourceId(resource.getId());
- c.addSortStartTime(PageOrdering.ASC);
- GWTServiceLookup.getAvailabilityService().findAvailabilityByCriteria(c,
- new AsyncCallback<PageList<Availability>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_availability_loadFailed(), caught);
- }
-
- public void onSuccess(PageList<Availability> result) {
- update(result);
- }
- });
- }
-
- private void update(PageList<Availability> result) {
-
- long start = result.get(0).getStartTime();
- long end = result.get(result.size() - 1).getEndTime() != null ? result.get(result.size() - 1).getEndTime()
- : System.currentTimeMillis();
-
- long diff = end - start;
-
- Img leftCap = new Img("availBar/leftCap.png", 8, 28);
- addMember(leftCap);
-
- for (Availability a : result) {
-
- long endTime = a.getEndTime() != null ? a.getEndTime() : System.currentTimeMillis();
-
- double width = (((double) (endTime - a.getStartTime()) / diff) * 100);
- String widthString = width + "%";
- if (width == 0) {
- widthString = "2px";
- }
-
- String imagePath = ImageManager.getAvailBarImagePath(a.getAvailabilityType());
-
- final Img section = new Img(imagePath);
- section.setHeight(28);
- section.setOpacity(60);
- section.setWidth(widthString);
-
- section.addMouseOverHandler(new MouseOverHandler() {
- public void onMouseOver(MouseOverEvent mouseOverEvent) {
- section.animateFade(100);
- }
- });
- section.addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- section.animateFade(60);
- }
- });
-
- long duration = endTime - a.getStartTime();
-
- String durationString = MeasurementConverterClient.format((double) duration, MeasurementUnits.MILLISECONDS,
- true);
-
- section.setTooltip("<div style=\"white-space: nowrap;\"><b>" + MSG.common_title_availability() + ": </b>"
- + a.getAvailabilityType().name() + "<br/><b>" + MSG.common_title_start() + ": </b>" + a.getStartTime()
- + "<br/><b>" + MSG.common_title_end() + ": </b>" + a.getEndTime() + "<br/><b>"
- + MSG.common_title_duration() + ": </b>" + durationString);
-
- addMember(section);
-
- }
- Img rightCap = new Img("availBar/rightCap.png", 8, 28);
- addMember(rightCap);
-
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index 3a39c2e..c6ad891 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -146,55 +146,8 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
}
});
- //@todo: delete once satisfied with d3 chart verification
- //add chart selected metric action
- addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- if (selection == null || selection.length == 0) {
- return;
- }
- // keyed on metric name - string[0] is the metric label, [1] is the units
- final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
- int[] definitionIds = new int[selection.length];
- int i = 0;
- for (ListGridRecord record : selection) {
- Integer defId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds[i++] = defId.intValue();
- String name = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_NAME);
- String label = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_LABEL);
- String units = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_UNITS);
- if (units == null || units.length() < 1) {
- units = MeasurementUnits.NONE.name();
- }
-
- scheduleNamesAndUnits.put(name, new String[] { label, units });
- }
-
- //build portal.war chart page to iFrame
- String destination = "/resource/common/monitor/Visibility.do?mode=chartMultiMetricSingleResource&id="
- + resourceId;
- for (int mId : definitionIds) {
- destination += "&m=" + mId;
- }
- ChartViewWindow window = new ChartViewWindow("");
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- window.addItem(iframe);
- window.show();
- refreshTableInfo();
- }
- });
-
- // new d3 chart selection
- //@todo: i18n when we remove gflot graphs
- addTableAction("d3 Chart Selection", new TableAction() {
+ addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
return selection != null && selection.length > 0;
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 0cd10cb..3d5ae84 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -11,11 +11,6 @@
<inherits name='com.smartgwt.SmartGwt' />
<inherits name="com.smartgwt.tools.SmartGwtTools"/>
-
- <!-- @todo: take out GFlot once we have d3 graphing in place -->
- <inherits name='ca.nanometrics.gflot.GFlot'/>
- <set-property name="gflot.load.jquery" value="EXTERNAL" />
-
<!-- ============================ gwt logging ============================= -->
<set-property name="gwt.logging.enabled" value="TRUE"/>
<!-- FINE ~= DEBUG in gwt-log -->
commit ca17805e57e131a9b1972987827d54a63d5b8fb0
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 17:04:34 2013 -0400
BZ 951121 - tell the user the server is still starting if they attempt to login during startup
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
index 46ea7f2..d896e63 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
@@ -67,11 +67,10 @@ import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.BrowserUtility;
import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/**
* @author Greg Hinkle
@@ -572,6 +571,8 @@ public class LoginView extends Canvas {
private void handleError(int statusCode) {
if (statusCode == 401) {
form.setFieldErrors("login", MSG.view_login_noUser(), true);
+ } else if (statusCode == 503) {
+ form.setFieldErrors("login", MSG.view_core_serverInitializing(), true);
} else {
form.setFieldErrors("login", MSG.view_login_noBackend(), true);
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
index f803b24..6995e4f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
@@ -154,6 +154,12 @@ public class UserSessionManager {
Log.info("response text = " + response.getText());
String sessionIdString = response.getText();
+ if (sessionIdString.startsWith("booting")) {
+ // "booting" is the string we get back from SessionAccessServlet if StartupBean hasn't finished
+ new LoginView().showLoginDialog(MSG.view_core_serverInitializing());
+ return;
+ }
+
// If a session is active it will return valid session strings
if (sessionIdString != null && sessionIdString.length() > 0) {
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 0b75e4f..0c5af20 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1357,6 +1357,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = The following connection
view_core_loggedOut = Logged out
view_core_noRecentAlerts = There are no recent alerts to report
view_core_recentAlerts = There are [{0}] recent alerts - click to go to the recent alerts report
+view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = Globally uncaught exception
view_dashboardManager_deleteFail = Failed to delete dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index bd735d0..42405aa 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1372,6 +1372,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = Následující položky m
view_core_loggedOut = Odhlášeno
view_core_noRecentAlerts = Nejsou žádné nedávné výstrahy k hlášení
view_core_recentAlerts = Je [{0}] nedávných výstrah - klikněte pro přechod na hlášení
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = Server je nedosažitelný, možná spadl
view_core_uncaught = Globálné nezachycená výjimka
view_dashboardManager_deleteFail = Nepodařilo se smazat dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 0ad2504..8185e7f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1226,6 +1226,7 @@ view_configurationHistoryList_title = Konfigurationsänderungen
view_core_loggedOut = Ausgeloggt
view_core_noRecentAlerts = Es liegen keine frischen Alarme vor
view_core_recentAlerts = [{0}] frische Alarme
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = Kann den Server nicht erreichen. Er abgeschaltet sein.
view_core_uncaught = Es ist eine nicht abgefangene Ausnahme aufgetreten.
view_dashboardManager_deleteFail = Konnte das Dashboard nicht löschen.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index ef42475..c15e129 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1352,6 +1352,7 @@ view_core_loggedInAs = {0} としてログイン
view_core_loggedOut = ログアウト
view_core_noRecentAlerts = レポートすべき最近のアラートは存在しません
view_core_recentAlerts = [{0}] 個の最近のアラートがありました - 最近のアラートレポートへクリックしてください
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = サーバーに到達できません。ダウンしている可能性があります。
view_core_uncaught = グローバルにキャッチされない例外
view_dashboardManager_deleteFail = ダッシュボードの削除に失敗しました
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 1d3530e..8105460 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -1163,6 +1163,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = 다음 연결 설정은
view_core_loggedOut = 로그 아웃
view_core_noRecentAlerts = 리포트에서 최근 알림이 없습니다
view_core_recentAlerts = [{0}] 최근 경고가 있습니다 - 최근 경고 리포트를 클릭하십시오
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = 서버에 접근할 수 없거나 다운되었을 수 있습니다
view_core_uncaught = 글로벌 캐치되지 않은 예외
view_dashboardManager_deleteFail = 대시 보드의 제거에 실패했습니다.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index b7cab71..d50a54e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1363,6 +1363,7 @@ view_core_loggedInAs = Logado como {0}
view_core_loggedOut = Desconectado
view_core_noRecentAlerts = N�o existem alertas recentes
view_core_recentAlerts = [{0}] alertas recentes
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = Exce\u00E7\u00E3o n\u00E3o capturada
view_dashboardManager_deleteFail = Falha ao excluir o dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 56cf3e6..fb45e35 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2675,6 +2675,7 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль
##view_configEdit_property = Vlastnost
##view_configEdit_unset = Unset?
##view_configEdit_value = Value
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_dashboardsManager_message_title_details = <h1>Welcome to {0}</h1>\n<p>This dashboard can be edited by clicking the (Edit Mode) button above.</p>\n<p>What would you like to do?</p>\n<p> <a href=\"{1}\">Import newly discovered resources.</a></p>\n<p> <a href=\"{2}\">Search for resources.</a></p>\n<p> <a href=\"{3}\">See help and documentation.</a></p>
##view_dynagroup_exprBuilder_groupBy = Group by
##view_dynagroup_exprBuilder_groupBy_tooltip = groupby will cause the system to pivot on the values from the entered expressions creating a separate group for each value. For example, groupby on the cluster name to create a group for each cluster with all cluster members in it.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 5e6afec..e929386 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1345,6 +1345,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = \u4e0b\u9762\u7684\u8fde\
view_core_loggedOut = \u9000\u51fa\u767b\u5f55
view_core_noRecentAlerts = \u6ca1\u6709\u65b0\u4ea7\u751f\u7684\u544a\u8b66\u4fe1\u606f
view_core_recentAlerts = \u65b0\u4ea7\u751f [{0}] \u6761\u544a\u8b66 - \u70b9\u51fb\u8df3\u8f6c\u5230\u65b0\u544a\u8b66\u62a5\u8868\u754c\u9762
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = \u5168\u5c40\u672a\u6355\u6349\u7684\u5f02\u5e38
view_dashboardManager_deleteFail = \u5220\u9664\u7edf\u8ba1\u8868\u76d8\u5931\u8d25.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
index caf4ab5..f7cca42 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
@@ -38,6 +38,7 @@ import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SessionNotFoundException;
import org.rhq.enterprise.server.auth.SessionTimeoutException;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* @author Greg Hinkle
@@ -59,6 +60,20 @@ public class SessionAccessServlet extends HttpServlet {
// some date in the past
response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
+ // do not go any further unless we know the server has been fully initialized
+ boolean serverInitialized;
+ try {
+ serverInitialized = LookupUtil.getStartupLocal().isInitialized();
+ } catch (Throwable t) {
+ serverInitialized = false; // this probably means we are still starting up and app server hasn't made EJBs available yet
+ }
+
+ if (!serverInitialized) {
+ response.setHeader("Retry-After", "30");
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Server is not ready - still booting up");
+ return;
+ }
+
//if a session does not already exist this call will create one
HttpSession session = request.getSession();
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
index 8743a33..c80e517 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
@@ -38,6 +38,7 @@ import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SessionNotFoundException;
import org.rhq.enterprise.server.auth.SessionTimeoutException;
+import org.rhq.enterprise.server.util.LookupUtil;
public final class AuthenticationFilter extends BaseFilter {
@@ -49,6 +50,20 @@ public final class AuthenticationFilter extends BaseFilter {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
+ // do not go any further unless we know the server has been fully initialized
+ boolean serverInitialized;
+ try {
+ serverInitialized = LookupUtil.getStartupLocal().isInitialized();
+ } catch (Throwable t) {
+ serverInitialized = false; // this probably means we are still starting up and app server hasn't made EJBs available yet
+ }
+
+ if (!serverInitialized) {
+ response.setHeader("Retry-After", "30");
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Server is not ready - still booting up");
+ return;
+ }
+
//if a session does not already exist this call will create one
HttpSession session = request.getSession();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index de4f6fe..5b5aa8c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -100,7 +100,7 @@ import org.rhq.enterprise.server.util.concurrent.AvailabilityReportSerializer;
*/
@Singleton
//@Startup // when AS7-5530 is fixed, uncomment this and remove class StartupBeanToWorkaroundAS7_5530
-public class StartupBean {
+public class StartupBean implements StartupLocal {
private Log log = LogFactory.getLog(this.getClass());
private boolean initialized = false;
@@ -138,6 +138,12 @@ public class StartupBean {
@Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
private DataSource dataSource;
+ @Override
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public boolean isInitialized() {
+ return this.initialized;
+ }
+
/**
* Modifies the naming subsystem to be able to check for Java security permissions on JNDI lookup.
* <p>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
index 88790d5..c66d328 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
@@ -43,7 +43,7 @@ public class StartupBeanPreparation {
private Log log = LogFactory.getLog(this.getClass());
@EJB
- private StartupBean startupBean;
+ private StartupLocal startupBean;
@Resource
private TimerService timerService; // needed to schedule our startup bean init call
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java
new file mode 100644
index 0000000..bc98bbf
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.core;
+
+import javax.ejb.Local;
+
+@Local
+public interface StartupLocal {
+ /**
+ * When false is returned, it means the startup bean has not finished initializing the server.
+ * Only when true is returned can we be assured that the server has been fully started and initialized, ready to accept
+ * agent requests and user requests from browser/remote clients.
+ *
+ * @return true if the startup bean has fully initialized the server
+ */
+ boolean isInitialized();
+
+ /**
+ * Tells the startup bean to do its work. This will finish the initialization of the server.
+ */
+ void init();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 112a590..698ec85 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -103,6 +103,8 @@ import org.rhq.enterprise.server.core.EmailManagerBean;
import org.rhq.enterprise.server.core.EmailManagerLocal;
import org.rhq.enterprise.server.core.RemoteClientManagerBean;
import org.rhq.enterprise.server.core.RemoteClientManagerLocal;
+import org.rhq.enterprise.server.core.StartupBean;
+import org.rhq.enterprise.server.core.StartupLocal;
import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.dashboard.DashboardManagerBean;
import org.rhq.enterprise.server.dashboard.DashboardManagerLocal;
@@ -589,6 +591,10 @@ public final class LookupUtil {
return lookupLocal(SubjectPreferencesCacheBean.class);
}
+ public static StartupLocal getStartupLocal() {
+ return lookupLocal(StartupBean.class);
+ }
+
public static CoreServerMBean getCoreServer() {
MBeanServer mbs = getJBossMBeanServer();
CoreServerMBean rhqServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class,
commit 58e3a41e18d47c955129d97c68a4149bea01a983
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 13:14:10 2013 -0400
BZ 951382 - in agent-configuration.xml, use "conf" instead to make it clear the user should probably put their certs in the conf/ directory.
diff --git a/modules/enterprise/agent/src/main/resources/agent-configuration.xml b/modules/enterprise/agent/src/main/resources/agent-configuration.xml
index 61339fe..d59fe71 100644
--- a/modules/enterprise/agent/src/main/resources/agent-configuration.xml
+++ b/modules/enterprise/agent/src/main/resources/agent-configuration.xml
@@ -1014,36 +1014,35 @@ commands named "config", "setconfig" and "setup" and the command line options
rhq.agent.client.security.server-auth-mode-enabled
These are the settings that are used if SSL is to be used for
- either the server or client communications. These can be left
- unset since the defaults will normally suffice. These
- properties are here just in case some use case occurs that
- require one or more of these settings to be customized.
+ either the server-side or client-side communications (that is,
+ for incoming messages into the agent and for outgoing messages
+ getting sent by the agent).
Note that if client-auth-mode is specified, it must be one of:
"none", "want", "need".
-->
<!--
<entry key="rhq.communications.connector.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.communications.connector.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.communications.connector.security.keystore.file" value="conf/keystore.dat" />
<entry key="rhq.communications.connector.security.keystore.algorithm" value="SunX509" />
<entry key="rhq.communications.connector.security.keystore.type" value="JKS" />
<entry key="rhq.communications.connector.security.keystore.password" value="rhqpwd" />
<entry key="rhq.communications.connector.security.keystore.key-password" value="rhqpwd" />
<entry key="rhq.communications.connector.security.keystore.alias" value="rhq" />
- <entry key="rhq.communications.connector.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.communications.connector.security.truststore.file" value="conf/truststore.dat" />
<entry key="rhq.communications.connector.security.truststore.algorithm" value="SunX509" />
<entry key="rhq.communications.connector.security.truststore.type" value="JKS" />
<entry key="rhq.communications.connector.security.truststore.password" value="" />
<entry key="rhq.communications.connector.security.client-auth-mode" value="none" />
<entry key="rhq.agent.client.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.agent.client.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.agent.client.security.keystore.file" value="conf/keystore.dat" />
<entry key="rhq.agent.client.security.keystore.algorithm" value="SunX509" />
<entry key="rhq.agent.client.security.keystore.type" value="JKS" />
<entry key="rhq.agent.client.security.keystore.password" value="rhqpwd" />
<entry key="rhq.agent.client.security.keystore.key-password" value="rhqpwd" />
<entry key="rhq.agent.client.security.keystore.alias" value="rhq" />
- <entry key="rhq.agent.client.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.agent.client.security.truststore.file" value="conf/truststore.dat" />
<entry key="rhq.agent.client.security.truststore.algorithm" value="SunX509" />
<entry key="rhq.agent.client.security.truststore.type" value="JKS" />
<entry key="rhq.agent.client.security.truststore.password" value="" />
commit 00be4f6ba09fd8f6a1cf55a99a4fd1f6f25130d6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue Apr 16 22:04:50 2013 +0200
Bug 593932 - (PRODMGT-355) Allow Trap OID for SNMP notification to be overridden per-alert definition
Snmp trap OID is set on v2c and v3 traps as the second variable binding.
In the past, users had been confused by the name of the SNMP notification parameter 'oid'. This parameter actually defines a variable binding prefix for the RHQ alert bindings.
Added tests for this server plugin
Added documentation to the plugin descriptor
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 909053a..b09ed2a 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -13,12 +13,32 @@
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
+ <properties>
+ <alert.snmp.test.port>35162</alert.snmp.test.port>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>1.8.2</version>
</dependency>
+
+ <!-- Test dependencies -->
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ <version>1.9.5</version>
+ </dependency>
+
</dependencies>
<build>
@@ -27,10 +47,14 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!--
- <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.rhq.test.testng.StdoutReporter</value>
+ </property>
+ </properties>
+ <useSystemClassLoader>false</useSystemClassLoader>
+ <argLine>${jacoco.unit-test.args}</argLine>
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
index 082e706..c92daae 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
@@ -1,19 +1,55 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
package org.rhq.enterprise.server.plugins.alertSnmp;
import org.rhq.core.domain.configuration.Configuration;
+/**
+ * Utility class giving a view of SNMP alert notification parameters.
+ *
+ * @deprecated as of 4.7. It's an internal utility class and should not have been made public.
+ */
+@Deprecated
public class SnmpInfo {
+ // SNMP Alert Notification parameter names
+ static final String PARAM_HOST = "host";
+ static final String PARAM_PORT = "port";
+ static final String PARAM_VARIABLE_BINDING_PREFIX = "oid";
+ static final String PARAM_TRAP_OID = "trapOid";
+
+ // Default remote port for SNMP trap
+ static final String DEFAULT_PORT = "162";
+
final public String host;
final public String port;
final public String oid;
+ final public String trapOid;
final public String error;
- private SnmpInfo(String host, String port, String oid) {
+ private SnmpInfo(String host, String port, String oid, String trapOid) {
this.host = host;
this.port = port;
this.oid = oid;
+ this.trapOid = trapOid;
String error = null;
if (oid == null) {
@@ -29,17 +65,26 @@ public class SnmpInfo {
this.error = error;
}
+ /**
+ * Creates an instance of {@link SnmpInfo} from alert definition parameters.
+ *
+ * @param configuration SNMP notification parameters in a {@link Configuration} object
+ * @return instance of {@link SnmpInfo}
+ */
public static SnmpInfo load(Configuration configuration) {
- String host = configuration.getSimpleValue("host", null); // required
- String port = configuration.getSimpleValue("port", "162");
- String oid = configuration.getSimpleValue("oid", null); // required
-
- return new SnmpInfo(host, port, oid);
+ String host = configuration.getSimpleValue(PARAM_HOST, null); // required
+ String port = configuration.getSimpleValue(PARAM_PORT, DEFAULT_PORT);
+ String oid = configuration.getSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, null); // required
+ String trapOid = configuration.getSimpleValue(PARAM_TRAP_OID, null);
+ return new SnmpInfo(host, port, oid, trapOid);
}
+ @Override
public String toString() {
String hostString = (host == null ? "UnknownHost" : host);
String oidString = (oid == null ? "UnknownOID" : oid);
- return hostString + ":" + port + " (" + oidString + ")";
+ String trapOidString = (trapOid == null ? "DefaultTrapOID" : trapOid);
+ return hostString + ":" + port + " (" + oidString + ") (" + trapOidString + ")";
}
+
}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
index 1ea5e0b..5c6d1e7 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.plugins.alertSnmp;
@@ -38,7 +38,23 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
public class SnmpSender extends AlertSender {
- private final Log log = LogFactory.getLog(SnmpSender.class);
+ private static final Log LOG = LogFactory.getLog(SnmpSender.class);
+
+ private ResourceManagerLocal resourceManager;
+
+ private AlertManagerLocal alertManager;
+
+ /**
+ * Default constructor needed for instanciation by server plugin container
+ */
+ public SnmpSender() {
+ this(LookupUtil.getResourceManager(), LookupUtil.getAlertManager());
+ }
+
+ public SnmpSender(ResourceManagerLocal resourceManager, AlertManagerLocal alertManager) {
+ this.resourceManager = resourceManager;
+ this.alertManager = alertManager;
+ }
@Override
public SenderResult send(Alert alert) {
@@ -47,12 +63,11 @@ public class SnmpSender extends AlertSender {
if (info.error != null) {
return SenderResult.getSimpleFailure(info.error);
}
- log.debug("Sending SNMP trap to: " + info);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Sending SNMP trap to: " + info);
+ }
try {
- AlertManagerLocal alertManager = LookupUtil.getAlertManager();
- ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
-
SnmpTrapSender snmpTrapSender = new SnmpTrapSender(preferences);
List<Resource> lineage = resourceManager.getResourceLineage(alert.getAlertDefinition().getResource()
@@ -69,6 +84,7 @@ public class SnmpSender extends AlertSender {
alertUrl, hierarchy);
return SenderResult.getSimpleSuccess(result);
} catch (Throwable t) {
+ LOG.error("Could not send SNMP trap to " + info, t);
return SenderResult.getSimpleFailure("failed - cause: " + t);
}
}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
index 92fc838..2556b38 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.plugins.alertSnmp;
@@ -72,6 +72,7 @@ import org.snmp4j.util.PDUFactory;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.util.StringUtil;
/**
* @author Ian Springer
@@ -135,12 +136,13 @@ public class SnmpTrapSender implements PDUFactory {
}
private void checkTrapVariables(List<VariableBinding> vbs) {
-
+ // Only on SNMP v2c or v3 trap
if ((pduType == PDU.INFORM) || (pduType == PDU.TRAP)) {
+ // Insert sysUpTime OID if not already present
if ((vbs.size() == 0) || ((vbs.size() >= 1) && (!(vbs.get(0)).getOid().equals(SnmpConstants.sysUpTime)))) {
vbs.add(0, new VariableBinding(SnmpConstants.sysUpTime, sysUpTime));
}
-
+ // Insert trap OID if not already present
if ((vbs.size() == 1) || ((vbs.size() >= 2) && (!(vbs.get(1)).getOid().equals(SnmpConstants.snmpTrapOID)))) {
vbs.add(1, new VariableBinding(SnmpConstants.snmpTrapOID, trapOID));
}
@@ -469,27 +471,28 @@ public class SnmpTrapSender implements PDUFactory {
return "SNMP is not enabled.";
}
- String baseOid = alertParameters.getSimpleValue("oid",null);
+ String variableBindingPrefix = alertParameters.getSimpleValue(SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX, null);
// TODO add a request id and a timestamp
this.address = createAddress(alertParameters);
// bind the alert definitions name on the oid set in the alert
- getVariableBindings(baseOid + ".1" + "={s}" + alert.getAlertDefinition().getName());
+ getVariableBindings(variableBindingPrefix + ".1" + "={s}" + alert.getAlertDefinition().getName());
// the resource the alert was defined on
- getVariableBindings(baseOid + ".2" + "={s}" + alert.getAlertDefinition().getResource().getName());
+ getVariableBindings(variableBindingPrefix + ".2" + "={s}" + alert.getAlertDefinition().getResource().getName());
// the platform this resource is on
- getVariableBindings(baseOid + ".3" + "={s}" + platformName);
+ getVariableBindings(variableBindingPrefix + ".3" + "={s}" + platformName);
// the conditions of this alert
- getVariableBindings(baseOid + ".4" + "={s}" + conditions);
+ getVariableBindings(variableBindingPrefix + ".4" + "={s}" + conditions);
// severity of the alert
- getVariableBindings(baseOid + ".5" + "={s}" + alert.getAlertDefinition().getPriority().toString().toLowerCase());
+ getVariableBindings(variableBindingPrefix + ".5" + "={s}" + alert.getAlertDefinition().getPriority().toString().toLowerCase());
// url of the alert detail
- getVariableBindings(baseOid + ".6" + "={s}" + alertUrl);
+ getVariableBindings(variableBindingPrefix + ".6" + "={s}" + alertUrl);
// hierarchy of the resource on alert
- getVariableBindings(baseOid + ".7" + "={s}" + hierarchy);
+ getVariableBindings(variableBindingPrefix + ".7" + "={s}" + hierarchy);
setSysUpTimeFromBootTime(bootTime); // needs to be called before checkTrapVariables();
+ setTrapOIDFromAlertParameters(alertParameters); // needs to be called before checkTrapVariables();
checkTrapVariables(this.vbs);
try {
PDU response = send();
@@ -533,6 +536,13 @@ public class SnmpTrapSender implements PDUFactory {
}
+ private void setTrapOIDFromAlertParameters(Configuration alertParameters) {
+ String trapOid = alertParameters.getSimpleValue(SnmpInfo.PARAM_TRAP_OID, null);
+ if (StringUtil.isNotBlank(trapOid)) {
+ setTrapOID(new OID(trapOid));
+ }
+ }
+
private boolean init() {
String snmpVersion = systemConfig.getSimpleValue("snmpVersion",null);
@@ -795,4 +805,4 @@ public class SnmpTrapSender implements PDUFactory {
public void setPduType(int pduType) {
this.pduType = pduType;
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
index 32ec521..83a55e9 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<alert-plugin
+<a:alert-plugin
name="alert-snmp"
displayName="Alert:SNMP"
- xmlns="urn:xmlns:rhq-serverplugin.alert"
+ xmlns:a="urn:xmlns:rhq-serverplugin.alert"
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
package="org.rhq.enterprise.server.plugins.alertSnmp"
@@ -65,15 +65,33 @@
</serverplugin:plugin-configuration>
<!-- How does this sender show up in drop downs etc -->
- <short-name>SNMP Traps</short-name>
+ <a:short-name>SNMP Traps</a:short-name>
<!-- Class that does the actual sending -->
- <plugin-class>SnmpSender</plugin-class>
+ <a:plugin-class>SnmpSender</a:plugin-class>
- <alert-configuration>
+ <a:alert-configuration>
<c:simple-property name="host" type="string" required="true" description="Trap target host"/>
<c:simple-property name="port" type="integer" required="false" default="162" description="Trap target port"/>
- <c:simple-property name="oid" type="string" required="true" description="OID of the trap sent"/>
-
- </alert-configuration>
-</alert-plugin>
+ <c:simple-property name="oid" displayName="Variable bindings prefix" type="string" required="true">
+ <c:description>
+ <![CDATA[
+ <p>RHQ will send alert notification details as a list of variable bindings in the
+ SNMP trap PDU.</p>
+ <p><strong>Do not confuse this paramater with 'Trap Oid'.</strong></p>
+ ]]>
+ </c:description>
+ </c:simple-property>
+ <c:simple-property name="trapOid" required="false">
+ <c:description>
+ <![CDATA[
+ <p>If set, the value of this paramater will override the value of the Trap Oid parameter defined globally
+ in the server plugin configuration. The Trap OID is sent as the second variable binding in the SNMP trap
+ PDU.</p>
+ <p><strong>Only applicable to v2c and v3 traps.</strong></p>
+ <p><strong>Do not confuse this paramater with 'Variable bindings prefix'.</strong></p>
+ ]]>
+ </c:description>
+ </c:simple-property>
+ </a:alert-configuration>
+</a:alert-plugin>
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java
new file mode 100644
index 0000000..c46c8b6
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java
@@ -0,0 +1,106 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.plugins.alertSnmp;
+
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.DEFAULT_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_HOST;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_TRAP_OID;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX;
+import static org.testng.Assert.*;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+
+/**
+ * @author Thomas Segismont
+ */
+public class SnmpInfoTest {
+
+ @Test
+ public void shouldDetectMissingParams() throws Exception {
+ Configuration configuration = new Configuration();
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: OID, host");
+
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: OID");
+
+ configuration.remove(PARAM_HOST);
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: host");
+ }
+
+ @Test
+ public void shouldAssumeDefaultValues() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNull(snmpInfo.error, "SnmpInfo#load should not have detected an error");
+ assertEquals(snmpInfo.host, "pipo");
+ assertEquals(snmpInfo.oid, "molo");
+ assertEquals(snmpInfo.port, SnmpInfo.DEFAULT_PORT);
+ }
+
+ @Test
+ public void shouldExposeAllParams() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ configuration.setSimpleValue(PARAM_PORT, "123");
+ configuration.setSimpleValue(PARAM_TRAP_OID, "logo");
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNull(snmpInfo.error, "SnmpInfo#load should not have detected an error");
+ assertEquals(snmpInfo.host, "pipo");
+ assertEquals(snmpInfo.port, "123");
+ assertEquals(snmpInfo.oid, "molo");
+ assertEquals(snmpInfo.trapOid, "logo");
+ }
+
+ @Test
+ public void testStringRepresentation() {
+ // We are not testing something really tricky here...
+ // But the String representation of an SnmpInfo instance is used in the UI as a description in the alert
+ // definition notification list. So this test is here to remind us in the future that the format of the
+ // String representation is constrained (even not strongly).
+ Configuration configuration = new Configuration();
+ assertEquals(SnmpInfo.load(configuration).toString(), "UnknownHost:" + DEFAULT_PORT
+ + " (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:" + DEFAULT_PORT + " (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_PORT, "35162");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (molo) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_TRAP_OID, "logo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (molo) (logo)");
+ }
+
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java
new file mode 100644
index 0000000..38b36d7
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java
@@ -0,0 +1,378 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.plugins.alertSnmp;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+import static org.rhq.core.domain.alert.AlertPriority.HIGH;
+import static org.rhq.core.domain.alert.notification.ResultState.FAILURE;
+import static org.rhq.core.domain.alert.notification.ResultState.SUCCESS;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_HOST;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_TRAP_OID;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX;
+import static org.testng.Assert.*;
+
+import java.util.Arrays;
+import java.util.ListIterator;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.snmp4j.CommandResponder;
+import org.snmp4j.CommandResponderEvent;
+import org.snmp4j.PDU;
+import org.snmp4j.Snmp;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.smi.Address;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.SMIConstants;
+import org.snmp4j.smi.UdpAddress;
+import org.snmp4j.smi.VariableBinding;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.notification.SenderResult;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.util.StringUtil;
+import org.rhq.enterprise.server.alert.AlertManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+
+/**
+ * @author Thomas Segismont
+ */
+public class SnmpSenderTest {
+
+ private static final Log LOG = LogFactory.getLog(SnmpSenderTest.class);
+
+ private static final String TEST_TRAP_OID_PLUGIN_CONFIG = "1.3.6.1.4.1.18017";
+
+ private static final String TEST_TRAP_OID_ALERT_PARAM = "1.3.6.1.4.1.18018";
+
+ private static final String TEST_VARIABLE_BINDING_PREFIX = "1.3.6.1.4.1.18019";
+
+ private static final String TEST_HOST = "127.0.0.1";
+
+ private static final int TEST_PORT = 35162;
+
+ private static final String TEST_PORT_VARIABLE = "alert.snmp.test.port";
+
+ private ConcurrentLinkedQueue<PDU> receivedTraps;
+
+ private Snmp snmp;
+
+ @Mock
+ private ResourceManagerLocal resourceManager;
+
+ @Mock
+ private AlertManagerLocal alertManager;
+
+ private TestSnmpSender snmpSender;
+
+ @BeforeMethod
+ public void setUp() throws Exception {
+ receivedTraps = new ConcurrentLinkedQueue<PDU>();
+
+ snmp = new Snmp(new DefaultUdpTransportMapping());
+ Address targetAddress = new UdpAddress(getTestPort());
+ boolean installedTrapListener = snmp.addNotificationListener(targetAddress, new CommandResponder() {
+ @Override
+ public void processPdu(CommandResponderEvent event) {
+ receivedTraps.offer(event.getPDU());
+ }
+ });
+ if (!installedTrapListener) {
+ throw new RuntimeException("Could not install trap listener");
+ }
+
+ MockitoAnnotations.initMocks(this);
+
+ Configuration pluginConfiguration = new Configuration();
+ pluginConfiguration.setSimpleValue("snmpVersion", "2c");
+ pluginConfiguration.setSimpleValue("trapOid", TEST_TRAP_OID_PLUGIN_CONFIG);
+ pluginConfiguration.setSimpleValue("community", "public");
+ snmpSender = new TestSnmpSender(resourceManager, alertManager, pluginConfiguration);
+ }
+
+ private static int getTestPort() {
+ String testPortVariable = System.getProperty(TEST_PORT_VARIABLE);
+ if (StringUtil.isNotBlank(testPortVariable)) {
+ try {
+ int port = Integer.parseInt(testPortVariable);
+ LOG.info("Using port " + testPortVariable + " for SNMP traps");
+ return port;
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid port variable: " + testPortVariable);
+ }
+ }
+ LOG.info("Using default port " + TEST_PORT + " for SNMP traps");
+ return TEST_PORT;
+ }
+
+ @AfterMethod
+ public void tearDown() throws Exception {
+ if (snmp != null) {
+ snmp.close();
+ }
+ }
+
+ @Test
+ public void shouldReturnSimpleFailureForInvalidNotificationParameters() {
+ Configuration alertParameters = new Configuration();
+ snmpSender.setAlertParameters(alertParameters);
+
+ SenderResult result = snmpSender.send(createAlertForResourceWithId(13004, "", "", HIGH));
+
+ assertNotNull(result);
+ assertEquals(result.getState(), FAILURE);
+ assertEquals(result.getFailureMessages().size(), 1);
+ String expectedError = SnmpInfo.load(alertParameters).error;
+ assertNotNull(expectedError);
+ assertEquals(result.getFailureMessages().get(0), expectedError);
+ }
+
+ @Test
+ public void shouldReturnSimpleFailureWhenErrorOccurs() {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ snmpSender.setAlertParameters(alertParameters);
+
+ int resourceId = 13004;
+ Alert alert = createAlertForResourceWithId(resourceId, "", "", HIGH);
+ String exceptionMessage = "Test Error";
+ when(resourceManager.getResourceLineage(eq(resourceId))).thenThrow(new RuntimeException(exceptionMessage));
+
+ SenderResult result = snmpSender.send(alert);
+
+ assertNotNull(result);
+ assertEquals(result.getState(), FAILURE);
+ assertEquals(result.getFailureMessages().size(), 1);
+ String actualErrorMessage = result.getFailureMessages().get(0);
+ assertTrue(actualErrorMessage.endsWith(exceptionMessage), "Unexpected error message: " + actualErrorMessage);
+ }
+
+ @Test(timeOut = 1000 * 60)
+ public void testSendWithDefaultSnmpTrapOid() throws Exception {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ snmpSender.setAlertParameters(alertParameters);
+
+ testSendWithSnmpTrapOid(new OID(TEST_TRAP_OID_PLUGIN_CONFIG));
+ }
+
+ @Test(timeOut = 1000 * 60)
+ public void testSendWithSpecificSnmpTrapOid() throws Exception {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ alertParameters.setSimpleValue(PARAM_TRAP_OID, TEST_TRAP_OID_ALERT_PARAM);
+ snmpSender.setAlertParameters(alertParameters);
+
+ testSendWithSnmpTrapOid(new OID(TEST_TRAP_OID_ALERT_PARAM));
+ }
+
+ private void testSendWithSnmpTrapOid(OID snmpTrapOid) throws InterruptedException {
+ int resourceId = 13004;
+ String resourceName = "Resource " + resourceId;
+ String alertDefinitionName = "Alert Definition " + resourceId;
+ AlertPriority alertPriority = HIGH;
+ Alert alert = createAlertForResourceWithId(resourceId, resourceName, alertDefinitionName, alertPriority);
+ Resource platformResouce = new Resource();
+ String platformName = "Platform Resource " + resourceId;
+ platformResouce.setName(platformName);
+
+ when(resourceManager.getResourceLineage(eq(resourceId))).thenReturn(
+ Arrays.asList(platformResouce, alert.getAlertDefinition().getResource()));
+ String alertConditions = "Alert Conditions " + resourceId;
+ when(alertManager.prettyPrintAlertConditions(eq(alert), eq(false))).thenReturn(alertConditions);
+ String alertUrl = "https://www.rhq.com/alert/" + resourceId;
+ when(alertManager.prettyPrintAlertURL(eq(alert))).thenReturn(alertUrl);
+
+ assertNull(receivedTraps.peek(), "Something sent a trap before on our test port");
+
+ SenderResult result = snmpSender.send(alert);
+
+ assertEquals(result.getState(), SUCCESS, result.getFailureMessages().toString());
+ while (receivedTraps.peek() == null) {
+ Thread.sleep(1000);
+ }
+ PDU pdu = receivedTraps.poll();
+ assertNull(receivedTraps.peek(), "Only one trap should have been received");
+
+ assertExpectedPdu(pdu, new PduExpectedValues(snmpTrapOid, resourceName, alertDefinitionName, alertPriority,
+ platformName, alertConditions, alertUrl));
+ }
+
+ private void assertExpectedPdu(PDU pdu, PduExpectedValues expectedValues) {
+ Vector variableBindings = pdu.getVariableBindings();
+
+ assertTrue(variableBindings.size() == 9, "Variable bindings should contain 9 variable bindings and not "
+ + variableBindings.size() + ": " + variableBindings);
+
+ @SuppressWarnings("unchecked")
+ ListIterator<VariableBinding> variableBindingsIterator = variableBindings.listIterator();
+
+ VariableBinding variableBinding = variableBindingsIterator.next();
+ assertEquals(variableBinding.getOid(), SnmpConstants.sysUpTime);
+
+ variableBinding = variableBindingsIterator.next();
+ assertEquals(variableBinding.getOid(), SnmpConstants.snmpTrapOID);
+ assertEquals(variableBinding.getVariable(), expectedValues.getSnmpTrapOid());
+
+ OID oidPrefix = new OID(TEST_VARIABLE_BINDING_PREFIX);
+ while (variableBindingsIterator.hasNext()) {
+ variableBinding = variableBindingsIterator.next();
+
+ assertVariableBindingIsPrefixed(variableBinding, oidPrefix);
+ assertVariableBindingHasStringValue(variableBinding);
+
+ switch (variableBindingsIterator.previousIndex()) {
+ case 2:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertDefinitionName()));
+ break;
+ case 3:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getResourceName()));
+ break;
+ case 4:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getPlatformName()));
+ break;
+ case 5:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertConditions()));
+ break;
+ case 6:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertPriority()
+ .toString().toLowerCase()));
+ break;
+ case 7:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertUrl()));
+ break;
+ case 8:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getPlatformName() + "::"
+ + expectedValues.getResourceName() + "::"));
+ break;
+ default:
+ throw new RuntimeException("Unexpected index: " + variableBindingsIterator.previousIndex());
+ }
+ }
+ }
+
+ private void assertVariableBindingHasStringValue(VariableBinding variableBinding) {
+ assertEquals(variableBinding.getVariable().getSyntax(), SMIConstants.SYNTAX_OCTET_STRING,
+ "Variable binding value [" + variableBinding.getVariable() + "] has wrong type");
+ }
+
+ private void assertVariableBindingIsPrefixed(VariableBinding variableBinding, OID oidPrefix) {
+ assertTrue(variableBinding.getOid().startsWith(oidPrefix), "Variable binding OID [" + variableBinding.getOid()
+ + "] has wrong prefix");
+ }
+
+ private Alert createAlertForResourceWithId(int resourceId, String resourceName, String alertDefinitionName,
+ AlertPriority alertPriority) {
+ Resource resource = new Resource();
+ resource.setId(resourceId);
+ resource.setName(resourceName);
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName(alertDefinitionName);
+ alertDefinition.setResource(resource);
+ alertDefinition.setPriority(alertPriority);
+ Alert alert = new Alert();
+ alert.setAlertDefinition(alertDefinition);
+ return alert;
+ }
+
+ private static final class TestSnmpSender extends SnmpSender {
+
+ TestSnmpSender(ResourceManagerLocal resourceManager, AlertManagerLocal alertManager,
+ Configuration pluginConfiguration) {
+ super(resourceManager, alertManager);
+ this.preferences = pluginConfiguration;
+ }
+
+ void setAlertParameters(Configuration alertParameters) {
+ this.alertParameters = alertParameters;
+ }
+
+ }
+
+ private static final class PduExpectedValues {
+
+ private final OID snmpTrapOid;
+ private final String resourceName;
+ private final String alertDefinitionName;
+ private final AlertPriority alertPriority;
+ private final String platformName;
+ private final String alertConditions;
+ private final String alertUrl;
+
+ private PduExpectedValues(OID snmpTrapOid, String resourceName, String alertDefinitionName,
+ AlertPriority alertPriority, String platformName, String alertConditions, String alertUrl) {
+ this.snmpTrapOid = snmpTrapOid;
+ this.resourceName = resourceName;
+ this.alertDefinitionName = alertDefinitionName;
+ this.alertPriority = alertPriority;
+ this.platformName = platformName;
+ this.alertConditions = alertConditions;
+ this.alertUrl = alertUrl;
+ }
+
+ public OID getSnmpTrapOid() {
+ return snmpTrapOid;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ public String getAlertDefinitionName() {
+ return alertDefinitionName;
+ }
+
+ public AlertPriority getAlertPriority() {
+ return alertPriority;
+ }
+
+ public String getPlatformName() {
+ return platformName;
+ }
+
+ public String getAlertConditions() {
+ return alertConditions;
+ }
+
+ public String getAlertUrl() {
+ return alertUrl;
+ }
+ }
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml b/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml
new file mode 100644
index 0000000..73b2ae5
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- | For more configuration information and examples, see the Jakarta Log4j | website: http://jakarta.apache.org/log4j -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="ERROR"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="target/test.log"/>
+ <param name="Append" value="false"/>
+ <param name="Threshold" value="DEBUG"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="DEBUG"/>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit fabce7666b08f73ea113807ec42b47a3d3eb5929
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 11:15:34 2013 -0400
BZ 957282 957288 add bundle target of "Install Directory"
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 5a30ec3..45f4e05 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1333,6 +1333,10 @@
</drift-definition>
<bundle-target>
+ <destination-base-dir name="Install Directory" description="The top directory where the application server is installed. (i.e. the value found in the 'Home Directory' connection property)">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>homeDir</value-name>
+ </destination-base-dir>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
<value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
commit 8ae20bd510aa660e94f70cad95fc680fd0dedd47
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Apr 26 14:41:02 2013 -0400
BZ 917085 - allow for relative and absolute raw file paths to include ".."
diff --git a/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java b/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
index e81fbaa..c55c1bc 100644
--- a/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
+++ b/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
@@ -30,6 +30,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import org.rhq.core.template.TemplateEngine;
+import org.rhq.core.util.file.FileUtil;
/**
* Data that describes a particular deployment. In effect, this provides the
@@ -114,7 +115,7 @@ public class DeploymentData {
this.deploymentProps = deploymentProps;
this.zipFiles = zipFiles;
this.rawFiles = rawFiles;
- this.destinationDir = destinationDir;
+ this.destinationDir = getCanonicalFile(destinationDir);
this.sourceDir = sourceDir;
this.ignoreRegex = ignoreRegex;
this.manageRootDir = manageRootDir;
@@ -131,6 +132,69 @@ public class DeploymentData {
this.templateEngine = templateEngine;
}
+ // We need to "normalize" all raw file paths that have ".." in them to ensure everything works properly.
+ // Any raw file pathname (the values in this.rawFiles) that needs to be normalized will be converted to
+ // a canonical path. Note that any pathname that is relative but have ".." paths that end up taking the file
+ // above the destination directory needs to be normalized and will end up being an absolute path
+ // (so all log messages will indicate the full absolute path and if the file
+ // needs to be backed up it will be backed up as if it was an external file that was specified with an absolute path).
+ // If the relative path has ".." but does not take the file above the destination directory will simply have its ".."
+ // normalized out but will still be a relative path (relative to destination directory) (we can't make it absolute
+ // otherwise Deployer's update will run into errors while backing up and scanning for deleted files).
+ // See BZ 917085.
+ for (Map.Entry<File, File> entry : this.rawFiles.entrySet()) {
+ File rawFile = entry.getValue();
+ String rawFilePath = rawFile.getPath();
+
+ boolean doubledot = rawFilePath.replace('\\', '/').matches(".*((/\\.\\.)|(\\.\\./)).*"); // finds "/.." or "../" in the string
+
+ if (doubledot) {
+ File fileToCanonicalize;
+
+ if (rawFile.isAbsolute()) {
+ fileToCanonicalize = rawFile;
+ } else {
+ boolean isWindows = (File.separatorChar == '\\');
+ if (isWindows) {
+ // of course, Windows has to make it enormously difficult to do this right...
+
+ // determine if the windows rawFile relative path specified a drive (e.g. C:foobar.txt)
+ StringBuilder rawFilePathBuilder = new StringBuilder(rawFilePath);
+ String rawFileDriveLetter = FileUtil.stripDriveLetter(rawFilePathBuilder); // rawFilePathBuilder now has drive letter stripped
+
+ // determine what, if any, drive letter is specified in the destination directory
+ StringBuilder destDirAbsPathBuilder = new StringBuilder(this.destinationDir.getAbsolutePath());
+ String destDirDriveLetter = FileUtil.stripDriveLetter(destDirAbsPathBuilder);
+
+ // figure out what the absolute, normalized path is for the raw file
+ if ((destDirDriveLetter == null || rawFileDriveLetter == null)
+ || rawFileDriveLetter.equals(destDirDriveLetter)) {
+ fileToCanonicalize = new File(this.destinationDir, rawFilePathBuilder.toString());
+ } else {
+ throw new IllegalArgumentException("Cannot normalize relative path [" + rawFilePath
+ + "]; its drive letter is different than the destination directory ["
+ + this.destinationDir.getAbsolutePath() + "]");
+ }
+ } else {
+ fileToCanonicalize = new File(this.destinationDir, rawFilePath);
+ }
+ }
+
+ fileToCanonicalize = getCanonicalFile(fileToCanonicalize);
+
+ if (isPathUnderBaseDir(this.destinationDir, fileToCanonicalize)) {
+ // we can keep rawFile path relative, but we need to normalize out the ".." paths
+ String baseDir = this.destinationDir.getAbsolutePath();
+ String absRawFilePath = fileToCanonicalize.getAbsolutePath();
+ String canonicalRelativePath = absRawFilePath.substring(baseDir.length() + 1); // should always return a valid path; if not, let it throw exception (which likely means there is a bug here)
+ entry.setValue(new File(canonicalRelativePath));
+ } else {
+ // raw file path has ".." such that the file is really above destination dir - use an absolute, canonical path
+ entry.setValue(fileToCanonicalize);
+ }
+ }
+ }
+
return;
}
@@ -177,4 +241,30 @@ public class DeploymentData {
public Map<File, Boolean> getZipsExploded() {
return zipsExploded;
}
+
+ private File getCanonicalFile(File file) {
+ try {
+ file = file.getCanonicalFile();
+ } catch (Exception e) {
+ // ignore this - this really should never happen, but if it does,
+ // we want to continue and hope using the non-normalized file is ok;
+ file = file.getAbsoluteFile();
+ }
+ return file;
+ }
+
+ private boolean isPathUnderBaseDir(File base, File path) {
+ // this method assumes base and path are absolute and canonical
+ if (base == null) {
+ return false;
+ }
+
+ while (path != null) {
+ if (base.equals(path)) {
+ return true;
+ }
+ path = path.getParentFile();
+ }
+ return false;
+ }
}
diff --git a/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java b/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java
new file mode 100644
index 0000000..7a62bf0
--- /dev/null
+++ b/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java
@@ -0,0 +1,275 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.core.util.updater;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.template.TemplateEngine;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * Tests deploying raw files to deployment locations specified with ".." in the path.
+ * This will require the deployer code to transform the paths to canonical paths.
+ *
+ * @author John Mazzitelli
+ */
+@Test
+public class DeployerCanonicalPathTest {
+ private TemplateEngine templateEngine;
+
+ @BeforeClass
+ public void beforeClass() {
+ Map<String, String> tokens = new HashMap<String, String>();
+ tokens.put("rhq.system.hostname", "localhost");
+ tokens.put("rhq.system.sysprop.java.version", System.getProperty("java.version"));
+
+ templateEngine = new TemplateEngine(tokens);
+ }
+
+ @BeforeMethod
+ public void beforeMethod() {
+ System.out.println("\n\n=============== START OF NEW TEST ===============\n");
+ }
+
+ // any raw file path (absolute or relative) that contains ".." will be converted to an absolute, canonical path - this is what we test
+ public void testInitialDeployRawFilesWithCanonicalPaths() throws Exception {
+ File tmpDirDest = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".dest", null);
+ File tmpDirSrc = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".src", null);
+ File rawFileRelativeDest = new File("dir-does-not-existA/../rawA.txt"); // relative to "tmpDirDest" that we just created above
+ File rawFileRelativeDest2 = new File("dir-does-not-existA/../../rawA.txt"); // relative to "tmpDirDest" but it takes us above it
+ File rawFileAbsoluteDest = new File(System.getProperty("java.io.tmpdir"), "dir-does-not-existB/../rawB.txt");
+
+ try {
+ // put some source files in our tmpDirSrc location
+ File testRawFileA = new File(tmpDirSrc, "updater-testA.txt");
+ File testRawFileA2 = new File(tmpDirSrc, "updater-testA2.txt");
+ File testRawFileB = new File(tmpDirSrc, "updater-testB.txt");
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA);
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA2);
+ FileUtil.copyFile(new File("target/test-classes/updater-testB.txt"), testRawFileB);
+
+ DeploymentProperties deploymentProps = new DeploymentProperties(0, "testbundle", "1.0.test", null);
+ Set<File> zipFiles = null;
+ Map<File, File> rawFiles = new HashMap<File, File>(3);
+ rawFiles.put(testRawFileA, rawFileRelativeDest); // we will realize this one ...
+ rawFiles.put(testRawFileA2, rawFileRelativeDest2); // and this one ...
+ rawFiles.put(testRawFileB, rawFileAbsoluteDest); // and we will realize this one, too
+ File destDir = tmpDirDest;
+ Pattern ignoreRegex = null;
+ Set<File> realizeRawFiles = new HashSet<File>(3);
+ realizeRawFiles.add(testRawFileA);
+ realizeRawFiles.add(testRawFileA2);
+ realizeRawFiles.add(testRawFileB);
+ DeploymentData dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null,
+ realizeRawFiles, templateEngine, ignoreRegex, true, null);
+ Deployer deployer = new Deployer(dd);
+ DeployDifferences diff = new DeployDifferences();
+ FileHashcodeMap map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+
+ String rawFileRelativeDestCanonical = new File(tmpDirDest, rawFileRelativeDest.getPath()).getCanonicalPath();
+ String rawFileRelativeDestCanonical2 = new File(tmpDirDest, rawFileRelativeDest2.getPath())
+ .getCanonicalPath();
+ String rawFileAbsoluteDestCanonical = rawFileAbsoluteDest.getCanonicalPath();
+
+ assert map.size() == 3 : map;
+
+ assert map.containsKey("rawA.txt") : map;
+ assert new File(rawFileRelativeDestCanonical).exists();
+ assert new File(rawFileRelativeDestCanonical2).exists();
+ assert MessageDigestGenerator.getDigestString(new File(rawFileRelativeDestCanonical)).equals(
+ map.get("rawA.txt"));
+
+ // rawFileRelativeDestCanonical2 should be treated just like an absolute, external file
+ assert MessageDigestGenerator.getDigestString(new File(rawFileRelativeDestCanonical2)).equals(
+ map.get(rawFileRelativeDestCanonical2));
+ assert !MessageDigestGenerator.getDigestString(testRawFileA).equals(map.get("rawA.txt")) : "should have different hash, we realize this one!";
+
+ assert map.containsKey(rawFileAbsoluteDestCanonical) : map;
+ assert new File(rawFileAbsoluteDestCanonical).exists();
+ assert MessageDigestGenerator.getDigestString(new File(rawFileAbsoluteDestCanonical)).equals(
+ map.get(rawFileAbsoluteDestCanonical));
+ assert !MessageDigestGenerator.getDigestString(testRawFileB).equals(map.get(rawFileAbsoluteDestCanonical)) : "should have different hash, we realized this one";
+
+ assert diff.getAddedFiles().size() == 3 : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ assert diff.getRealizedFiles().size() == 3 : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ } finally {
+ FileUtil.purge(tmpDirDest, true);
+ FileUtil.purge(tmpDirSrc, true);
+ rawFileAbsoluteDest.getCanonicalFile().delete();
+ }
+ }
+
+ public void testUpdateDeployRawFileWithRelativePath() throws Exception {
+ File tmpDirDest = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".dest", null);
+ File tmpDirSrc = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".src", null);
+ File rawFileRelativeDest = new File("dir-does-not-existA/../rawA.txt"); // relative to "tmpDirDest" that we just created above
+ File rawFileRelativeDest2 = new File("dir-does-not-existA/../../rawA.txt"); // relative to "tmpDirDest" but it takes us above it
+ File rawFileAbsoluteDest = new File(System.getProperty("java.io.tmpdir"), "dir-does-not-existB/../rawB.txt");
+
+ try {
+ // put some source files in our tmpDirSrc location
+ File testRawFileA = new File(tmpDirSrc, "updater-testA.txt");
+ File testRawFileA2 = new File(tmpDirSrc, "updater-testA2.txt");
+ File testRawFileB = new File(tmpDirSrc, "updater-testB.txt");
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA);
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA2);
+ FileUtil.copyFile(new File("target/test-classes/updater-testB.txt"), testRawFileB);
+
+ DeploymentProperties deploymentProps = new DeploymentProperties(0, "testbundle", "1.0.test", null);
+ Set<File> zipFiles = null;
+ Map<File, File> rawFiles = new HashMap<File, File>(3);
+ rawFiles.put(testRawFileA, rawFileRelativeDest);
+ rawFiles.put(testRawFileA2, rawFileRelativeDest2);
+ rawFiles.put(testRawFileB, rawFileAbsoluteDest);
+ File destDir = tmpDirDest;
+ Pattern ignoreRegex = null;
+ DeploymentData dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null, null,
+ templateEngine, ignoreRegex, true, null);
+ Deployer deployer = new Deployer(dd);
+ DeployDifferences diff = new DeployDifferences();
+ FileHashcodeMap map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+ assert map.size() == 3 : map;
+
+ // make sure the first raw file is in the dest dir
+ String f = rawFileRelativeDest.getPath();
+ File destFile = new File(tmpDirDest, f).getCanonicalFile(); // notice f is assumed relative to tmpDirDest, must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedR".getBytes()), destFile); // change the file so we back it up during update
+
+ // make sure the second raw file, though specified originally as a relative file, is in the external location
+ f = rawFileRelativeDest2.getPath();
+ destFile = new File(tmpDirDest, f).getCanonicalFile(); // must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedR2".getBytes()), destFile); // change the file so we back it up during update
+
+ // make sure the third raw file is in the external location
+ destFile = rawFileAbsoluteDest.getCanonicalFile(); // must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedA".getBytes()), destFile); // change the file so we back it up during update
+
+ // UPDATE
+ // alter the src files so we backup our changed files
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedR".getBytes()), testRawFileA);
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedR2".getBytes()), testRawFileA2);
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedA".getBytes()), testRawFileB);
+
+ deploymentProps = new DeploymentProperties(1, "testbundle", "2.0.test", null);
+ dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null, null,
+ templateEngine, ignoreRegex, true, null);
+ deployer = new Deployer(dd);
+ diff = new DeployDifferences();
+ map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+
+ String rawFileRelativeDestCanonical = new File(tmpDirDest, rawFileRelativeDest.getPath())
+ .getCanonicalPath();
+ String rawFileRelativeDestCanonical2 = new File(tmpDirDest, rawFileRelativeDest2.getPath())
+ .getCanonicalPath();
+ String rawFileAbsoluteDestCanonical = rawFileAbsoluteDest.getCanonicalPath();
+
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileRelativeDestCanonical))))
+ .equals("src.modifiedR");
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileRelativeDestCanonical2))))
+ .equals("src.modifiedR2");
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileAbsoluteDestCanonical))))
+ .equals("src.modifiedA");
+
+ boolean isWindows = File.separatorChar == '\\';
+ final File metadir = new File(tmpDirDest, ".rhqdeployments");
+ File backupRel = new File(metadir, "1/backup/rawA.txt");
+ File backupRel2;
+ // test the second raw file, the one that was specified originally as a relative file but took us out of the dest dir
+ if (!isWindows) {
+ backupRel2 = new File(metadir, "1/ext-backup/" + rawFileRelativeDestCanonical2);
+ } else {
+ StringBuilder str = new StringBuilder(rawFileRelativeDestCanonical2);
+ String driveLetter = FileUtil.stripDriveLetter(str);
+ if (driveLetter != null) {
+ driveLetter = "_" + driveLetter + '/';
+ } else {
+ driveLetter = "";
+ }
+ backupRel2 = new File(metadir, "1/ext-backup/" + driveLetter + str.toString());
+ }
+ // test the third raw file, the one that was specified originally as an absolute, external file
+ File backupAbs;
+ if (!isWindows) {
+ backupAbs = new File(metadir, "1/ext-backup/" + rawFileAbsoluteDestCanonical);
+ } else {
+ StringBuilder str = new StringBuilder(rawFileAbsoluteDestCanonical);
+ String driveLetter = FileUtil.stripDriveLetter(str);
+ if (driveLetter != null) {
+ driveLetter = "_" + driveLetter + '/';
+ } else {
+ driveLetter = "";
+ }
+ backupAbs = new File(metadir, "1/ext-backup/" + driveLetter + str.toString());
+ }
+
+ // the backup files should exist
+ assert backupRel.exists() : backupRel;
+ assert backupRel2.exists() : backupRel2;
+ assert backupAbs.exists() : backupAbs;
+
+ assert map.size() == 3 : map;
+ assert diff.getChangedFiles().size() == 3 : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ assert diff.getDeletedFiles().isEmpty() : diff;
+ assert diff.getBackedUpFiles().size() == 3 : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ } finally {
+ FileUtil.purge(tmpDirDest, true);
+ FileUtil.purge(tmpDirSrc, true);
+ rawFileAbsoluteDest.getCanonicalFile().delete();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index daf5463..f0605a2 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -26,10 +26,12 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
@@ -70,20 +72,25 @@ import org.rhq.core.util.updater.DeploymentsMetadata;
@Test
public class AntBundlePluginComponentTest {
+ private static final boolean ENABLE_TESTS = true;
+
private static final String DEST_BASE_DIR_NAME = "Root File System"; // just mimics the real platform plugin types' name
private AntBundlePluginComponent plugin;
+ private File testFilesBaseDir; // under here will go all our test files: tmpDir, bundleFilesDir and destDir
private File tmpDir;
private File bundleFilesDir;
private File destDir;
@BeforeClass
public void initDirs() throws Exception {
- this.tmpDir = new File("target/antbundletest/tmp");
+ this.testFilesBaseDir = new File("target/antbundletest");
+
+ this.tmpDir = new File(this.testFilesBaseDir, "tmp");
FileUtil.purge(this.tmpDir, true);
- this.bundleFilesDir = new File("target/antbundletest/bundlefiles");
+ this.bundleFilesDir = new File(this.testFilesBaseDir, "bundlefiles");
FileUtil.purge(this.bundleFilesDir, true);
- this.destDir = new File("target/antbundletest/destination");
+ this.destDir = new File(this.testFilesBaseDir, "destination");
FileUtil.purge(this.destDir, true);
}
@@ -117,7 +124,7 @@ public class AntBundlePluginComponentTest {
FileUtil.purge(this.destDir, true);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleRevert() throws Exception {
// install then upgrade a bundle first
testAntBundleUpgrade();
@@ -227,17 +234,17 @@ public class AntBundlePluginComponentTest {
assert previousProps.getBundleVersion().equals("3.0"); // testAntBundleUpgrade deployed version 3.0
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleUpgrade() throws Exception {
upgrade(false);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleCleanUpgrade() throws Exception {
upgrade(true);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleInitialInstall() throws Exception {
doAntBundleInitialInstall(true);
}
@@ -348,7 +355,7 @@ public class AntBundlePluginComponentTest {
/**
* Test deployment of an RHQ bundle recipe.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundle() throws Exception {
ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
@@ -412,9 +419,149 @@ public class AntBundlePluginComponentTest {
}
/**
+ * Test raw files whose destination locations have ".." in their paths.
+ */
+ @Test(enabled = ENABLE_TESTS)
+ public void testRawFilesWithDotDotPaths() throws Exception {
+ // our test bundle's relative raw file paths that resolve above dest dir will resolve to here
+ final File externalDir = new File(this.testFilesBaseDir, "ext");
+
+ ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
+ BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
+ Repo repo = new Repo("testSimpleBundle");
+ PackageType packageType = new PackageType("testSimpleBundle", resourceType);
+ Bundle bundle = new Bundle("testSimpleBundle", bundleType, repo, packageType);
+ BundleVersion bundleVersion = new BundleVersion("testSimpleBundle", "1.0", bundle,
+ getRecipeFromFile("test-bundle-dotdot.xml"));
+ BundleDestination destination = new BundleDestination(bundle, "testSimpleBundle", new ResourceGroup(
+ "testSimpleBundle"), DEST_BASE_DIR_NAME, this.destDir.getAbsolutePath());
+ Configuration config = new Configuration();
+
+ BundleDeployment deployment = new BundleDeployment();
+ deployment.setId(0);
+ deployment.setName("test bundle deployment name");
+ deployment.setBundleVersion(bundleVersion);
+ deployment.setConfiguration(config);
+ deployment.setDestination(destination);
+
+ // create test files (see bundle recipe for why these files are created)
+ final String TEST1 = "test1.txt";
+ File file1 = new File(this.bundleFilesDir, TEST1);
+ writeFile(TEST1, file1);
+
+ final String TEST2 = "test2.txt";
+ File file2 = new File(this.bundleFilesDir, TEST2);
+ writeFile(TEST2, file2);
+
+ final String TEST3 = "test3.txt";
+ File file3 = new File(this.bundleFilesDir, TEST3);
+ writeFile(TEST3, file3);
+
+ final String TEST4 = "test4.txt";
+ File file4 = new File(this.bundleFilesDir, TEST4);
+ writeFile(TEST4, file4);
+
+ // ----- initial deployment -----
+ BundleDeployRequest request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ BundleDeployResult results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // test that the files were put where we expected them to be
+ File file1Dest = new File(this.destDir, "subdir/" + TEST1);
+ File file2Dest = new File(this.destDir, TEST2);
+ File file3Dest = new File(externalDir, TEST3);
+ File file4Dest = new File(externalDir, TEST4);
+ assert TEST1.equals(readFile(file1Dest)); // inside dest dir
+ assert TEST2.equals(readFile(file2Dest)); // inside dest dir
+ assert TEST3.equals(readFile(file3Dest)); // outside dest dir
+ assert TEST4.equals(readFile(file4Dest)); // outside dest dir
+
+ // ----- prepare to update the bundle ----
+ cleanPluginDirs(); // clean everything but the dest dir - we want to keep the metadata (this should not purge ext/ dir)
+ prepareBeforeTestMethod(); // prepare for our new test
+ // our src files will have different content for this bundle deployment compared to the initial deployment
+ writeFile(TEST1 + "update", file1);
+ writeFile(TEST2 + "update", file2);
+ writeFile(TEST3 + "update", file3);
+ writeFile(TEST4 + "update", file4);
+ // change our initial deployment files, RHQ should see the changes and back these files up
+ writeFile(TEST1 + "modified", file1Dest);
+ writeFile(TEST2 + "modified", file2Dest);
+ writeFile(TEST3 + "modified", file3Dest);
+ writeFile(TEST4 + "modified", file4Dest);
+
+ // ----- update deployment -----
+ deployment.setId(1);
+ request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // test that all files were updated
+ assert (TEST1 + "update").equals(readFile(file1Dest)); // inside dest dir
+ assert (TEST2 + "update").equals(readFile(file2Dest)); // inside dest dir
+ assert (TEST3 + "update").equals(readFile(file3Dest)); // outside dest dir
+ assert (TEST4 + "update").equals(readFile(file4Dest)); // outside dest dir
+
+ // test that our changed files that were under dest dir were properly backed up
+ DeploymentsMetadata metadata = new DeploymentsMetadata(this.destDir);
+ File backupDir = metadata.getDeploymentBackupDirectory(deployment.getId());
+ File file1Backup = new File(backupDir, "subdir/" + TEST1);
+ File file2Backup = new File(backupDir, TEST2);
+ assert file1Backup.isFile() : "should have been backed up: " + file1Backup;
+ assert file2Backup.isFile() : "should have been backed up: " + file2Backup;
+ assert (TEST1 + "modified").equals(readFile(file1Backup)) : "bad backup file: " + file1Backup;
+ assert (TEST2 + "modified").equals(readFile(file2Backup)) : "bad backup file: " + file2Backup;
+
+ // test that our changed files that were above dest dir were properly backed up
+ Map<String, File> winDirs = metadata.getDeploymentExternalBackupDirectoriesForWindows(deployment.getId());
+ if (winDirs == null) {
+ // we are running on non-windows platform
+ backupDir = metadata.getDeploymentExternalBackupDirectory(deployment.getId());
+ } else {
+ // we are on windows, our test only uses a single drive root, so we can grab the only item in the map
+ assert winDirs.size() == 1 : "should only have 1 ext backup dir on windows: " + winDirs;
+ backupDir = winDirs.values().iterator().next().getAbsoluteFile();
+ }
+ File file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
+ File file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+ assert file3Backup.isFile() : "should have been backed up: " + file3Backup;
+ assert file4Backup.isFile() : "should have been backed up: " + file4Backup;
+ assert (TEST3 + "modified").equals(readFile(file3Backup)) : "bad backup file: " + file3Backup;
+ assert (TEST4 + "modified").equals(readFile(file4Backup)) : "bad backup file: " + file4Backup;
+
+ // ----- revert to last deployment, restoring backed up files
+ deployment.setId(2);
+ request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ request.setRevert(true);
+ results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // make sure our files were reverted, giving us back the files that were backed up
+ assert readFile(file1Backup).equals(readFile(file1Dest)); // inside dest dir
+ assert readFile(file2Backup).equals(readFile(file2Dest)); // inside dest dir
+ assert readFile(file3Backup).equals(readFile(file3Dest)); // outside dest dir
+ assert readFile(file4Backup).equals(readFile(file4Dest)); // outside dest dir
+
+ // ----- clean up our test -----
+ FileUtil.purge(externalDir, true);
+ }
+
+ /**
* Test realizing of replacement tokens of resource tags.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testTags() throws Exception {
ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
@@ -484,7 +631,7 @@ public class AntBundlePluginComponentTest {
/**
* Test deployment of an RHQ bundle recipe where the deploy directory is not to be fully managed.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleNoManageRootDir() throws Exception {
ResourceType resourceType = new ResourceType("testNoManageRootDirBundle", "plugin", ResourceCategory.SERVER,
null);
@@ -618,7 +765,7 @@ public class AntBundlePluginComponentTest {
* Test deployment of an RHQ bundle recipe where the deploy directory is to be fully managed.
* This is the typical use-case and the default behavior.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleManageRootDir() throws Exception {
ResourceType resourceType = new ResourceType("testManageRootDirBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testManageRootDirBundle", resourceType);
@@ -878,6 +1025,10 @@ public class AntBundlePluginComponentTest {
return new String(StreamUtil.slurp(new FileInputStream(file)));
}
+ private void writeFile(final String content, final File file) throws IOException {
+ FileUtil.writeFile(new ByteArrayInputStream(content.getBytes()), file);
+ }
+
private void loadProperties(Properties realizedProps, FileInputStream fileInputStream) throws Exception {
try {
realizedProps.load(fileInputStream);
diff --git a/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml b/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml
new file mode 100644
index 0000000..f96b241
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<project name="bundle-dotdot" default="main" xmlns:rhq="antlib:org.rhq.bundle">
+
+ <rhq:bundle name="bundle-dotdot" version="1.0"
+ description="testing raw files with .. in their destination paths">
+
+ <rhq:deployment-unit name="bundle">
+ <rhq:file name="test1.txt" destinationFile="nothere/../phantom/../subdir/test1.txt" /> <!-- still under dest dir -->
+ <rhq:file name="test2.txt" destinationDir="nothere/../" /> <!-- still under dest dir -->
+ <rhq:file name="test3.txt" destinationFile="../ext/test3.txt" /> <!-- external location outside dest dir-->
+ <rhq:file name="test4.txt" destinationDir="../ext" /> <!-- external location outside dest dir-->
+ </rhq:deployment-unit>
+
+ </rhq:bundle>
+
+ <target name="main"/>
+
+</project>
\ No newline at end of file
commit 06da5f05ae6b970dd16db61226626c45530655f5
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Apr 26 10:39:32 2013 +0200
Don't test the TagManager if it is not enabled.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
index 0195603..aa0ebd4 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
@@ -88,6 +88,10 @@ public class ScriptingAPIServerTest extends ScriptableAbstractEJB3Test {
for (RhqManager m : RhqManager.values()) {
String name = m.name();
+ // Only check for the TagManager if it is enabled at all
+ if (name.contains("TagManager") && !RhqManager.TagManager.enabled()) {
+ continue;
+ }
Object scriptedManager = engine.eval(name);
assertNotNull(scriptedManager);
commit 24ca08b47b9c9b9f23b5c993ec1f04b158c9be43
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Apr 26 10:17:45 2013 +0200
Get the jndi-access test to work with JBoss EAP 6.1alpha1
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 03dfcc9..f83573d 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -15,7 +15,7 @@
<properties>
<jboss.zip>${settings.localRepository}/org/jboss/as/jboss-as-dist/${jboss.version}/jboss-as-dist-${jboss.version}.zip</jboss.zip>
- <jboss.unzip.location>${basedir}/target/jboss-as-${jboss.version}</jboss.unzip.location>
+ <jboss.unzip.location>${basedir}/target/${jboss.eap.version}</jboss.unzip.location>
<jnp.port>54987</jnp.port>
<jnp.rmiPort>54988</jnp.rmiPort>
</properties>
@@ -26,21 +26,21 @@
<artifactId>log4j</artifactId>
<scope>runtime</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-dist</artifactId>
<type>zip</type>
<scope>provided</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-ejb3</artifactId>
<version>${jboss.version}</version>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-scripting-api</artifactId>
@@ -54,7 +54,7 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-scripting-python</artifactId>
@@ -69,7 +69,7 @@
<scope>test</scope>
</dependency>
- <!-- We need to pull some classes from the server jar and itests-2 - namely the naming hack to be able to test
+ <!-- We need to pull some classes from the server jar and itests-2 - namely the naming hack to be able to test
that it actually works -->
<dependency>
<groupId>org.rhq</groupId>
@@ -84,20 +84,20 @@
<artifactId>arquillian-testng-container</artifactId>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<scope>provided</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-depchain</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
-
+
<!-- We'll try remote connections using JNP -->
<dependency>
<groupId>jboss</groupId>
@@ -105,7 +105,7 @@
<version>4.2.2.GA</version>
<scope>test</scope>
</dependency>
-
+
<!-- This is here only to ensure the build order and HAS TO COME AS LAST to avoid any classpath
collisions. -->
<dependency>
@@ -148,6 +148,12 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.jboss.xnio</groupId>
+ <artifactId>xnio-api</artifactId>
+ <version>${xnio.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</profile>
@@ -158,13 +164,13 @@
<name>!remote-test-server</name>
</property>
</activation>
-
+
<dependencies>
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-managed</artifactId>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
</profile>
@@ -175,7 +181,7 @@
<name>remote-test-server</name>
</property>
</activation>
-
+
<dependencies>
<dependency>
<groupId>org.jboss.spec</groupId>
@@ -187,13 +193,12 @@
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-remote</artifactId>
- <version>${jboss.version}</version>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
</profile>
</profiles>
-
+
<build>
<testResources>
<testResource>
@@ -211,8 +216,8 @@
<phase>process-test-resources</phase>
<configuration>
<target>
- <unzip src="${jboss.zip}" dest="${jboss.unzip.location}/.." />
- <copy file="src/test/resources/security.policy" toDir="${jboss.unzip.location}"/>
+ <unzip src="${jboss.zip}" dest="${jboss.unzip.location}/.." />
+ <copy file="src/test/resources/security.policy" toDir="${jboss.unzip.location}"/>
</target>
</configuration>
<goals>
@@ -221,10 +226,10 @@
</execution>
</executions>
</plugin>
-
+
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
- <!-- Everything but the web service tests, this is the standard
+ <!-- Everything but the web service tests, this is the standard
test execution -->
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
@@ -237,7 +242,7 @@
</systemPropertyVariables>
<argLine>${jacoco.unit-test.args} -Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
<additionalClasspathElements>
- <!-- The below is required for tests to run against
+ <!-- The below is required for tests to run against
Oracle. -->
<additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
</additionalClasspathElements>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
index 8bee491..1783f59 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
@@ -1,7 +1,7 @@
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
-
+
<defaultProtocol type="Servlet 3.0" />
<container qualifier="as7" default="true">
<configuration>
diff --git a/pom.xml b/pom.xml
index d6489ef..da1506f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -153,6 +153,7 @@
<arquillian.version>1.0.3.Final</arquillian.version>
<arquillian.jboss.container.version>7.2.0.Final</arquillian.jboss.container.version>
<shrinkwrap-resolver.version>2.0.0-alpha-7</shrinkwrap-resolver.version>
+ <xnio.version>3.0.7.GA</xnio.version> <!-- needed in jndi-access tests to talk to the managed AS -->
<xercesImpl.version>2.9.1-jbossas-2</xercesImpl.version> <!-- see BZ-820629 and CVE-2009-2625 -->
<opencsv.version>1.8</opencsv.version>
<commons-httpclient.version>3.0.1</commons-httpclient.version>
@@ -725,6 +726,12 @@
</dependency>
<dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-arquillian-container-remote</artifactId>
+ <version>${arquillian.jboss.container.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<version>${jacoco.version}</version>
commit 2f656dc37a45c5ccdb14dbb173f55dec830acb88
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 12:20:55 2013 -0400
add API to get the data directory for the app server
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 5078d08..9a766f4 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -126,6 +126,12 @@ public class CoreJBossASClient extends JBossASClient {
return dir;
}
+ public String getAppServerDataDir() throws Exception {
+ final String[] address = { CORE_SERVICE, SERVER_ENVIRONMENT };
+ final String dir = getStringAttribute(true, "data-dir", Address.root().add(address));
+ return dir;
+ }
+
/**
* Enabled or disables the default deployment scanner.
* @param enabled the new status to be set
commit 06071e1f7f1562e86c364e0a03835a39fb241b22
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 10:40:10 2013 -0400
BZ 956388 - opps. forgot to commit this
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
index 7474b22..fe5dcf3 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
@@ -94,7 +94,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public BundleAgentService getBundleAgentService(long timeout) {
+ public BundleAgentService getBundleAgentService(Long timeout) {
return getBundleAgentService();
}
@@ -104,7 +104,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ContentAgentService getContentAgentService(long timeout) {
+ public ContentAgentService getContentAgentService(Long timeout) {
return getContentAgentService();
}
@@ -114,7 +114,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ResourceFactoryAgentService getResourceFactoryAgentService(long timeout) {
+ public ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout) {
return getResourceFactoryAgentService();
}
@@ -124,7 +124,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ConfigurationAgentService getConfigurationAgentService(long timeout) {
+ public ConfigurationAgentService getConfigurationAgentService(Long timeout) {
return getConfigurationAgentService();
}
@@ -134,7 +134,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public DiscoveryAgentService getDiscoveryAgentService(long timeout) {
+ public DiscoveryAgentService getDiscoveryAgentService(Long timeout) {
return getDiscoveryAgentService();
}
@@ -144,7 +144,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public MeasurementAgentService getMeasurementAgentService(long timeout) {
+ public MeasurementAgentService getMeasurementAgentService(Long timeout) {
return getMeasurementAgentService();
}
@@ -154,7 +154,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public OperationAgentService getOperationAgentService(long timeout) {
+ public OperationAgentService getOperationAgentService(Long timeout) {
return getOperationAgentService();
}
@@ -164,7 +164,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public SupportAgentService getSupportAgentService(long timeout) {
+ public SupportAgentService getSupportAgentService(Long timeout) {
return getSupportAgentService();
}
@@ -174,7 +174,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public DriftAgentService getDriftAgentService(long timeout) {
+ public DriftAgentService getDriftAgentService(Long timeout) {
return getDriftAgentService();
}
commit 9159de1ad8c1055dfb05fe8cb1aed1f2d73d63a3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 10:20:45 2013 -0400
BZ 956388 - autboxing got us. the API should allow for Long (not long) to allow for code to pass in long numbers or null to pick up the default
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
index c91c0a9..1f86df3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
@@ -72,37 +72,37 @@ public interface AgentClient {
BundleAgentService getBundleAgentService();
- BundleAgentService getBundleAgentService(long timeout);
+ BundleAgentService getBundleAgentService(Long timeout);
ContentAgentService getContentAgentService();
- ContentAgentService getContentAgentService(long timeout);
+ ContentAgentService getContentAgentService(Long timeout);
ResourceFactoryAgentService getResourceFactoryAgentService();
- ResourceFactoryAgentService getResourceFactoryAgentService(long timeout);
+ ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout);
DiscoveryAgentService getDiscoveryAgentService();
- DiscoveryAgentService getDiscoveryAgentService(long timeout);
+ DiscoveryAgentService getDiscoveryAgentService(Long timeout);
MeasurementAgentService getMeasurementAgentService();
- MeasurementAgentService getMeasurementAgentService(long timeout);
+ MeasurementAgentService getMeasurementAgentService(Long timeout);
OperationAgentService getOperationAgentService();
- OperationAgentService getOperationAgentService(long timeout);
+ OperationAgentService getOperationAgentService(Long timeout);
ConfigurationAgentService getConfigurationAgentService();
- ConfigurationAgentService getConfigurationAgentService(long timeout);
+ ConfigurationAgentService getConfigurationAgentService(Long timeout);
SupportAgentService getSupportAgentService();
- SupportAgentService getSupportAgentService(long timeout);
+ SupportAgentService getSupportAgentService(Long timeout);
DriftAgentService getDriftAgentService();
- DriftAgentService getDriftAgentService(long timeout);
+ DriftAgentService getDriftAgentService(Long timeout);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
index 5ef22e6..c2d4049 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
@@ -137,7 +137,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public BundleAgentService getBundleAgentService(long timeout) {
+ public BundleAgentService getBundleAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(BundleAgentService.class, timeout);
}
@@ -147,7 +147,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ContentAgentService getContentAgentService(long timeout) {
+ public ContentAgentService getContentAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ContentAgentService.class, timeout);
}
@@ -157,7 +157,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ResourceFactoryAgentService getResourceFactoryAgentService(long timeout) {
+ public ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ResourceFactoryAgentService.class, timeout);
}
@@ -167,7 +167,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public DiscoveryAgentService getDiscoveryAgentService(long timeout) {
+ public DiscoveryAgentService getDiscoveryAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(DiscoveryAgentService.class, timeout);
}
@@ -177,7 +177,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public MeasurementAgentService getMeasurementAgentService(long timeout) {
+ public MeasurementAgentService getMeasurementAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(MeasurementAgentService.class, timeout);
}
@@ -187,7 +187,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public OperationAgentService getOperationAgentService(long timeout) {
+ public OperationAgentService getOperationAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(OperationAgentService.class, timeout);
}
@@ -197,7 +197,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ConfigurationAgentService getConfigurationAgentService(long timeout) {
+ public ConfigurationAgentService getConfigurationAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ConfigurationAgentService.class, timeout);
}
@@ -207,7 +207,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public SupportAgentService getSupportAgentService(long timeout) {
+ public SupportAgentService getSupportAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(SupportAgentService.class, timeout);
}
@@ -217,7 +217,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public DriftAgentService getDriftAgentService(long timeout) {
+ public DriftAgentService getDriftAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(DriftAgentService.class, timeout);
}
commit d2330a2d819b5ad2855fe1f32dc3005ab31f8543
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Apr 25 14:52:06 2013 +0200
Discover WildFly servers as such.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
index fb328a3..9a4d5bd 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
@@ -70,6 +70,7 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
private static final String JBOSS_AS_PREFIX = "jboss-as-";
private static final String JBOSS_EAP_PREFIX = "jboss-eap-";
+ private static final String WILDFLY_PREFIX = "wildfly-";
private static final String HOME_DIR_SYSPROP = "jboss.home.dir";
@@ -467,14 +468,14 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
return detail;
}
- private String getServerAttribute(ASConnection connection, String attributeName) {
+ private <T>T getServerAttribute(ASConnection connection, String attributeName) {
Operation op = new ReadAttribute(null, attributeName);
Result res = connection.execute(op);
if (!res.isSuccess()) {
throw new InvalidPluginConfigurationException("Could not connect to remote server ["
+ res.getFailureDescription() + "]. Did you enable management?");
}
- return (String) res.getResult();
+ return (T) res.getResult();
}
// never returns null
@@ -563,7 +564,9 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
protected String determineServerVersionFromHomeDir(File homeDir) {
String version;
String homeDirName = homeDir.getName();
- if (homeDirName.startsWith(JBOSS_AS_PREFIX)) {
+ if (homeDirName.startsWith(WILDFLY_PREFIX)) {
+ version = homeDirName.substring(WILDFLY_PREFIX.length());
+ } else if (homeDirName.startsWith(JBOSS_AS_PREFIX)) {
version = homeDirName.substring(JBOSS_AS_PREFIX.length());
} else if (homeDirName.startsWith(JBOSS_EAP_PREFIX)) {
version = homeDirName.substring(JBOSS_EAP_PREFIX.length());
@@ -606,8 +609,17 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
ASConnection connection = new ASConnection(hostname, port, user, pass);
try {
String productName = getServerAttribute(connection, "product-name");
- productType = ((productName != null) && !productName.isEmpty()) ?
- JBossProductType.getValueByProductName(productName) : JBossProductType.AS;
+ if ((productName != null) && !productName.isEmpty())
+ productType = JBossProductType.getValueByProductName(productName);
+ else {
+ Integer apiVersion = getServerAttribute(connection,"management-major-version");
+ if (apiVersion==1) {
+ productType = JBossProductType.AS;
+ } else {
+ // In the future also check for other versions of WildFly via the release-version
+ productType = JBossProductType.WILDFLY8;
+ }
+ }
releaseVersion = getServerAttribute(connection, "release-version");
releaseCodeName = getServerAttribute(connection, "release-codename");
serverName = getServerAttribute(connection, "name");
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index eb86f0b..9edfb2f 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -36,7 +36,8 @@ public enum JBossProductType {
EPP("EPP", "JBoss EAP 6", "JBoss Enterprise Portal Platform 6", "Portal Platform"),
JPP("JPP", "JBoss EAP 6", "JBoss Portal Platform 6", "Portal Platform"),
// EWP("EWP", "JBoss EWP 6", "JBoss Enterprise Web Platform 6", "EWP"),
- SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP");
+ SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP"),
+ WILDFLY8("WildFly","WildFly 8" ,"WildFly Appliction Server 8" , "WildFly");
public final String SHORT_NAME;
public final String NAME;
@@ -98,7 +99,7 @@ public enum JBossProductType {
productType = JBossProductType.EAP;
} else if (slot.equals("jdg")) {
productType = JBossProductType.JDG;
- } else if (slot.equals("epp")) {//old EPP
+ } else if (slot.equals("epp")) {//old EPP
productType = JBossProductType.EPP;
} else if (slot.equals("jpp")) {//new EPP->JPP plugin
productType = JBossProductType.JPP;
@@ -108,7 +109,9 @@ public enum JBossProductType {
throw new RuntimeException("Unknown product type: " + slot);
}
} else {
- productType = JBossProductType.AS;
+ // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
+ // so we need another way to distinguish them
+ productType = determineJBossProductTypeViaHomeDirName(homeDir);
}
return productType;
@@ -119,6 +122,8 @@ public enum JBossProductType {
String homeDirName = homeDir.getName();
if (homeDirName.contains("-as-")) {
productType = JBossProductType.AS;
+ } else if (homeDirName.contains("wildfly")) {
+ productType = JBossProductType.WILDFLY8;
} else if (homeDirName.contains("-eap-")) {
productType = JBossProductType.EAP;
} else if (homeDirName.contains("-jdg-")||(homeDirName.contains("datagrid-server"))) {
10 years, 11 months
[rhq] Branch 'nightly/rhq.jon' - 105 commits - .classpath etc/rhq-ircBot etc/samples .gitignore .mailmap modules/common modules/core modules/enterprise modules/integration-tests modules/plugins pom.xml
by Simeon Pinder
.classpath | 4
.gitignore | 2
.mailmap | 1
etc/rhq-ircBot/pom.xml | 15
etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java | 270
etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java | 375 +
etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks |binary
etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties | 2
etc/samples/embedded-ext-plugin/pom.xml | 72
etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java | 58
etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml | 21
etc/samples/skeleton-plugin/pom.xml | 99
etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java | 47
etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java | 61
etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml | 20
etc/samples/skinny-platform/pom.xml | 60
etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java | 39
etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java | 67
etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml | 18
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java | 50
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java | 4
modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java | 140
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java | 78
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java | 9
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java | 9
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java | 113
modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java | 27
modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java | 40
modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java | 5
modules/core/domain/src/main/resources/META-INF/persistence.xml | 8
modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java | 92
modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java | 275
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java | 2
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java | 63
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java | 40
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java | 32
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java | 33
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java | 212
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java | 6
modules/enterprise/agent/src/main/resources/agent-configuration.xml | 15
modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java | 7
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java | 11
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java | 153
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java | 9
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java | 42
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java | 72
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java | 31
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java | 6
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java | 32
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java | 214
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java | 203
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java | 31
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java | 358 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java | 383 +
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java | 8
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java | 34
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java | 340 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java | 39
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java | 137
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java | 35
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java | 44
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java | 146
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java | 303 -
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java | 34
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java | 159
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java | 137
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java | 23
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java | 49
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java | 16
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java | 13
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java | 18
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml | 3
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java | 9
modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java | 7
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml | 14
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 89
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 5
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 5
modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html | 18
modules/enterprise/gui/coregui/src/main/webapp/css/charts.css | 7
modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css | 128
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png |binary
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png |binary
modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png |binary
modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js | 2855 ++++++++--
modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js | 32
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java | 15
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java | 15
modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml | 2
modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml | 4
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml | 2
modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml | 4
modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js | 2
modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java | 16
modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh | 3
modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf | 9
modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh | 2
modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc | 6
modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml | 31
modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java | 66
modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java | 4
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java | 30
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java | 17
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java | 86
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java | 323 -
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java | 4
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java | 33
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java | 4
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java | 9
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java | 5
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java | 18
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java | 23
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java | 54
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java | 52
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java | 30
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java | 39
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java | 209
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java | 12
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java | 231
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java | 124
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java | 41
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java | 26
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java | 75
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java | 210
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java | 102
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java | 7
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java | 57
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java | 24
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java | 97
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java | 30
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java | 432 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java | 120
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java | 21
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 6
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java | 756 ++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java | 22
modules/enterprise/server/plugins/alert-snmp/pom.xml | 32
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java | 59
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java | 32
modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java | 38
modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml | 36
modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java | 106
modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java | 378 +
modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml | 32
modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java | 4
modules/integration-tests/jndi-access/jndi-access-test/pom.xml | 47
modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml | 2
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java | 9
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java | 106
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java | 94
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java | 129
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java | 44
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java | 188
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java | 269
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java | 2
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java | 4
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java | 21
modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java | 9
modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java | 186
modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml | 19
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java | 50
modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java | 2
modules/plugins/jboss-as-7/pom.xml | 12
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java | 13
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java | 25
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java | 86
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java | 39
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java | 43
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java | 10
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java | 8
modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java | 19
modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml | 50
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java | 33
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java | 14
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java | 17
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java | 19
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java | 74
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java | 239
modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java | 24
modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java | 2
pom.xml | 7
233 files changed, 10757 insertions(+), 4522 deletions(-)
New commits:
commit 45c43c4848b6672ccf9ffc7784ba671c6b840ae4
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:32:46 2013 -0400
Moving pom versions back to 4.7.0.JON for ALPHA build.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index dbb487d..4aae357 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index efe6d1f..434edad 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 138e9ca..86baa5a 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 5afdead..0faef44 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 0beb20b..5949978 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index b8c1682..cbb58f3 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index 6dac77b..7ce384f 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 088e268..da1d138 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index fe5f377..f4b2afa 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 258d050..33e48b1 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 67b02a8..66df7dd 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index 231ab67..bbe0954 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index 4ed7bca..b560968 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index 7adcd3b..c5184a1 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 1fb2161..62028e4 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index cc040f8..b30f82e 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 776459d..8c36237 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index dc21aad..52e1956 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 46fe305..86a3e7e 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index 8060a89..adf5bd4 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 9c801de..2ed4c26 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 3c070a9..e03ac78 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 18fa318..97ed3ab 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index 0374729..b2c1184 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index 99c875d..0820f4b 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index 426d298..ecdde93 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c41a8f4..9765a55 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index cdc3b9b..2bd8b52 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index 2d7093d..c832b41 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 67ed9a8..329f7fb 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index d5b7643..91ab077 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index 8148262..9ade65f 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index a140a9c..539cff8 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index cb7dd3a..3dea516 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 018a802..57c01e8 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index d2998cc..8b742ff 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 638bccd..0dae4ac 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index c9aa075..0cd7bf7 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 33e330e..10a7cd8 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 3fad441..0e5c315 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index dec19d0..40ed02c 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index cba50db..49e0186 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index 6db40f2..a087cb1 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 7bf574e..bbd87da 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index 268af3a..b584947 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index acc09aa..c376943 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index a58f1ca..4c47992 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index dc69d9e..385978a 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index f186d70..d6e97a0 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 3e69ded..560de86 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 867ebe1..dd10dec 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 23d8e94..9ee8e93 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 5e4e076..460342b 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index 84e34c4..c0a0bae 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index ea9bd42..1bd8378 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index a2102a3..5252acc 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index bd5f656..ee5adda 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index 934cb7e..8c7670d 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index 28d1d56..80d32e7 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 4338526..6438e21 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 21ec5f7..b2ecdbe 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index a6c054a..cb37a34 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index f84398b..12ac31b 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index d4d2564..3e43ea6 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 648b451..7784473 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 6f56e82..5c79143 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index 21bb689..dde366f 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 7111543..6429931 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index 6ab0964..b36fcbb 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 32ffc76..6285905 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index 2a75e07..de6f9c4 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index dc862db..7e75407 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index bb1740d..19bc8b1 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 06da613..32d9a39 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index 6f8ac10..c97e216 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 9c60e30..48fd5ea 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index b2b741e..ab869f2 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index d4f7715..fc69668 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 014420b..6377787 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 7152fc3..286398c 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 00e558b..2f0d910 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index f2f2455..e63e38e 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index 6f36514..a7ed4cc 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index 8772058..84d6d04 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index ecebf6c..a853c5e 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index c5a4a41..2ef0b85 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index baf0801..0567602 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index bf4ca3d..24f015d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index a9d7296..ca3d81f 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 48808ac..0b0c363 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index 6ded494..5e1f84c 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index d11992a..777f236 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index 7e5f521..ac50627 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index bca2fe4..8debbc4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index 2809e95..d74b6cc 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 75a98a4..780b6e3 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 380f6e6..cead04e 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index ada89b3..d68d451 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 37ffe0e..2e80e03 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index a17a3d8..79f789b 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index 9424397..f37463b 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 3aa5463..cd8f563 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 03349f8..2292a6f 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index 8a5f0e6..7da6b89 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index a1c3353..8a77511 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index d8325e4..1618ff0 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index adee980..d2dc58a 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index f587112..0a159b5 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index d1f3e43..b31fd66 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 93a915f..34e2f82 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index b043e7b..daaa104 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index f2e6f8a..7dc2147 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index d85e7e3..397026c 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index b792d26..155912f 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 837852d..896a15d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 3828a6a..6976d9b 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 864f675..5ac7010 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 094f451..1dee28d 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index 54b9f53..e8fe102 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 572851e..22d5822 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 6b663ff..3b6bd23 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index 68af26a..f479b37 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index ed93d10..a55e980 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 5653d69..4811181 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index f852e8a..8d330c6 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index e28148c..48bd3e1 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 0e27179..8b95b87 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 12ae83c..45c5ae5 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 26d37b3..b2f56ff 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 6bf549f..0805240 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 968a154..5b0231a 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 20e41c4..8eb6a1b 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index d31500b..9cf27a2 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 36ab8be..8eb8486 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index 74d740b..cca0dfb 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index e0a216e..e99a393 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 3891b84..6ccc01b 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index eb97008..2848dbb 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 45c2544..928ab6c 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 63eb6ae..f590ca2 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index de510c5..17d502f 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 8f4cf31..0e18cc9 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index c343deb..3407cad 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index b46ee9e..314c512 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.8.0-SNAPSHOT</version>
+ <version>4.7.0.JON</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 914ec1e15b09a712f18ce46e4c3124e1a8baa6d4
Merge: 3368ace 2eef3b4
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:31:15 2013 -0400
Merge branch 'master' into nightly/rhq.jon
Conflicts:
modules/plugins/jboss-as-7/pom.xml
commit 3368acebc21e2a43a981379774d319781daabffa
Author: Simeon Pinder <spinder(a)redhat.com>
Date: Thu May 30 04:27:37 2013 -0400
Temporarily move the pom version to minimize auto commit issues.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index 4aae357..dbb487d 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index 434edad..efe6d1f 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 86baa5a..138e9ca 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 0faef44..5afdead 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 5949978..0beb20b 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index cbb58f3..b8c1682 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index 7ce384f..6dac77b 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index da1d138..088e268 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index f4b2afa..fe5f377 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 33e48b1..258d050 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 66df7dd..67b02a8 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index bbe0954..231ab67 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index b560968..4ed7bca 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index c5184a1..7adcd3b 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 62028e4..1fb2161 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index b30f82e..cc040f8 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index 8c36237..776459d 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index 52e1956..dc21aad 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 86a3e7e..46fe305 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index adf5bd4..8060a89 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 2ed4c26..9c801de 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index e03ac78..3c070a9 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 97ed3ab..18fa318 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index b2c1184..0374729 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index 0820f4b..99c875d 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index ecdde93..426d298 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 9765a55..c41a8f4 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index 2bd8b52..cdc3b9b 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index c832b41..2d7093d 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 329f7fb..67ed9a8 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index 91ab077..d5b7643 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index 9ade65f..8148262 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 539cff8..a140a9c 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 3dea516..cb7dd3a 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 57c01e8..018a802 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index 8b742ff..d2998cc 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 0dae4ac..638bccd 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index 0cd7bf7..c9aa075 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 10a7cd8..33e330e 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 0e5c315..3fad441 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 40ed02c..dec19d0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index 49e0186..cba50db 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index a087cb1..6db40f2 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index bbd87da..7bf574e 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index b584947..268af3a 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index c376943..acc09aa 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 4c47992..a58f1ca 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index 385978a..dc69d9e 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index d6e97a0..f186d70 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 560de86..3e69ded 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index dd10dec..867ebe1 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 9ee8e93..23d8e94 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 460342b..5e4e076 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index c0a0bae..84e34c4 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index 1bd8378..ea9bd42 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index 5252acc..a2102a3 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index ee5adda..bd5f656 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index 8c7670d..934cb7e 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index 80d32e7..28d1d56 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 6438e21..4338526 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index b2ecdbe..21ec5f7 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index cb37a34..a6c054a 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 87a66cc..b933e91 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index 3e43ea6..d4d2564 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 7784473..648b451 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 5c79143..6f56e82 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index dde366f..21bb689 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 6429931..7111543 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index b36fcbb..6ab0964 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 6285905..32ffc76 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index de6f9c4..2a75e07 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 7e75407..dc862db 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 19bc8b1..bb1740d 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 32d9a39..06da613 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index c97e216..6f8ac10 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 48fd5ea..9c60e30 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index ab869f2..b2b741e 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index fc69668..d4f7715 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 6377787..014420b 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 286398c..7152fc3 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 2f0d910..00e558b 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index e63e38e..f2f2455 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index a7ed4cc..6f36514 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index 84d6d04..8772058 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index a853c5e..ecebf6c 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index 2ef0b85..c5a4a41 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index 0567602..baf0801 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index 24f015d..bf4ca3d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index ca3d81f..a9d7296 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 59becbb..7ae77d3 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index 5e1f84c..6ded494 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index 777f236..d11992a 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index ac50627..7e5f521 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index 8debbc4..bca2fe4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index d74b6cc..2809e95 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 780b6e3..75a98a4 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index cead04e..380f6e6 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index d68d451..ada89b3 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 2e80e03..37ffe0e 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index 79f789b..a17a3d8 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index f37463b..9424397 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index cd8f563..3aa5463 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 2292a6f..03349f8 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index 7da6b89..8a5f0e6 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 8a77511..a1c3353 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index 1618ff0..d8325e4 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index d2dc58a..adee980 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 0a159b5..f587112 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index b31fd66..d1f3e43 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 34e2f82..93a915f 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index daaa104..b043e7b 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 7dc2147..f2e6f8a 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 75e7b74..0b36f29 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index 155912f..b792d26 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index 896a15d..837852d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 6976d9b..3828a6a 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 5ac7010..864f675 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 1dee28d..094f451 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index e8fe102..54b9f53 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 22d5822..572851e 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 3b6bd23..6b663ff 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index f479b37..68af26a 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index a55e980..ed93d10 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 4811181..5653d69 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 8d330c6..f852e8a 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index 48bd3e1..e28148c 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 8b95b87..0e27179 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 45c5ae5..12ae83c 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index b2f56ff..26d37b3 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index 0805240..6bf549f 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 5b0231a..968a154 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 8eb6a1b..20e41c4 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 9cf27a2..d31500b 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 8eb8486..36ab8be 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index cca0dfb..74d740b 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index e99a393..e0a216e 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index 6ccc01b..3891b84 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index 2848dbb..eb97008 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 928ab6c..45c2544 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index f590ca2..63eb6ae 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index 17d502f..de510c5 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 0e18cc9..8f4cf31 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index 3407cad..c343deb 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index 9b29fab..a5588bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0.JON</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 2eef3b4fcd05fc1b248ab3c95fbc115e3758079d
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed May 29 13:48:05 2013 +0200
[BZ 967542] - UI shows confusing units when editing Availability Duration alert condition type
Now if user iserts e.g. 90 mins and reopens the dialog, it won't display
1.5 hours anymore, but 90 mins as expected.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
index 104b84c..6c41897 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
@@ -38,6 +38,7 @@ import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
@@ -238,26 +239,17 @@ public class DurationItem extends CanvasItem {
this.form.setValue(FIELD_VALUE, formattedOutput);
setValue(formattedOutput);
} else {
- String valueWithUnits = MeasurementConverterClient.format((double) longValue,
- MeasurementUnits.MILLISECONDS, true);
- String[] chunks = valueWithUnits.split(" ");
- String value = chunks[0];
- if (value.endsWith(".0")) {
- value = value.substring(0, value.indexOf(".0"));
+ MeasurementNumericValueAndUnits valueWithUnits;
+ if (longValue % HOUR_IN_MILLIS == 0) {
+ valueWithUnits = MeasurementConverterClient.fit((double) longValue, MeasurementUnits.MILLISECONDS,
+ MeasurementUnits.HOURS, MeasurementUnits.HOURS);
+ } else {
+ valueWithUnits = MeasurementConverterClient.fit((double) longValue, MeasurementUnits.MILLISECONDS,
+ MeasurementUnits.MINUTES, MeasurementUnits.MINUTES);
}
- this.form.setValue(FIELD_VALUE, value);
- String units = chunks[1];
SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
- if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.SECONDS).equals(units)) {
- unitsItem.setValue(TimeUnit.SECONDS.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.MINUTES)
- .equals(units)) {
- unitsItem.setValue(TimeUnit.MINUTES.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.HOURS).equals(units)) {
- unitsItem.setValue(TimeUnit.HOURS.name().toLowerCase());
- } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.DAYS).equals(units)) {
- unitsItem.setValue(TimeUnit.DAYS.name().toLowerCase());
- }
+ this.form.setValue(FIELD_VALUE, valueWithUnits.getValue().intValue());
+ unitsItem.setValue(valueWithUnits.getUnits().name().toLowerCase());
}
}
commit 2e3f2b2e2f8db3894fea0777508e79e4bf3817cd
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue May 28 14:32:14 2013 -0400
BZ 967990 the installer now turns off the admin console
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 8cef6e1..eaf6f66 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -40,12 +40,33 @@ public class CoreJBossASClient extends JBossASClient {
public static final String SCANNER = "scanner";
public static final String EXTENSION = "extension";
public static final String MODULE = "module";
+ public static final String CORE_SERVICE_MGMT = "management";
+ public static final String MGMT_INTERFACE = "management-interface";
+ public static final String MGMT_INTERFACE_HTTP = "http-interface";
public CoreJBossASClient(ModelControllerClient client) {
super(client);
}
/**
+ * Allows the caller to turn on or off complete access for the app server's admin console.
+ *
+ * @param enableFlag true if the admin console enabled and visible; false if you want to prohibit all access to the admin console
+ * @throws Exception
+ */
+ public void setEnableAdminConsole(boolean enableFlag) throws Exception {
+ // /core-service=management/management-interface=http-interface/:write-attribute(name=console-enabled,value=false)
+ final Address address = Address.root()
+ .add(CORE_SERVICE, CORE_SERVICE_MGMT, MGMT_INTERFACE, MGMT_INTERFACE_HTTP);
+ final ModelNode req = createWriteAttributeRequest("console-enabled", Boolean.toString(enableFlag), address);
+ final ModelNode response = execute(req);
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return;
+ }
+
+ /**
* Given a string with possible ${x} expressions in it, this will resolve that expression
* using system property values that are set within the AS JVM itself. If the string
* to resolve has no expressions, or has no expressions that are resolveable, the expression
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 0b9c078..bb42d4a 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -1034,6 +1034,9 @@ public class InstallerServiceImpl implements InstallerService {
// we don't want to the JBossAS welcome screen; turn it off
new WebJBossASClient(mcc).setEnableWelcomeRoot(false);
+ // we don't want users to access the admin console
+ new CoreJBossASClient(mcc).setEnableAdminConsole(false);
+
} catch (Exception e) {
log("deployServices failed", e);
throw new Exception("Failed to deploy services: " + ThrowableUtil.getAllMessages(e));
commit 57333dd7c4a683fe39bfcf68ea706cbfa6feded9
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue May 28 18:40:38 2013 +0200
[BZ 967542] - UI shows confusing units when editing Availability Duration alert condition type
I improved the DurationItem component to use internally the SelectItem
instead of ComboBoxItem. When using ComboBoxItem, it was possible to
write to the combobox and this is something that shouldn't happen in
this component because the unit types should be fixed. The DurationItem
is also used from the operation tab view, but no reggression was
introduced by this commit in this view.
Modifying also the DurationItem.setAndFormatValue() to populate the time correctly when
!isReadOnly.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
index 8fe6d4b..0a2627c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
@@ -65,7 +65,6 @@ import org.rhq.enterprise.gui.coregui.client.components.form.DurationItem;
import org.rhq.enterprise.gui.coregui.client.components.form.NumberWithUnitsValidator;
import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
import org.rhq.enterprise.gui.coregui.client.components.form.TimeUnit;
-import org.rhq.enterprise.gui.coregui.client.components.form.UnitType;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.enterprise.gui.coregui.client.util.measurement.MeasurementParser;
import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -959,7 +958,7 @@ public class ConditionEditor extends EnhancedVLayout {
durationValue.setTooltip(MSG.view_alert_definition_condition_editor_availabilityDuration_tooltip_duration());
durationValue.setHoverWidth(200);
if (editMode) {
- durationValue.setValue(Integer.parseInt(existingCondition.getOption()), UnitType.TIME);
+ durationValue.setAndFormatValue(Integer.parseInt(existingCondition.getOption()) * 1000L);
}
durationValue.setShowIfCondition(ifFunc);
formItems.add(durationValue);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index 25742f5..e24d1b4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -211,6 +211,8 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
public void execute(Boolean value) {
if (value) {
save();
+ } else {
+ unregisterHandler();
}
}
});
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
index 633188a..104b84c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/form/DurationItem.java
@@ -29,17 +29,19 @@ import java.util.TreeSet;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.IntegerItem;
+import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
+import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.FormUtility;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
import org.rhq.enterprise.gui.coregui.client.util.TypeConversionUtility;
/**
@@ -142,7 +144,7 @@ public class DurationItem extends CanvasItem {
}
});
- ComboBoxItem unitsItem = new ComboBoxItem(FIELD_UNITS);
+ SelectItem unitsItem = new SelectItem(FIELD_UNITS);
unitsItem.setShowTitle(false);
LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
@@ -230,10 +232,33 @@ public class DurationItem extends CanvasItem {
if (longValue < 0) {
throw new IllegalArgumentException("negative time period " + longValue);
}
- String formattedOutput = formatMilliseconds(longValue);
- this.unitType = UnitType.TIME;
- this.form.setValue(FIELD_VALUE, formattedOutput);
- setValue(formattedOutput);
+ if (isReadOnly) {
+ String formattedOutput = formatMilliseconds(longValue);
+ this.unitType = UnitType.TIME;
+ this.form.setValue(FIELD_VALUE, formattedOutput);
+ setValue(formattedOutput);
+ } else {
+ String valueWithUnits = MeasurementConverterClient.format((double) longValue,
+ MeasurementUnits.MILLISECONDS, true);
+ String[] chunks = valueWithUnits.split(" ");
+ String value = chunks[0];
+ if (value.endsWith(".0")) {
+ value = value.substring(0, value.indexOf(".0"));
+ }
+ this.form.setValue(FIELD_VALUE, value);
+ String units = chunks[1];
+ SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
+ if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.SECONDS).equals(units)) {
+ unitsItem.setValue(TimeUnit.SECONDS.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.MINUTES)
+ .equals(units)) {
+ unitsItem.setValue(TimeUnit.MINUTES.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.HOURS).equals(units)) {
+ unitsItem.setValue(TimeUnit.HOURS.name().toLowerCase());
+ } else if (MeasurementConverterClient.getMeasurementUnitAbbreviation(MeasurementUnits.DAYS).equals(units)) {
+ unitsItem.setValue(TimeUnit.DAYS.name().toLowerCase());
+ }
+ }
}
/**
@@ -474,7 +499,7 @@ public class DurationItem extends CanvasItem {
}
private TimeUnit getInputTimeUnit() {
- ComboBoxItem unitsItem = (ComboBoxItem) this.form.getItem(FIELD_UNITS);
+ SelectItem unitsItem = (SelectItem) this.form.getItem(FIELD_UNITS);
String unitString = unitsItem.getValueAsString(); // this will always be non-null
TimeUnit unit;
try {
commit ecb57a4e3e147e18b000388a2baec312c31c7bf2
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue May 28 12:36:26 2013 -0400
Make sure sub-queries used for updates do not include implicit
paging/sorting.
Also, make a small change to test cleanup in related test class.
Note: Fix by lkrejci
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
index 9febeb8..24bcc84 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/test/MeasurementScheduleManagerTest.java
@@ -342,10 +342,15 @@ public class MeasurementScheduleManagerTest extends AbstractMeasurementScheduleM
try {
if (null != em) {
em.flush();
- getTransactionManager().commit();
}
} catch (Throwable t) {
-
+ // best effort
+ }
+ try {
+ getTransactionManager().commit();
+ } catch (Throwable t) {
+ // best effort
}
}
+
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
index 2e4eeda..d53a037 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementScheduleManagerBean.java
@@ -820,6 +820,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
*/
private void markResources(EntityContext context, int agentId) {
ResourceCriteria criteria = new ResourceCriteria();
+ criteria.clearPaging(); //important to avoid setting the ordering in the generated query
if (context.type == EntityContext.Type.Resource) {
criteria.addFilterId(context.resourceId);
} else if (context.type == EntityContext.Type.ResourceGroup) {
@@ -832,7 +833,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
try {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(criteria);
- ;
+
generator.alterProjection("resource.id");
String resourceSubQuery = generator.getParameterReplacedQuery(false);
@@ -848,7 +849,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
markResourceQuery.setParameter("now", System.currentTimeMillis());
int affectedRows = markResourceQuery.executeUpdate();
if (log.isDebugEnabled()) {
- log.debug("Marked " + affectedRows + " for future measurement scheudle update");
+ log.debug("Marked " + affectedRows + " for future measurement schedule update");
}
} catch (Throwable t) {
log.error("Could not notify agents of updates", t);
@@ -877,6 +878,7 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
}
MeasurementScheduleCriteria criteria = new MeasurementScheduleCriteria();
+ criteria.clearPaging(); //important to avoid setting the ordering in the generated query
if (context.type == EntityContext.Type.Resource) {
criteria.addFilterResourceId(context.resourceId);
} else if (context.type == EntityContext.Type.ResourceGroup) {
@@ -1607,4 +1609,4 @@ public class MeasurementScheduleManagerBean implements MeasurementScheduleManage
// }
// }
-}
+}
\ No newline at end of file
commit 2f15379bb357495c558b05fb271e247fa1681d01
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue May 28 17:36:13 2013 +0200
Bug 885686 - Tomcat web application configuration form allows save without Config File required field
It's not a Tomcat specific issue. We had a problem in *EditView classes: the check to enable/disable the save button was only based on the invalid properties set having been changed. Now it also looks at the set being empty or not.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
index c7604c4..a428a22 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.drift;
@@ -190,8 +190,10 @@ public class DriftDefinitionEditView extends EnhancedVLayout implements Property
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
index dd69993..0ccc445 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/drift/DriftDefinitionTemplateEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.drift;
@@ -178,8 +178,10 @@ public class DriftDefinitionTemplateEditView extends EnhancedVLayout implements
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
index 55ac8fd..d0c440f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/GroupResourceConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration;
@@ -261,8 +261,10 @@ public class GroupResourceConfigurationEditView extends EnhancedVLayout implemen
Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
index b6e892f..8680cc4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/GroupPluginConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.inventory;
@@ -256,8 +256,10 @@ public class GroupPluginConfigurationEditView extends EnhancedVLayout implements
Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
index ae7fde1..e3b119c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configuration;
@@ -222,8 +222,10 @@ public class ResourceConfigurationEditView extends EnhancedVLayout implements Pr
.toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
index fd374eb..63245a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationEditView.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory;
@@ -171,8 +171,10 @@ public class PluginConfigurationEditView extends EnhancedVLayout implements Prop
Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
index 128a540..bdbe026 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestConfigurationView.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010-2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.test.configuration;
@@ -111,8 +110,10 @@ public class TestConfigurationView extends EnhancedVLayout implements PropertyVa
EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
index 483e71c..00da718 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/test/configuration/TestGroupConfigurationView.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.test.configuration;
@@ -112,8 +111,10 @@ public class TestGroupConfigurationView extends EnhancedVLayout implements Prope
EnumSet.of(Message.Option.Transient, Message.Option.Sticky));
}
messageCenter.notify(message);
- } else {
+ } else if (event.getInvalidPropertyNames().isEmpty()) {
this.saveButton.enable();
+ } else {
+ this.saveButton.disable();
}
}
commit eeffaed93e68612eb6a88226479702d4f373e510
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue May 28 03:11:56 2013 +0200
[BZ 967622 - Server CLI script can't require modules from rhq://downloads]
This was primarily caused by a new permission required by EAP 6.1 we've
switched to. To access the ModelControllerClient, the code now needs a
RuntimePermission("canAccessModelController").
We need the ModelControllerClient when determining the EAR installation
dir, which we in turn need when determining where to locate the scripts
in the "rhq://downloads" location. This is done while running a script,
which is done in a restricted access control context which does not and
should not have that permission.
The minimal fix is to wrap the getting of the ModelControllerClient in a
privileged action but some more "defensive" code was added in the
RhqDownloadScriptSourceProvider, too, to guard against different times it
might get instantiated during the script execution.
Javadocs were updated to warn about the security considerations when
writing a script source provider available on the server side.
diff --git a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
index 4c6756f..87241ef 100644
--- a/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
+++ b/modules/enterprise/binding/src/main/java/org/rhq/bindings/script/BaseRhqSchemeScriptSourceProvider.java
@@ -55,8 +55,11 @@ public abstract class BaseRhqSchemeScriptSourceProvider implements ScriptSourceP
* The base implementation of the {@link #getScriptSource(URI)} method
* only checks that the scheme of the URI is "rhq" and that the scheme
* specific part starts with "//".
- *
- * @param scriptUri
+ * <p/>
+ * Please follow the general suggestions mentioned in {@link ScriptSourceProvider#getScriptSource(java.net.URI)}
+ * docs.
+ *
+ * @param scriptUri the URI to load the script from
* @return the reader of the script or null if the script could not be
* found using the URI
*
diff --git a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
index e65f793..fb0f606 100644
--- a/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
+++ b/modules/enterprise/scripting/api/src/main/java/org/rhq/scripting/ScriptSourceProvider.java
@@ -29,14 +29,26 @@ import java.net.URI;
* <p>
* Implementations of this interface can be located using the {@link ScriptSourceProviderFactory}
* if they are registered in META-INF/services.
- *
+ * <p/>
+ * Note that instances of this class can be created and called in an access control context with limited privileges.
+ * If you need to make safe calls that require privileges not granted to a script run in the RHQ server (by default this
+ * is determined by the {@code org.rhq.bindings.StandardScriptPermissions} class), make sure to call such actions with
+ * elevated permissions through
+ * {@link java.security.AccessController#doPrivileged(java.security.PrivilegedExceptionAction)} or any of its
+ * derivatives.
+ * <p/>
+ * For example JNDI look-ups are not allowed by default for the scripts, so if your provider needs to perform some
+ * JNDI lookups to locate the script to include, you need to wrap any code that does a JNDI look-up as above.
+ *
* @author Lukas Krejci
*/
public interface ScriptSourceProvider {
/**
* Returns the reader of the source of the script specified by given location.
- *
+ * <p/>
+ * Review the class description for the security considerations.
+ *
* @param location the location of the script
* @return the reader of the script source or null if it could not be found
*/
diff --git a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
index 1cbbe39..23e8fb5 100644
--- a/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
+++ b/modules/enterprise/server/client-api/src/main/java/org/rhq/enterprise/client/RhqDownloadsScriptSourceProvider.java
@@ -26,6 +26,11 @@ import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.Callable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -45,20 +50,67 @@ public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceP
private CoreServerMBean coreServer;
+ /**
+ * A bunch of methods optionally enclosed in privileged actions to ensure that we can access the information
+ * inside RHQ server even though it might not be accessible in the access control context the scripts run in
+ * in the RHQ server.
+ */
+ private static class SecurityActions {
+ private SecurityActions() {
+
+ }
+
+ private static CoreServerMBean lookupCoreServer() {
+ if (System.getSecurityManager() == null) {
+ return LookupUtil.getCoreServer();
+ } else {
+ return AccessController.doPrivileged(new PrivilegedAction<CoreServerMBean>() {
+ @Override
+ public CoreServerMBean run() {
+ return LookupUtil.getCoreServer();
+ }
+ });
+ }
+ }
+
+ private static File getDownloadDir(final CoreServerMBean coreServer) {
+ File earDeployDir;
+ if (System.getSecurityManager() == null) {
+ earDeployDir = coreServer.getEarDeploymentDir();
+ } else {
+ earDeployDir = AccessController.doPrivileged(new PrivilegedAction<File>() {
+ @Override
+ public File run() {
+ return coreServer.getEarDeploymentDir();
+ }
+ });
+ }
+ File downloadDir = new File(earDeployDir, "rhq-downloads");
+ return downloadDir;
+ }
+ }
+
public RhqDownloadsScriptSourceProvider() {
- this(LookupUtil.getCoreServer());
+ //we need to do a safe JNDI lookup, but we may run in unprivileged context...
+ this(SecurityActions.lookupCoreServer());
}
-
+
+ /**
+ * This is meant only for testing purposes.
+ *
+ * @param coreServerMBean the CoreServer MBean to use
+ */
public RhqDownloadsScriptSourceProvider(CoreServerMBean coreServerMBean) {
super(AUTHORITY);
this.coreServer = coreServerMBean;
}
-
+
@Override
protected Reader doGetScriptSource(URI scriptUri) {
String path = scriptUri.getPath().substring(1); //remove the leading /
- File downloadsDir = getDownloadHomeDir();
+ //We're going to be doing an MBean call here which the scripts don't have privs for by default
+ File downloadsDir = SecurityActions.getDownloadDir(coreServer);
File scriptDownloads = new File(downloadsDir, "script-modules");
File file = new File(scriptDownloads, path);
@@ -69,10 +121,4 @@ public class RhqDownloadsScriptSourceProvider extends BaseRhqSchemeScriptSourceP
return null;
}
}
-
- private File getDownloadHomeDir() {
- File earDeployDir = this.coreServer.getEarDeploymentDir();
- File downloadDir = new File(earDeployDir, "rhq-downloads");
- return downloadDir;
- }
}
diff --git a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
index e62dd32..1b366ba 100644
--- a/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
+++ b/modules/enterprise/server/client-api/src/test/java/org/rhq/enterprise/client/test/RhqDownloadsScriptSourceProviderTest.java
@@ -85,8 +85,8 @@ public class RhqDownloadsScriptSourceProviderTest {
try {
String contents = StreamUtil.slurp(rdr);
assertEquals(contents, EXPECTED_CONTENTS, "Unexpected script loaded");
- } finally {
- rdr.close();
+ } finally {
+ StreamUtil.safeClose(rdr);
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
index 9a60f12..b74b704 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
@@ -22,6 +22,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
@@ -69,6 +71,24 @@ public class CoreServer implements CoreServerMBean {
*/
private static final String PROP_BUILD_DATE = "Build-Date";
+ private static class SecurityActions {
+ private SecurityActions() {
+
+ }
+
+ private static ModelControllerClient getModelControllerClient() {
+ if (System.getSecurityManager() == null) {
+ return ManagementService.getClient();
+ } else {
+ return AccessController.doPrivileged(new PrivilegedAction<ModelControllerClient>() {
+ @Override
+ public ModelControllerClient run() {
+ return ManagementService.getClient();
+ }
+ });
+ }
+ }
+ }
private Properties buildProps;
private Date bootTime;
@@ -136,7 +156,10 @@ public class CoreServer implements CoreServerMBean {
@Override
public File getEarDeploymentDir() {
- ModelControllerClient mcc = ManagementService.getClient();
+ //Getting model controller client requires privs our callers might not have, but we want to provide this
+ //function even to them.
+ ModelControllerClient mcc = SecurityActions.getModelControllerClient();
+
try {
DeploymentJBossASClient client = new DeploymentJBossASClient(mcc);
String earPath = client.getDeploymentPath(RHQConstants.EAR_FILE_NAME);
@@ -229,4 +252,4 @@ public class CoreServer implements CoreServerMBean {
return buildProps;
}
-}
\ No newline at end of file
+}
commit ff37cd971a73a9fefc4024f5022aff85b7b90b90
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 23:29:46 2013 -0400
remove use of method not supported by GWT
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index d8552de..f398020 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -179,7 +179,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.sortId = sortId;
} else {
- throw new UnsupportedOperationException("ID sort is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("ID sort is not supported by supported by this class");
}
}
@@ -188,7 +188,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.filterId = filterId;
} else {
- throw new UnsupportedOperationException("ID filter is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("ID filter is not supported by this class");
}
}
@@ -197,7 +197,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
} else {
- throw new UnsupportedOperationException("IDS filter is not supported by " + this.getClass().getSimpleName());
+ throw new UnsupportedOperationException("IDS filter is not supported by this class");
}
}
commit 471b8a20f984f79d448acf58c01ec8c38cee8e67
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 19:45:41 2013 -0400
Bug 966665
- Criteria queries with paging and sorting on non unique fields may return same item on different pages
All paged criteria queries now apply ID as the least significant
ordering field (see exceptions below). Since ID is unique, this ensures
that queries for pages always return the same ordering of rows.
ID will not be automatically appended as an ordering field if:
- the paging is unlimited (i.e. no pagesize, all rows returned)
- the Criteria class does not support an ID sort
- the caller has set the Criteria class instance to not support the ID sort
- ID is already specified as an ordering field
- the max number of ordering fields has already been set (3)
Note that CriteriaQuery has had its support for implicit ID sorting removed,
as the new mechanism, which moves support to the CriteriaQueryGenerator,
replaces it.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index 2dde3a4..d8552de 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -109,6 +109,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
private List<Permission> requiredPermissions;
private boolean strict;
private Restriction restriction = null;
+ private boolean supportsAddSortId = true;
protected Map<String, String> filterOverrides;
protected Map<String, String> sortOverrides;
@@ -173,16 +174,54 @@ public abstract class Criteria implements Serializable, BaseCriteria {
}
public void addSortId(PageOrdering sortId) {
- addSortField("id");
- this.sortId = sortId;
+ if (isSupportsAddSortId()) {
+ addSortField("id");
+ this.sortId = sortId;
+
+ } else {
+ throw new UnsupportedOperationException("ID sort is not supported by " + this.getClass().getSimpleName());
+ }
}
public void addFilterId(Integer filterId) {
- this.filterId = filterId;
+ if (isSupportsAddFilterId()) {
+ this.filterId = filterId;
+
+ } else {
+ throw new UnsupportedOperationException("ID filter is not supported by " + this.getClass().getSimpleName());
+ }
}
public void addFilterIds(Integer... filterIds) {
- this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
+ if (isSupportsAddFilterIds()) {
+ this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
+
+ } else {
+ throw new UnsupportedOperationException("IDS filter is not supported by " + this.getClass().getSimpleName());
+ }
+ }
+
+ /**
+ * By default all Criteria support sort on ID. And this sort is applied implicitly to criteria
+ * queries involving paging, to ensure consistent ordering of query results. If for some unlikely reason
+ * the caller needs to disable the implicit ID sort then call this, setting the value to false.
+ *
+ * @param supportsAddSortId
+ */
+ public void setSupportsAddSortId(boolean supportsAddSortId) {
+ this.supportsAddSortId = supportsAddSortId;
+ }
+
+ public boolean isSupportsAddSortId() {
+ return supportsAddSortId;
+ }
+
+ public boolean isSupportsAddFilterId() {
+ return true;
+ }
+
+ public boolean isSupportsAddFilterIds() {
+ return true;
}
protected void addSortField(String fieldName) {
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
index af888ea..2b03228 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftChangeSetCriteria.java
@@ -292,13 +292,12 @@ public class JPADriftChangeSetCriteria extends Criteria implements DriftChangeSe
}
@Override
- public void addSortId(PageOrdering pageOrdering) {
- throw new UnsupportedOperationException("The sort is not supported by DriftChangeSetCriteria.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The filter is not supported by DriftChangeSetCriteria.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
-
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
index 56f0ddf..b13ca90 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/JPADriftCriteria.java
@@ -245,13 +245,12 @@ public class JPADriftCriteria extends Criteria implements DriftCriteria {
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The filter is not supported by DriftCriteria.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addSortId(PageOrdering pageOrdering) {
- throw new UnsupportedOperationException("The sort is not supported by DriftCriteria.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
-
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
index a27e58d..3a2a2c1 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/MeasurementDataTraitCriteria.java
@@ -135,17 +135,17 @@ public class MeasurementDataTraitCriteria extends Criteria {
}
@Override
- public void addSortId(PageOrdering sortId) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddSortId() {
+ return false;
}
@Override
- public void addFilterId(Integer filterId) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddFilterId() {
+ return false;
}
@Override
- public void addFilterIds(Integer... filterIds) {
- throw new UnsupportedOperationException("The id column is not defined on this entity.");
+ public boolean isSupportsAddFilterIds() {
+ return false;
}
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
index f87a814..888c821 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
@@ -82,14 +82,22 @@ public class PageControl implements Serializable, Cloneable {
return new PageControl(0, 1);
}
+ /**
+ * Equivalent to initDefaultOrderingField(defaultField, PageOrdering.ASC).
+ *
+ * @param defaultField
+ * @see #initDefaultOrderingField(String, PageOrdering)
+ */
public void initDefaultOrderingField(String defaultField) {
initDefaultOrderingField(defaultField, PageOrdering.ASC);
}
- public void addDefaultOrderingField(String defaultField) {
- addDefaultOrderingField(defaultField, PageOrdering.ASC);
- }
-
+ /**
+ * Sets initial sort. If sorting is already defined this call will have no effect.
+ *
+ * @param defaultField
+ * @param defaultPageOrdering
+ */
public void initDefaultOrderingField(String defaultField, PageOrdering defaultPageOrdering) {
if (orderingFields.size() > 0) {
return;
@@ -98,6 +106,24 @@ public class PageControl implements Serializable, Cloneable {
addDefaultOrderingField(defaultField, defaultPageOrdering);
}
+ /**
+ * Equivalent to addDefaultOrderingField(defaultField, PageOrdering.ASC).
+ *
+ * @param defaultField
+ * @see #addDefaultOrderingField(String, PageOrdering)
+ */
+ public void addDefaultOrderingField(String defaultField) {
+ addDefaultOrderingField(defaultField, PageOrdering.ASC);
+ }
+
+ /**
+ * Add a default ordering field. If the maximum number of sort fields (currently 3) are already
+ * defined this call will have no effect. If the field is already a sort field this call will have no
+ * effect. Otherwise, the ordering field will be appended to the existing ordering fields.
+ *
+ * @param defaultField
+ * @param defaultPageOrdering
+ */
public void addDefaultOrderingField(String defaultField, PageOrdering defaultPageOrdering) {
if (orderingFields.size() >= MAX_ORDERING_FIELD_COUNT) {
return; // only need to add defaults if there are less than 3 sort orders
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
index 2d40388..a2bbfee 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQuery.java
@@ -27,7 +27,6 @@ import java.util.NoSuchElementException;
import org.rhq.core.domain.criteria.BaseCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
-import org.rhq.core.domain.util.PageOrdering;
/** This class provides a way to make PageList results easily iterable with 'for each','while',etc. loops
* and importantly automatically handles iteration through all PageControl results. This
@@ -62,17 +61,6 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
public CriteriaQuery(C criteria, CriteriaQueryExecutor<T, C> queryExecutor) {
this.criteria = criteria;
this.queryExecutor = queryExecutor;
-
- // make sure we have at least a default sort, otherwise chunking doesn't work
- PageControl pageControlOverrides = this.criteria.getPageControlOverrides();
- if (null != pageControlOverrides) {
- if (pageControlOverrides.getOrderingFields().isEmpty()) {
- pageControlOverrides.addDefaultOrderingField("id");
- }
-
- } else if (this.criteria.getOrderingFieldNames().isEmpty()) {
- this.criteria.addSortId(PageOrdering.ASC);
- }
}
/** Returns iterator for a single page of results as defined by
@@ -110,7 +98,8 @@ public class CriteriaQuery<T, C extends BaseCriteria> implements Iterable<T> {
public QueryResultsIterator(PageList<T> firstPage) {
currentPage = firstPage;
iterator = currentPage.iterator();
- count = firstPage == null || firstPage.getPageControl() == null ? 0 : firstPage.getPageControl().getStartRow();
+ count = firstPage == null || firstPage.getPageControl() == null ? 0 : firstPage.getPageControl()
+ .getStartRow();
}
@Override
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index d1d2f73..574fe73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -951,6 +951,7 @@ public final class CriteriaQueryGenerator {
} else {
pc = new PageControl(criteria.getPageNumber(), criteria.getPageSize());
}
+
for (String fieldName : criteria.getOrderingFieldNames()) {
for (Field sortField : getFields(criteria, Criteria.Type.SORT)) {
if (sortField.getName().equals(fieldName) == false) {
@@ -969,6 +970,15 @@ public final class CriteriaQueryGenerator {
}
}
}
+
+ // Unless paging is unlimited or it's not supported, add a sort on ID. This ensures that when paging
+ // we always have a consistent ordering. In other words, if the data set is unchanged between pages, there
+ // will no overlap/repetition of rows. Note that this applies even if other sort fields have been
+ // set, because they may still not have unique values. See https://bugzilla.redhat.com/show_bug.cgi?id=966665.
+ if (!pc.isUnlimited() && criteria.isSupportsAddSortId()) {
+ pc.addDefaultOrderingField("id");
+ }
+
return pc;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
index 2e1c897..b1f5272 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/util/CriteriaQueryTest.java
@@ -24,11 +24,15 @@ import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
+import org.testng.AssertJUnit;
import org.testng.annotations.Test;
import org.rhq.core.domain.criteria.Criteria;
+import org.rhq.core.domain.criteria.JPADriftCriteria;
+import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
public class CriteriaQueryTest {
@@ -229,4 +233,22 @@ public class CriteriaQueryTest {
assert e.getMessage().contains("NonUniqueResultException");
}
}
+
+ @Test
+ public void testAddSort() {
+ try {
+ JPADriftCriteria c = new JPADriftCriteria();
+ c.addSortId(PageOrdering.ASC);
+ AssertJUnit.fail("Should have thrown exception");
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+
+ ResourceCriteria c = new ResourceCriteria();
+ c.addSortName(PageOrdering.ASC);
+
+ assertEquals(2, CriteriaQueryGenerator.getPageControl(c).getOrderingFields().size());
+ assertEquals("name", CriteriaQueryGenerator.getPageControl(c).getOrderingFields().get(0).getField());
+ assertEquals("id", CriteriaQueryGenerator.getPageControl(c).getOrderingFields().get(1).getField());
+ }
}
commit 6613ba3db6f3c57c2d2ecac4823e368269a07152
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri May 24 15:40:51 2013 -0400
Use only apache logger and not the jboss logger from the base class.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
index d89c04b..b83a037 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
@@ -84,7 +84,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
- debugEnabled = log.isDebugEnabled();
+ debugEnabled = LOG.isDebugEnabled();
super.initialize(subject, callbackHandler, sharedState, options);
@@ -101,14 +101,14 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
}
if (debugEnabled) {
- log.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
+ LOG.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
}
// Now create the context for later use
try {
loginContext = new LoginContext(delegateTo, new DelegateCallbackHandler());
} catch (LoginException e) {
- log.warn("Initialize failed : " + e.getMessage());
+ LOG.warn("Initialize failed : " + e.getMessage());
}
}
@@ -123,7 +123,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
@Override
public boolean login() throws LoginException {
try {
- // Get the username / password the user entred and save if for later use
+ // Get the username / password the user entered and save if for later use
usernamePassword = super.getUsernameAndPassword();
// Try to log in via the delegate
@@ -141,7 +141,7 @@ public class DelegatingLoginModule extends UsernamePasswordLoginModule {
loginOk = true;
if (debugEnabled) {
- log.debug("Login ok for " + usernamePassword[0]);
+ LOG.debug("Login ok for " + usernamePassword[0]);
}
return true;
commit dfa94acdf6e92526bf35f08ebd2199c3c4c4db87
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 24 23:56:54 2013 +0200
Bug 920214 - [as7] add async avail check support to AS7 plugin
Only applies to server level resource (Standalone, Domain and Managed servers)
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 5f538b7..d85e7e3 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -617,6 +617,7 @@
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
</includes>
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index b80a39a..5d540fd 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -16,6 +16,7 @@
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
@@ -40,6 +41,8 @@ import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.availability.AvailabilityCollectorRunnable;
+import org.rhq.core.pluginapi.availability.AvailabilityFacet;
import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
@@ -81,7 +84,8 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
private LogFileEventResourceComponentHelper logFileEventDelegate;
private StartScriptConfiguration startScriptConfig;
private ServerPluginConfiguration serverPluginConfig;
- private AvailabilityType lastAvail;
+ private AvailabilityType previousAvailabilityType;
+ private AvailabilityCollectorRunnable availabilityCollector;
@Override
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
@@ -89,38 +93,69 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
serverPluginConfig = new ServerPluginConfiguration(pluginConfiguration);
connection = ASConnection.newInstanceForServerPluginConfiguration(serverPluginConfig);
+ // The availabilityCollector is still null at this point. So this call will always perform a real availability
+ // check and throw InvalidPluginConfigurationException as needed.
getAvailability();
logFileEventDelegate = new LogFileEventResourceComponentHelper(context);
logFileEventDelegate.startLogFileEventPollers();
startScriptConfig = new StartScriptConfiguration(pluginConfiguration);
+
+ Integer availabilityCheckPeriod = null;
+ try {
+ availabilityCheckPeriod = serverPluginConfig.getAvailabilityCheckPeriod();
+ } catch (NumberFormatException e) {
+ log.error("Avail check period config prop was not a valid number. Cause: " + e);
+ }
+ if (availabilityCheckPeriod != null) {
+ long availCheckMillis = availabilityCheckPeriod * 1000L;
+ this.availabilityCollector = resourceContext.getAvailabilityContext().createAvailabilityCollectorRunnable(
+ new AvailabilityFacet() {
+ public AvailabilityType getAvailability() {
+ return getAvailabilityNow();
+ }
+ }, availCheckMillis);
+ this.availabilityCollector.start();
+ }
}
@Override
public void stop() {
logFileEventDelegate.stopLogFileEventPollers();
- lastAvail = null;
+ previousAvailabilityType = null;
+ if (this.availabilityCollector != null) {
+ this.availabilityCollector.stop();
+ this.availabilityCollector = null;
+ }
}
@Override
public AvailabilityType getAvailability() {
- AvailabilityType avail;
+ if (this.availabilityCollector != null) {
+ return this.availabilityCollector.getLastKnownAvailability();
+ } else {
+ return getAvailabilityNow();
+ }
+ }
+
+ private AvailabilityType getAvailabilityNow() {
+ AvailabilityType availabilityType;
try {
readAttribute("launch-type");
- avail = AvailabilityType.UP;
+ availabilityType = AvailabilityType.UP;
} catch (Exception e) {
- avail = AvailabilityType.DOWN;
+ availabilityType = AvailabilityType.DOWN;
}
try {
- if ((avail == AvailabilityType.UP) && (lastAvail != AvailabilityType.UP)) {
+ if ((availabilityType == AvailabilityType.UP) && (previousAvailabilityType != AvailabilityType.UP)) {
validateServerAttributes();
log.info(getResourceDescription() + " has just come UP.");
}
} finally {
- lastAvail = avail;
+ previousAvailabilityType = availabilityType;
}
- return avail;
+ return availabilityType;
}
private void validateServerAttributes() throws InvalidPluginConfigurationException {
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
index e7fcd5b..4f0ea36 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ManagedASComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.AVAIL_CHECK_PERIOD_CONFIG_PROP;
+
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
@@ -30,6 +33,8 @@ import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDataTrait;
import org.rhq.core.domain.measurement.MeasurementReport;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.availability.AvailabilityCollectorRunnable;
+import org.rhq.core.pluginapi.availability.AvailabilityFacet;
import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceContext;
@@ -51,6 +56,7 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
private static final String MANAGED_SERVER_TYPE_NAME = "Managed Server";
private LogFileEventResourceComponentHelper logFileEventDelegate;
+ private AvailabilityCollectorRunnable availabilityCollector;
@Override
public void start(ResourceContext<HostControllerComponent<?>> hostControllerComponentResourceContext)
@@ -59,13 +65,34 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
logFileEventDelegate = new LogFileEventResourceComponentHelper(context);
logFileEventDelegate.startLogFileEventPollers();
+
+ Integer availabilityCheckPeriod = null;
+ try {
+ availabilityCheckPeriod = pluginConfiguration.getSimple(AVAIL_CHECK_PERIOD_CONFIG_PROP).getIntegerValue();
+ } catch (NumberFormatException e) {
+ log.error("Avail check period config prop was not a valid number. Cause: " + e);
+ }
+ if (availabilityCheckPeriod != null) {
+ long availCheckMillis = availabilityCheckPeriod * 1000L;
+ this.availabilityCollector = hostControllerComponentResourceContext.getAvailabilityContext()
+ .createAvailabilityCollectorRunnable(new AvailabilityFacet() {
+ public AvailabilityType getAvailability() {
+ return getAvailabilityNow();
+ }
+ }, availCheckMillis);
+ this.availabilityCollector.start();
+ }
+
}
@Override
public void stop() {
super.stop();
-
logFileEventDelegate.stopLogFileEventPollers();
+ if (this.availabilityCollector != null) {
+ this.availabilityCollector.stop();
+ this.availabilityCollector = null;
+ }
}
/**
@@ -76,6 +103,14 @@ public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>
*/
@Override
public AvailabilityType getAvailability() {
+ if (this.availabilityCollector != null) {
+ return this.availabilityCollector.getLastKnownAvailability();
+ } else {
+ return getAvailabilityNow();
+ }
+ }
+
+ private AvailabilityType getAvailabilityNow() {
if (context.getResourceType().getName().equals(MANAGED_SERVER_TYPE_NAME)) {
Address theAddress = new Address();
String host = pluginConfiguration.getSimpleValue("domainHost", "local");
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
index 1433c17..3832ed2 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/ServerPluginConfiguration.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,14 +13,16 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.helper;
import java.io.File;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.modules.plugins.jbossas7.JBossProductType;
/**
@@ -43,6 +45,7 @@ public class ServerPluginConfiguration {
public static final String LOG_DIR = "logDir";
public static final String PRODUCT_TYPE = "productType";
public static final String HOST_CONFIG_FILE = "hostConfigFile";
+ public static final String AVAIL_CHECK_PERIOD_CONFIG_PROP = "availabilityCheckPeriod";
}
private Configuration pluginConfig;
@@ -143,4 +146,14 @@ public class ServerPluginConfiguration {
hostConfigFile.toString() : null);
}
+ public Integer getAvailabilityCheckPeriod() {
+ PropertySimple propertySimple = this.pluginConfig.getSimple(Property.AVAIL_CHECK_PERIOD_CONFIG_PROP);
+ return propertySimple == null ? null : propertySimple.getIntegerValue();
+ }
+
+ public void setAvailabilityCheckPeriod(Integer availabilityCheckPeriod) {
+ this.pluginConfig.setSimpleValue(Property.AVAIL_CHECK_PERIOD_CONFIG_PROP,
+ availabilityCheckPeriod == null ? null : availabilityCheckPeriod.toString());
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index ad22370..7213acd 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -82,6 +82,17 @@
</c:list-property>
</c:group>
'>
+
+ <!ENTITY availabilityCheckPeriod '
+ <c:simple-property name="availabilityCheckPeriod"
+ description="The amount of time, in seconds, that must elapse between availability checks to see if the server is up. If set, the availability checks will be performed asynchronously thus allowing slow-responding servers to avoid being falsely reported as down. Minimum value is 60 seconds."
+ units="seconds" required="false" type="integer">
+ <c:constraint>
+ <c:integer-constraint minimum="60"/>
+ </c:constraint>
+ </c:simple-property>
+'>
+
<!ENTITY serverKindMetrics '
<metric property="_skm:release-codename" dataType="trait" displayName="Server Code Name"/>
<metric property="_skm:release-version" dataType="trait" displayName="Server Version"/>
@@ -862,6 +873,10 @@
&startScriptPluginConfigGroup;
&logSources;
+
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<process-scan name="HostController" query="process|basename|match=^java.*,arg|org.jboss.as.host-controller|match=.*"/>
@@ -1173,6 +1188,10 @@
&startScriptPluginConfigGroup;
&logSources;
+
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<process-scan name="StandaloneAS" query="process|basename|match=^java.*,arg|org.jboss.as.standalone|match=.*"/>
@@ -1621,6 +1640,9 @@
<plugin-configuration>
<c:simple-property name="path" readOnly="true"/>
&logSources;
+ <c:group name="advanced" displayName="Advanced" hiddenByDefault="true">
+ &availabilityCheckPeriod;
+ </c:group>
</plugin-configuration>
<operation name="start" description="Start this server instance." displayName="Start">
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
index 43e6e06..8c61c8e 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractJBossAS7PluginTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.itest;
+import static org.rhq.core.domain.measurement.AvailabilityType.UP;
+import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.Set;
@@ -31,8 +34,10 @@ import org.rhq.core.domain.util.ResourceFilter;
import org.rhq.core.domain.util.ResourceUtility;
import org.rhq.core.domain.util.TypeAndKeyResourceFilter;
import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.inventory.ResourceContainer;
import org.rhq.core.plugin.testutil.AbstractAgentPluginTest;
import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration;
import org.rhq.modules.plugins.jbossas7.itest.domain.DomainServerComponentTest;
import org.rhq.modules.plugins.jbossas7.itest.standalone.StandaloneServerComponentTest;
import org.rhq.test.arquillian.AfterDiscovery;
@@ -152,4 +157,26 @@ public abstract class AbstractJBossAS7PluginTest extends AbstractAgentPluginTest
return serverResource;
}
+ protected void testAsynchronousAvailabilityCheck(Resource resource) throws Exception {
+ // Activate asynchronous availability checking
+ ServerPluginConfiguration serverPluginConfig = new ServerPluginConfiguration(resource.getPluginConfiguration());
+ int availabilityCheckPeriod = 65;
+ serverPluginConfig.setAvailabilityCheckPeriod(availabilityCheckPeriod);
+ restartResourceComponent(resource);
+
+ Thread.sleep((3 * availabilityCheckPeriod * 1000L) / 2);
+ assertEquals(getAvailability(resource), UP);
+
+ // Deactivate asynchronous availability checking as subsequent tests may rely on immediate availabilty checking
+ serverPluginConfig.setAvailabilityCheckPeriod(null);
+ restartResourceComponent(resource);
+ }
+
+ private void restartResourceComponent(Resource resource) throws PluginContainerException {
+ InventoryManager inventoryManager = this.pluginContainer.getInventoryManager();
+ inventoryManager.deactivateResource(resource);
+ ResourceContainer serverContainer = inventoryManager.getResourceContainer(resource);
+ inventoryManager.activateResource(resource, serverContainer, true);
+ }
+
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
index 4effd50..91ece92 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,9 +13,10 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
+
package org.rhq.modules.plugins.jbossas7.itest.domain;
import java.io.File;
@@ -76,14 +77,20 @@ public class DomainServerComponentTest extends AbstractServerComponentTest {
testServerAttributeValidation();
}
+ @Test(priority = 1002)
+ public void testDomainServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getServerResource());
+ }
+
+
// ******************************* METRICS ******************************* //
- @Test(priority = 1002, enabled = true)
+ @Test(priority = 1003, enabled = true)
public void testDomainReleaseVersionTrait() throws Exception {
super.testReleaseVersionTrait();
}
// ******************************* OPERATIONS ******************************* //
- @Test(priority = 1003, enabled = true)
+ @Test(priority = 1004, enabled = true)
public void testDomainServerShutdownAndStartOperations() throws Exception {
super.testShutdownAndStartOperations();
}
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
index 3f9f101..42bab08 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/domain/ManagedServerTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest.domain;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.PluginContainerException;
@@ -32,9 +35,6 @@ import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
import org.rhq.test.arquillian.RunDiscovery;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
/**
* Test dealing with managed servers
* @author Heiko W. Rupp
@@ -45,7 +45,7 @@ public class ManagedServerTest extends AbstractJBossAS7PluginTest {
public static final ResourceType RESOURCE_TYPE = new ResourceType("Managed Server", PLUGIN_NAME, ResourceCategory.SERVER, null);
private static final String RESOURCE_KEY = "master/server-one";
- @Test(priority = 1020, groups = "discovery", enabled = false)
+ @Test(priority = 1020, groups = "discovery", enabled = true)
@RunDiscovery(discoverServices = true, discoverServers = true)
public void runDiscovery() throws Exception {
Resource platform = this.pluginContainer.getInventoryManager().getPlatform();
@@ -93,6 +93,11 @@ public class ManagedServerTest extends AbstractJBossAS7PluginTest {
assertEquals(avail, AvailabilityType.UP);
}
+ @Test(priority = 1022)
+ public void testManagedServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getResource());
+ }
+
private Resource getResource() {
InventoryManager im = pluginContainer.getInventoryManager();
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
index 9845b03..8446345 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,11 +13,14 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest.standalone;
+import static org.rhq.core.domain.measurement.AvailabilityType.UP;
+import static org.testng.Assert.assertEquals;
+
import java.io.File;
import java.util.Arrays;
import java.util.List;
@@ -38,8 +41,6 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.modules.plugins.jbossas7.itest.AbstractServerComponentTest;
import org.rhq.test.arquillian.RunDiscovery;
-import static org.testng.Assert.assertEquals;
-
/**
* Test discovery and facets of the "JBossAS7 Standalone Server" Resource type.
*
@@ -105,20 +106,20 @@ public class StandaloneServerComponentTest extends AbstractServerComponentTest {
}
// TODO: Re-enable once fixed.
- @Test(priority = 5, dependsOnMethods = "testStandaloneServerShutdownAndStartOperations", enabled = false)
+ @Test(priority = 6, dependsOnMethods = "testStandaloneServerShutdownAndStartOperations", enabled = false)
public void testRestartOperation() throws Exception {
// First make sure the server is up.
AvailabilityType avail = getAvailability(getServerResource());
- assertEquals(avail, AvailabilityType.UP);
+ assertEquals(avail, UP);
// Make sure the server is back up.
// TODO (ips): Check that the server is a different process now.
invokeOperationAndAssertSuccess(getServerResource(), RESTART_OPERATION_NAME, null);
avail = getAvailability(getServerResource());
- assertEquals(avail, AvailabilityType.UP);
+ assertEquals(avail, UP);
}
- @Test(priority = 6, enabled = true)
+ @Test(priority = 7, enabled = true)
public void testSystemPropertiesSettings() throws Exception {
Configuration config = loadResourceConfiguration(getServerResource());
@@ -152,6 +153,11 @@ public class StandaloneServerComponentTest extends AbstractServerComponentTest {
}
+ @Test(priority = 8)
+ public void testStandaloneServerAsynchronousAvailabilityCheck() throws Exception {
+ testAsynchronousAvailabilityCheck(getServerResource());
+ }
+
protected String getExpectedStartScriptFileName() {
return (File.separatorChar == '/') ? "standalone.sh" : "standalone.bat";
}
commit 64c225a14337769a1f6ce1df40a9e025ee3258e0
Merge: 078a2da e87ea03
Author: Jirka Kremser <jiri.kremser(a)gmail.com>
Date: Fri May 24 14:40:00 2013 -0700
Merge pull request #1 from lzoubek/master
Merging the rhq bot improvements
commit 078a2da4e488645284359940e3df7a61a0299109
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri May 24 16:43:50 2013 +0200
[BZ 965833 - Potential bug in join/fetch/avoidance code]
It is now possible to lazily fetch fields defined in super classes.
The avoidance of the join-fetch with limits exposed a missing feature that
was present in the code from the day one. It would be failing if the
criteria query was used to fetch a custom object (i.e. not the primary
persistent class of the criteria object) using an "altered projection" and
a fetch would be set on a field defined in a super class of the persistent
class of the criteria object. Only by chance this has never happened
before, because we don't use the altered projections on the criteria
queries that often.
Now that we lazily fetch fields much more often (to avoid join fetch
with limits) this is a problem even in cases without an altered projection.
The fix is fortunately very simple - we need to also search the
superclasses of the criteria's persistent class when looking for a field
to lazily fetch.
The possibility of fields being present in super-classes was taken into
account on other places in the CriteriaQueryGenerator class, too.
Documentation on the getJoinFetchFields() and alterProjection() was
enhanced to hopefully better explain the conditions underwhich you can
combine fetching and altered projection together.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index 867ea16..d1d2f73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -343,7 +343,7 @@ public final class CriteriaQueryGenerator {
} else {
if (this.projection == null) {
/*
- * if not altering the projection, join fetching can be using
+ * if not altering the projection, join fetching can be used
* to retrieve the associated instance in the same SELECT
*
* We further avoid a JOIN FETCH when executing queries with limits.
@@ -664,14 +664,9 @@ public final class CriteriaQueryGenerator {
}
private boolean isPersistentBag(String fieldName) {
- try {
- Class<?> persistentClass = criteria.getPersistentClass();
- Field field = persistentClass.getDeclaredField(fieldName);
+ Field field = findField(fieldName);
- return isAList(field) && !field.isAnnotationPresent(IndexColumn.class);
- } catch (NoSuchFieldException e) {
- return false;
- }
+ return field != null && isAList(field) && !field.isAnnotationPresent(IndexColumn.class);
}
private boolean isAList(Field field) {
@@ -690,23 +685,40 @@ public final class CriteriaQueryGenerator {
}
private void addPersistentBag(String fieldName) {
- try {
- Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
- persistentBagFields.add(field);
- } catch (NoSuchFieldException e) {
- LOG.warn("Failed to add persistent bag collection on class [" + criteria.getPersistentClass().getName() +"]: ", e);
+ Field f = findField(fieldName);
+ if (f == null) {
+ LOG.warn(
+ "Failed to add persistent bag collection [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() +
+ "]. There doesn't seem to be a field of that name on the class or any of its superclasses.");
+ } else {
+ persistentBagFields.add(f);
}
}
private void addJoinFetch(String fieldName) {
- try {
- Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
- joinFetchFields.add(field);
- } catch (NoSuchFieldException e) {
- LOG.warn("Failed to add join fetch field on class [" + criteria.getPersistentClass().getName() + "]: ", e);
+ Field f = findField(fieldName);
+ if (f == null) {
+ LOG.warn(
+ "Failed to add join fetch field [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() +
+ "]. There doesn't seem to be a field of that name on the class or any of its superclasses.");
+ } else {
+ joinFetchFields.add(f);
}
}
+ private Field findField(String fieldName) {
+ Class<?> cls = criteria.getPersistentClass();
+ while (cls != null) {
+ try {
+ return cls.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ cls = cls.getSuperclass();
+ }
+ }
+
+ return null;
+ }
+
/**
* <strong>Note:</strong> This method should only be called after {@link #getQueryString(boolean)}} because it is
* that method where the persistentBagFields property is initialized.
@@ -718,6 +730,21 @@ public final class CriteriaQueryGenerator {
return persistentBagFields;
}
+ /**
+ * <strong>Note:</strong> This method should only be called after {@link #getQueryString(boolean)}} because it is
+ * that method where the persistentBagFields property is initialized.
+ * <p/>
+ * The elements of the returned list are a (sub)set of the fields that the criteria object specified to be fetched
+ * (using the fetchXXX() methods). If the {@link CriteriaQueryRunner} is not set to automatically fetch all the
+ * fields, you need to manually initialize these fields by for example using
+ * {@link CriteriaQueryRunner#initFetchFields(Object)} method on each of the results.
+ *
+ * @see #alterProjection(String) <code>alterProjection(String)</code> for special attention you need to make when
+ * mixing fetching fields and altered projection.
+ *
+ * @return Returns a list of fields from the persistent class to which the criteria class corresponds. The fields in
+ * the list are fields specified by the criteria to be fetched (using the fetchXXX() methods).
+ */
public List<Field> getJoinFetchFields() {
return joinFetchFields;
}
@@ -728,8 +755,11 @@ public final class CriteriaQueryGenerator {
* only affect the ResultSet for the data query, not the count query.
* <p/>
* If you are projecting a composite object that does not directly extend the entity your Criteria object
- * represents, then you will need to manually initialize the persistent bags using the methods exposed on
- * {@link CriteriaQueryRunner}
+ * represents, then you will need to manually initialize the persistent bags and fetch fields using the
+ * {@link CriteriaQueryRunner#initFetchFields(Object)} method for each object in the results (for which you need
+ * to instantiate the {@link CriteriaQueryRunner} with automatic fetching switched OFF). <b>Note</b> that this will
+ * NOT work on the composite object itself. You need to pass an instance of the entity class to the
+ *{@link CriteriaQueryRunner#initFetchFields(Object)} method.
*/
public void alterProjection(String projection) {
this.projection = projection;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
index a788fb0..73292be 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
@@ -129,9 +129,7 @@ public class CriteriaQueryRunner<T> {
public void initFetchFields(Object entity) {
initPersistentBags(entity);
- if (queryGenerator.isProjectionAltered()) {
- initJoinFetchFields(entity);
- }
+ initJoinFetchFields(entity);
}
private void initPersistentBags(Object entity) {
commit e87ea0381518ffda4a42be7a119ce0ab764cd551
Author: Libor Zoubek <lzoubek(a)jezzovo.net>
Date: Fri May 24 16:45:08 2013 +0200
rhq-Bot: only devs can send private echo command to bot
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index 1960f1d..a7b3e78 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -209,8 +209,12 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
String message = privateMessageEvent.getMessage();
Matcher echoMatcher = ECHO_PATTERN.matcher(message);
if (echoMatcher.matches()) {
- String echoMessage = echoMatcher.group(1);
- bot.sendMessage(this.channel, echoMessage);
+ if (!JON_DEVS.contains(privateMessageEvent.getUser().getNick())) {
+ privateMessageEvent.respond("You're not my master, I am your master, go away");
+ } else {
+ String echoMessage = echoMatcher.group(1);
+ bot.sendMessage(this.channel, echoMessage);
+ }
} else if (message.equalsIgnoreCase(Command.PREFIX + "listrenames")) {
//Generate a list of renames in the form of old1 changed to new1, old2 changed to new2, etc
StringBuilder users = new StringBuilder();
commit 66c47dde1721632eca6990d389195708e8deeefe
Author: Libor Zoubek <lzoubek(a)jezzovo.net>
Date: Fri May 24 16:40:57 2013 +0200
ircBot: improved recognition of commands
Bot now recognizes commands only when in the beginning of message or if you
highlight bot's nick and command is the very first word (like rhq-bot:
!help)
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index cd6d43a..1960f1d 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -61,7 +61,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
SUPPORT,
WIKI("Our wiki is available from https://docs.jboss.org/author/display/RHQ/Home", true);
- public static final char PREFIX = '!';
+ public static final String PREFIX = "!";
private final String staticRespond;
private final boolean includeInHelp;
@@ -106,7 +106,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
this.channel = channel;
isRedHatChannel = "irc.devel.redhat.com".equals(channel);
StringBuilder commandRegExp = new StringBuilder();
- commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
+ commandRegExp.append("^(?i)[ ]*").append(Command.PREFIX).append("(");
for (Command command : Command.values()) {
commandRegExp.append(command.name()).append('|');
}
@@ -173,6 +173,11 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
}
+ if (message.startsWith(event.getBot().getNick())) {
+ // someone asked bot directly, we have to remove that from message
+ message = message.substring(event.getBot().getNick().length());
+ message = message.replaceFirst("[^ ]*", "");
+ }
// react to commands included in the messages
Matcher commandMatcher = commandPattern.matcher(message);
while (commandMatcher.find()) {
commit adac13e48ddd26aa55b6a6cbc6f3c3bcff5f802e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 24 11:14:44 2013 +0200
Add some translations
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 057785a..d158243 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -10,25 +10,25 @@
#
###################################
##avail_chart_down_label = DOWN
-##avail_chart_title_label = Availability
+avail_chart_title_label = Verfügbarkeit
##avail_chart_up_label = UP
-##chart_date_label = Date
+chart_date_label = Datum
##chart_down_label = Down
##chart_time_label = Start
-##chart_unknown_label = Unknown
-##chart_no_data_label = No Data
-##chart_title_avg_label = Avg
-##chart_title_min_label = Min
-##chart_title_peak_label = Max
-##chart_hover_availability_label = Availability
-##chart_hover_availability_type_warn = MIXED
-##chart_hover_date_format = %m/%d/%y
+chart_unknown_label = Unbekannt
+chart_no_data_label = Keine Daten vorhanden
+chart_title_avg_label = Durchschn.
+chart_title_min_label = Min
+chart_title_peak_label = Max
+chart_hover_availability_label = Verfügbarkeit
+chart_hover_availability_type_warn = Gemischt
+chart_hover_date_format = %d.%m.%y
##chart_hover_time_format = %I:%M:%S %p
-##chart_ie_not_supported = Charting is not available for this browser.
-##chart_hover_start_label = Start
-##chart_hover_end_label = End
+chart_ie_not_supported = Charting ist bei diesem Browser nicht unterstützt
+chart_hover_start_label = Start
+chart_hover_end_label = Ende
##chart_hover_period_label = Period
-##chart_hover_bar_label = Duration
+chart_hover_bar_label = Dauer
common_alert_high = HOCH
common_alert_low = NIEDRIG
common_alert_medium = MITTEL
@@ -68,7 +68,7 @@ common_button_schedule = Planen
common_button_search = Suchen
common_button_set = Setzen
common_button_showDetails = Details anzeigen...
-##common_button_unignore = Unignore
+common_button_unignore = Ignorieren aufheben
common_button_uninventory = Aus dem Inventar löschen
common_calendar_april_short = Apr
common_calendar_august_short = Aug
@@ -91,7 +91,7 @@ common_label_filters = Filter
common_label_hour = Stunde
common_label_item = Eintrag
common_label_items = Einträge
-##common_label_link = Link
+common_label_link = Link
common_label_month = Monat
common_label_none = keine
common_label_none2 = keines
@@ -128,7 +128,7 @@ common_status_nochange = Keine Änderung
common_status_partial = partiell
common_status_success = Erfolg
common_status_unknown = Unbekannt
-##common_title_acknowledged = Acknowledged
+common_title_acknowledged = Bestätigt
common_title_add_column = Spalte hinzufügen
common_title_add_portlet = Portlet hinzufügen
common_title_address = Adresse
@@ -418,7 +418,7 @@ favorites_recentlyViewed = Kürzlich angesehen
favorites_resources = Gemerkte Ressourcen
filter_from_date = Von
filter_to_date = Bis
-##group_tree_groupOfResourceType = Group of [{0}]
+group_tree_groupOfResourceType = Gruppe von [{0}]
group_tree_partialClusterTooltip = {0} der {1} Gruppenmitglieder haben eine ''{2}'' Ressource
util_disambiguationReportDecorator_pluginSuffix = ({0} Plugin)
util_errorHandler_nullException = Exception war null
@@ -441,8 +441,8 @@ view_adminConfig_agentPlugins = Agent Plugins
view_adminConfig_alertDefTemplates = Vorlagen für Alarmdefinitionen
view_adminConfig_downloads = Downloads
view_adminConfig_driftDefTemplates = Vorlagen für Dritf-Definitionen
-##view_adminConfig_ignoreResourceTypes = Ignored Resource Types
-##view_adminConfig_ignoreResourceTypes_changeTitle = Change?
+view_adminConfig_ignoreResourceTypes = Ignorierte Ressource Typen
+view_adminConfig_ignoreResourceTypes_changeTitle = Ändern?
##view_adminConfig_ignoreResourceTypes_confirmIgnore = Are you sure you want to ignore the resource type [{0}]? You will no longer be able to import resources of this type and any resources of this type that are already in inventory will be uninventoried and you can no longer manage them.
##view_adminConfig_ignoreResourceTypes_confirmUnignore = Are you sure you want to unignore the resource type [{0}]? Any resources of this type that exist in your managed environment will be able to be discovered and inventoried.
##view_adminConfig_ignoreResourceTypes_failure = Failed to set the ignore flag on the selected resource type.
@@ -456,7 +456,7 @@ view_adminConfig_systemSettings = Systemeinstellungen
view_adminContent_contentSources = Quellen für Inhalte
view_adminRoles_assignedGroups = Zugewiesene Ressourcen-Gruppen
view_adminRoles_assignedSubjects = Zugewisene Benutzer
-##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name.
+view_adminRoles_failCreateRoleWithExistingName = Konnte die Rolle mit dem existierenden Namen [{0}] nicht anlegen. Bitte wählen Sie einen anderen Namen.
view_adminRoles_failLdap = Konnte nicht ermitteln, ob LDAP konfiguriert ist - gehe von keiner LDAP-Konfiguration aus.
view_adminRoles_failLdapGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt.
view_adminRoles_failLdapGroupsRole = Konnte die LDAP-Gruppen für die Rolle nicht laden.
@@ -526,23 +526,23 @@ view_adminTemplates_pluginTemplates = Vorlagen für Plugins Plugins
view_adminTemplates_servers = Server
view_adminTemplates_userTemplates = Nutzers-spezifische Vorlagen
view_adminTopology_affinityGroups = Affinitätsgruppen
-##view_adminTopology_affinityGroups_agentCount = Agent Count
-##view_adminTopology_affinityGroups_agentsInThisGroup = Agents in This Group
+view_adminTopology_affinityGroups_agentCount = Anzahl Agenten
+view_adminTopology_affinityGroups_agentsInThisGroup = Agenten in dieser Gruppe
##view_adminTopology_affinityGroups_agentsNotPartOfAnAffinityGroup = Agents not Part of an Affinity Group
##view_adminTopology_affinityGroups_agetnMembers = Agent Members
-##view_adminTopology_affinityGroups_createNew = Create New
+view_adminTopology_affinityGroups_createNew = Neu anlegen
##view_adminTopology_affinityGroups_details = Affinity Group Details
-##view_adminTopology_affinityGroups_removeSelected = Remove Selected
-##view_adminTopology_affinityGroups_serverCount = Server Count
+view_adminTopology_affinityGroups_removeSelected = Ausgewählte entfernen
+view_adminTopology_affinityGroups_serverCount = Anzahl Server
##view_adminTopology_affinityGroups_serverMembers = Server Members
-##view_adminTopology_agentDetail_address = Address
+view_adminTopology_agentDetail_address = Adresse
##view_adminTopology_agentDetail_agentFailoverList = Agent Failover List
-##view_adminTopology_agentDetail_currentServer = Current Server
+view_adminTopology_agentDetail_currentServer = Aktueller Server
##view_adminTopology_agentDetail_token = Token
##view_adminTopology_agent_agentBindAddress = Agent Bind Address
##view_adminTopology_agent_agentBindPort = Agent Bind Port
-##view_adminTopology_agent_agentName = Agent Name
-##view_adminTopology_agent_connectedServer = Connected Server
+view_adminTopology_agent_agentName = Name des Agenten
+view_adminTopology_agent_connectedServer = Verbundener Server
##view_adminTopology_agent_delete_confirm = This will deregister the selected agents and uninventory their corresponding platforms and all other resources associated with them. There is no way to undo this action. Are you sure you want to do this?
##view_adminTopology_agent_lastAvailabilityPing = Last Availability Ping
##view_adminTopology_agent_lastAvailabilityReport = Last Availability Report
@@ -592,7 +592,7 @@ view_adminTopology_partitionEvents = Partitionierungs-Ereignisse
##view_adminTopology_partitionEventsDetail_eventDetails = Event Details
##view_adminTopology_partitionEventsDetail_eventExecutionTime = Event Execution Time
##view_adminTopology_partitionEventsDetail_eventType = Event Type
-##view_adminTopology_partitionEvents_details = Details
+view_adminTopology_partitionEvents_details = Details
##view_adminTopology_partitionEvents_detailsFilter = Details Filter
##view_adminTopology_partitionEvents_execStatusFilter = Execution Status Filter
##view_adminTopology_partitionEvents_execTime = Execution Time
@@ -600,7 +600,7 @@ view_adminTopology_partitionEvents = Partitionierungs-Ereignisse
##view_adminTopology_partitionEvents_forceRepartition = Force Repartition
##view_adminTopology_partitionEvents_initiatedBy = Initiated By
##view_adminTopology_partitionEvents_purgeAll = Purge All
-##view_adminTopology_partitionEvents_type = Type
+view_adminTopology_partitionEvents_type = Typ
##view_adminTopology_partitionEvents_typeFilter = Type Filter
view_adminTopology_remoteAgentInstall = Installation entfernter Agenten
##view_adminTopology_serverDetail_connectedAgents = Connected Agents
@@ -610,7 +610,7 @@ view_adminTopology_remoteAgentInstall = Installation entfernter Agenten
##view_adminTopology_server_agentCount = Agent Count
##view_adminTopology_server_endpointAddress = Endpoint Address
##view_adminTopology_server_lastUpdateTime = Last Update Time
-##view_adminTopology_server_mode = Mode
+view_adminTopology_server_mode = Modus
##view_adminTopology_server_nonSecurePort = Nonsecure Port
##view_adminTopology_server_removeSelected = Remove Selected
##view_adminTopology_server_securePort = Secure Port
@@ -728,15 +728,15 @@ view_admin_systemSettings_serverDetails_dbUrl = URL der Datenbankverbindung
view_admin_systemSettings_serverDetails_dbVersion = Produktversion der Datenbank
view_admin_systemSettings_serverDetails_installDir = Installationsverzeichnis des Servers
view_admin_systemSettings_serverDetails_nextRotation = Nächste Rotation der Metrik-Tabellen
-##view_admin_systemSettings_serverDetails_productName = Product Name
-##view_admin_systemSettings_serverDetails_serverName = Server Name
+view_admin_systemSettings_serverDetails_productName = Produktname
+view_admin_systemSettings_serverDetails_serverName = Servername
view_admin_systemSettings_serverDetails_time = Lokale Zeit des Servers
view_admin_systemSettings_serverDetails_tz = Zeitzone des Servers
view_admin_topology = Topologie
view_alert_common_tab_conditions = Bedingungen
view_alert_common_tab_conditions_expression = Alarm auslösen wenn
##view_alert_common_tab_conditions_expression_tooltip = Determines if ANY or ALL of the conditions must evaluate to true in order for the entire condition set to be considered true.
-##view_alert_common_tab_conditions_modalEdit_title = Edit Condition
+view_alert_common_tab_conditions_modalEdit_title = Bedingungen ändern
view_alert_common_tab_conditions_modal_title = Bedingung hinzufügen
view_alert_common_tab_conditions_recovery_disabled = Dieser Alarm hat seine Definition deaktiviert.
view_alert_common_tab_conditions_recovery_enabled = Ausgelöst, dass ''{0}'' wieder aktiviert wurde
@@ -883,7 +883,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Änderung de
view_alert_definition_condition_editor_option_operation = Ausführung der Operation
view_alert_definition_condition_editor_option_resource_configuration = Änderung der Konfiguration der Ressource
##view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
-##view_alert_definition_editCondition = Edit Condition
+view_alert_definition_editCondition = Bedingungen ändern
view_alert_definition_for_group = Gruppendefinition ansehen
view_alert_definition_for_type = Vorlage ansehen
view_alert_definition_notification_cliScript_editor_anotherUser = Anderer Benutzer
@@ -892,7 +892,7 @@ view_alert_definition_notification_cliScript_editor_script = Skript
view_alert_definition_notification_cliScript_editor_thisUser = Aktueller Benutzer
view_alert_definition_notification_editor_delete_confirm = Sind Sie sicher, dass sie die ausgewählten Alarm-Benachrichtigungen löschen wollen?
view_alert_definition_notification_editor_field_configuration = Konfiguration
-##view_alert_definition_notification_editor_field_configuration_loadFailed = Failed to get notification configuration preview
+view_alert_definition_notification_editor_field_configuration_loadFailed = Konte die Vorschau der Benachrichtigung nicht laden
view_alert_definition_notification_editor_field_configuration_not_loaded = Unbekannt
view_alert_definition_notification_editor_field_sender = Sender
view_alert_definition_notification_editor_loadFailed = Kann die Alarm-Sender nicht laden
@@ -946,7 +946,7 @@ view_alert_definitions_disable_success = Es wurden {0} Alarm-Definitionen erfolg
view_alert_definitions_enable_confirm = Die ausgewählten Alarm-Definitionen aktivieren?
view_alert_definitions_enable_failure = Konnte die ausgewählten Alarm-Definitionen nicht aktivieren
view_alert_definitions_enable_success = Es wurden {0} Alarm-Definitionen erfolgreich aktiviert
-##view_alert_definitions_leaveUnsaved = Do you want to save the modified alert definition?
+view_alert_definitions_leaveUnsaved = Möchten Sie die geänderte Alarm-Definition speichern?
view_alert_definitions_loadFailed = Konnte die Daten für die Alarm-Definitionen nicht laden
view_alert_definitions_loadFailed_single = Konnte die Daten für die Alarm-Definition mit der id {0}
view_alert_definitions_table_title_group = Alarm-Definitionen für Gruppen
@@ -1184,7 +1184,7 @@ view_bundle_version_backToBundle = Zurück zum Bundle
##view_bundle_version_deleteSuccessful = You successfully deleted the bundle version [{0}]
##view_bundle_version_loadFailure = Failed to load bundle version
view_bundle_versions = Versionen
-##view_charts_time_axis_label = Time
+view_charts_time_axis_label = Zeit
view_configCompare_comparingConfigs = Konfigurationen vergleichen
##view_configCompare_configCompare = Configuration Comparison
view_configEdit_addItem = Eintrag zur Liste hinzufügen
@@ -1483,13 +1483,13 @@ view_inventory_groups_children = Kinder
##view_inventory_groups_deleteSuccessful = You have successfully deleted the selected resource groups
##view_inventory_groups_descendants = Descendants
##view_inventory_groups_loadFailed = Failed to load group composite data
-##view_inventory_ignoredResources = Ignored Resources
+view_inventory_ignoredResources = Ignorierte Ressourcen
view_inventory_mixed = gemischt
view_inventory_platforms = Platformen
view_inventory_problemGroups = Gruppen mit Problemen
##view_inventory_resource_loadFailed = Resource with id [{0}] does not exist or is not accessible
-##view_inventory_resources_deleteConfirm = Are you sure you want to delete the selected resources?
-##view_inventory_resources_deleteFailed = Failed to delete the selected resources
+view_inventory_resources_deleteConfirm = Sind Sie sicher, dass Sie die ausgewählten Ressourcen löschen wollen?
+view_inventory_resources_deleteFailed = Löschen der ausgewählten Ressourcen ist fehlgeschlagen
##view_inventory_resources_deleteSuccessful = A request to perform the resource deletion has been submitted successfully to the agent(s).
##view_inventory_resources_disableSuccessful = You have successfully disabled the selected resources and their children, [{0}] resources.
##view_inventory_resources_ignoreConfirm = Are you sure you want the selected resources to be ignored? They will no longer show up in inventory.
commit 0d6dcd43a16699348430e81a241ae38da6d431af
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Thu May 23 17:14:50 2013 -0400
Fix test that started failing after the change to remove JOIN FETCH
from Criteria calls that include paging and optional data. It seems the
new approach changes slightly the way the data is returned.
loadDefinition() returns hibernate proxied data. It is not safe to pass
proxies into equals() impls because these typically access fields directly,
not through getters, and therefore bypass the proxied data.
Note that this change in behavior due to the JOIN FETCH fix would only
affect non-client code (like test code or intra-slsb calls) because return
values to client code would already be cleansed of the proxies. The test
is fixed in the same way, by using HibernateDetachUtility to scrub the
proxies before attempting the assertEquals().
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
index 18c7093..4202d6a 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/drift/ManageDriftDefinitionsTest.java
@@ -57,6 +57,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.test.AssertUtils;
@@ -91,7 +92,7 @@ public class ManageDriftDefinitionsTest extends AbstractDriftServerTest {
deleteEntity(ResourceType.class, DRIFT_NOT_SUPPORTED_TYPE);
}
- public void createDefinitionFromUnpinnedTemplate() {
+ public void createDefinitionFromUnpinnedTemplate() throws Exception {
// first create a template
final DriftDefinition templateDef = new DriftDefinition(new Configuration());
templateDef.setName(NAME_PREFIX + "createUnpinnedDefinition");
@@ -114,6 +115,7 @@ public class ManageDriftDefinitionsTest extends AbstractDriftServerTest {
DriftDefinitionComparator comparator = new DriftDefinitionComparator(
BOTH_BASE_INFO_AND_DIRECTORY_SPECIFICATIONS);
+ HibernateDetachUtility.nullOutUninitializedFields(newDef, SerializationType.SERIALIZATION);
assertEquals("The drift definition was not persisted correctly", 0, comparator.compare(definition, newDef));
assertEquals("The template association was not set on the definition", template, newDef.getTemplate());
}
commit 301a28ce97530f69416677a8b8b470e3f157d9bd
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 22:38:18 2013 +0200
Bit of cleanup and testing of alert->ack and alert->purge
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 92d2499..224ab3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -25,12 +25,9 @@ package org.rhq.enterprise.server.rest;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -251,89 +248,8 @@ public class AbstractRestBean {
return result;
}
- protected void putResourceToCache(Resource res) {
- putToCache(res.getId(), Resource.class, res);
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- try {
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
-
- if (null == visibleResources) {
- visibleResources = new HashSet<Integer>();
- }
-
- visibleResources.add(res.getId());
- cache.put(callerKey, visibleResources);
-
- Map<Integer, Integer> childParentMap = (Map<Integer, Integer>) cache.get(META_KEY);
-
- if (null == childParentMap) {
- childParentMap = new HashMap<Integer, Integer>();
- }
- int pid = res.getParentResource() == null ? 0 : res.getParentResource().getId();
- childParentMap.put(res.getId(), pid);
- cache.put(META_KEY, childParentMap);
-
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
- }
-
- protected List<Resource> getResourcesFromCacheByParentId(int pid) {
- List<Integer> candidateIds = new ArrayList<Integer>();
- List<Resource> ret = new ArrayList<Resource>();
-
- // First determine candidate children
- Map<Integer, Integer> childParentMap = (Map<Integer, Integer>) cache.get(META_KEY);
-
- if (null != childParentMap) {
- try {
- for (Map.Entry<Integer, Integer> entry : childParentMap.entrySet()) {
- if (entry.getValue() == pid)
- candidateIds.add(entry.getKey());
- }
- // then see if the current user can see them
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
- Iterator<Integer> iter = candidateIds.iterator();
- while (iter.hasNext()) {
- Integer resId = iter.next();
- if (!visibleResources.contains(resId)) {
- iter.remove();
- }
- }
-
- // Last but not least, get the resources and return them
- for (Integer resId : candidateIds) {
- ret.add(getFromCache(resId, Resource.class));
- }
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
-
- }
- return ret;
- }
-
- protected Resource getResourceFromCache(int resourceid) {
-
- Resource res = null;
- // check if the current user can see the resource
- CacheKey callerKey = new CacheKey("rhq.rest.caller", caller.getId());
- Set<Integer> visibleResources = (Set<Integer>) cache.get(callerKey);
- if (null != visibleResources) {
- try {
- if (visibleResources.contains(resourceid)) {
- res = getFromCache(resourceid, Resource.class);
- }
- } catch (Exception e) {
- log.warn(e.getMessage());
- }
- }
-
- return res;
- }
/**
* Remove an item from the cache
@@ -393,6 +309,7 @@ public class AbstractRestBean {
uriBuilder.path("/resource/{id}/children");
uri = uriBuilder.build(res.getId());
link = new Link("children", uri.toString());
+ rwt.addLink(link);
uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/resource/{id}/alerts");
uri = uriBuilder.build(res.getId());
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index acbb492..355adcd 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -1434,6 +1434,8 @@ public class AlertTest extends AbstractBase {
int definitionId = createEmptyAlertDefinition(true);
+ int alertId;
+
// Now add a condition
try {
@@ -1481,7 +1483,7 @@ public class AlertTest extends AbstractBase {
// wait a little
Thread.sleep(5000);
- int alertId =
+ alertId =
given()
.header(acceptJson)
.queryParam("definitionId",definitionId)
@@ -1543,9 +1545,32 @@ public class AlertTest extends AbstractBase {
.when()
.get("/resource/{resourceId}/alerts");
+ if (alertId>0) {
+ // Acknowledge the alert
+ given()
+ .header(acceptWrappedJson)
+ .pathParam("id", alertId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .put("/alert/{id}");
+
+ Thread.sleep(500);
+
+ // purge the alert
+ given()
+ .header(acceptJson)
+ .pathParam("id", alertId)
+ .expect()
+ .statusCode(204)
+ .log().ifError()
+ .when()
+ .delete("/alert/{id}");
+ }
}
-
finally {
+
// delete the definition again
cleanupDefinition(definitionId);
}
commit e290b1316861f301f25cdef2e537751eb5eed689
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Thu May 23 22:21:32 2013 +0200
rhq irc bot: disabling the !pto and !support commands on Freenode channel
diff --git a/etc/rhq-ircBot/pom.xml b/etc/rhq-ircBot/pom.xml
index 6e66187..a6ab873 100644
--- a/etc/rhq-ircBot/pom.xml
+++ b/etc/rhq-ircBot/pom.xml
@@ -8,7 +8,7 @@
<groupId>org.rhq.etc</groupId>
<artifactId>rhq-ircbot</artifactId>
- <version>1.0</version>
+ <version>1.1</version>
<packaging>jar</packaging>
<name>RHQ IRC Bot</name>
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
index 8a7e578..cd6d43a 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -93,6 +93,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
private final String server;
private final String channel;
+ private final boolean isRedHatChannel;
private String docspaceLogin;
private String docspacePassword;
private BugzillaConnector bzConnector = new BugzillaConnector();
@@ -103,6 +104,7 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
public RhqIrcBotListener(String server, String channel) {
this.server = server;
this.channel = channel;
+ isRedHatChannel = "irc.devel.redhat.com".equals(channel);
StringBuilder commandRegExp = new StringBuilder();
commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
for (Command command : Command.values()) {
@@ -176,7 +178,9 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
while (commandMatcher.find()) {
Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
String response = prepareResponseForCommand(command);
- bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ if (response != null) {
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
}
// ping JON devs
@@ -215,9 +219,12 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
// react to commands included in the messages
Matcher commandMatcher = commandPattern.matcher(message);
while (commandMatcher.find()) {
+ isCommand = true;
Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
String response = prepareResponseForCommand(command);
- bot.sendMessage(privateMessageEvent.getUser(), response);
+ if (response != null) {
+ bot.sendMessage(privateMessageEvent.getUser(), response);
+ }
}
if (!isCommand) {
bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".\n"
@@ -271,8 +278,10 @@ public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
}
switch (command) {
case SUPPORT:
+ if (isRedHatChannel)
return whoIsOnSupport(SUPPORT_LINK);
case PTO:
+ if (isRedHatChannel)
return whoIsOnPto(PTO_LINK);
default:
System.err.println("Unknown command:" + command);
commit b33564602373317e5e73adbc71e0521929e0762e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 23 15:04:09 2013 -0400
BZ 962841 962845 fix the resource type admin pages to support types with multiple parents (i.e. types with <runs-inside>)
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
index 9b4027e..4f790a1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/AlertDefinitionTemplateTypeView.java
@@ -197,14 +197,19 @@ public class AlertDefinitionTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_ENABLED_TEMPLATES, composite.getEnabledAlertCount());
setAttribute(ATTR_DISABLED_TEMPLATES, composite.getDisabledAlertCount());
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED_TEMPLATES, this.getAttributeAsLong(ATTR_ENABLED_TEMPLATES));
+ dup.setAttribute(ATTR_DISABLED_TEMPLATES, this.getAttributeAsLong(ATTR_DISABLED_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
index 143c475..ebb2d9d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/DriftDefinitionTemplateTypeView.java
@@ -211,11 +211,8 @@ public class DriftDefinitionTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_PLUGIN_TEMPLATES, composite.getPluginDriftTemplates());
setAttribute(ATTR_USER_TEMPLATES, composite.getUserDriftTemplates());
// If the type has no plugin templates then drift monitoring is not enabled for the type
@@ -223,6 +220,14 @@ public class DriftDefinitionTemplateTypeView extends ResourceTypeTreeView {
setAttribute(ATTRIB_EDIT, ImageManager.getEditDisabledIcon());
}
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_PLUGIN_TEMPLATES, this.getAttributeAsLong(ATTR_PLUGIN_TEMPLATES));
+ dup.setAttribute(ATTR_USER_TEMPLATES, this.getAttributeAsLong(ATTR_USER_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
index 246a71e..91a4ca2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/IgnoreResourceTypesView.java
@@ -182,6 +182,13 @@ public class IgnoreResourceTypesView extends ResourceTypeTreeView {
super(composite, plugin);
setAttribute(ATTR_ENABLED, ImageManager.getAvailabilityIcon(!composite.getType().isIgnored()));
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED, this.getAttribute(ATTR_ENABLED));
+ return dup;
+ }
}
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
index 19c53d2..e4aa4fe 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/MetricTemplateTypeView.java
@@ -170,11 +170,8 @@ public class MetricTemplateTypeView extends ResourceTypeTreeView {
}
public static class TreeNode extends ResourceTypeTreeNode {
-
public TreeNode(ResourceTypeTemplateCountComposite composite, String plugin) {
-
super(composite, plugin);
-
setAttribute(ATTR_ENABLED_TEMPLATES, composite.getEnabledMetricCount());
setAttribute(ATTR_DISABLED_TEMPLATES, composite.getDisabledMetricCount());
// If the type has no metrics then metric templates are enabled for the type
@@ -182,6 +179,14 @@ public class MetricTemplateTypeView extends ResourceTypeTreeView {
setAttribute(ATTRIB_EDIT, ImageManager.getEditDisabledIcon());
}
}
+
+ @Override
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = super.copy();
+ dup.setAttribute(ATTR_ENABLED_TEMPLATES, this.getAttributeAsLong(ATTR_ENABLED_TEMPLATES));
+ dup.setAttribute(ATTR_DISABLED_TEMPLATES, this.getAttributeAsLong(ATTR_DISABLED_TEMPLATES));
+ return dup;
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
index 72563c2..e90f398 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/templates/ResourceTypeTreeNodeBuilder.java
@@ -18,11 +18,14 @@
*/
package org.rhq.enterprise.gui.coregui.client.admin.templates;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.TreeModelType;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.tree.Tree;
@@ -48,7 +51,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
static private final Messages MSG = CoreGUI.getMessages();
public static final String ATTRIB_ID = "id";
- public static final String ATTRIB_PARENT_ID = "parentId";
+ public static final String ATTRIB_CHILDREN = "children";
public static final String ATTRIB_NAME = "name";
public static final String ATTRIB_PLUGIN = "plugin";
public static final String ATTRIB_CATEGORY = "category";
@@ -67,13 +70,18 @@ public abstract class ResourceTypeTreeNodeBuilder {
@Override
public void onSuccess(Map<Integer, ResourceTypeTemplateCountComposite> result) {
+ // result contains all of our resource types, including the parent hierarchy
HashSet<ResourceTypeListGridRecord> platformsRecords;
HashSet<ResourceTypeListGridRecord> platformServicesRecords;
- HashSet<ResourceTypeTreeNode> treeNodes;
+ HashMap<Integer, ResourceTypeTreeNode> serversNodes; // all server nodes (top level and below)
+ HashSet<Integer> topServers; // those servers that are at the root of the tree
+ HashMap<Integer, ArrayList<Integer>> childrenGraph; // defines the children of all server nodes
platformsRecords = new HashSet<ResourceTypeListGridRecord>();
platformServicesRecords = new HashSet<ResourceTypeListGridRecord>();
- treeNodes = new HashSet<ResourceTypeTreeNode>();
+ serversNodes = new HashMap<Integer, ResourceTypeTreeNode>();
+ topServers = new HashSet<Integer>();
+ childrenGraph = new HashMap<Integer, ArrayList<Integer>>();
for (ResourceTypeTemplateCountComposite composite : result.values()) {
ResourceType type = composite.getType();
@@ -84,7 +92,9 @@ public abstract class ResourceTypeTreeNodeBuilder {
platformsRecords.add(getGridRecordInstance(composite));
} else {
// no parents but not a platform - these are our top-level servers
- treeNodes.add(getTreeNodeInstance(composite, type.getPlugin()));
+ ResourceTypeTreeNode node = getTreeNodeInstance(composite, type.getPlugin());
+ topServers.add(node.getResourceTypeId());
+ serversNodes.put(node.getResourceTypeId(), node);
}
} else {
// has parents; if all the direct parents are top level platforms
@@ -106,22 +116,37 @@ public abstract class ResourceTypeTreeNodeBuilder {
if (isPlatformService) {
platformServicesRecords.add(getGridRecordInstance(composite));
-
} else {
- // in some cases, a top level server is limited to which platforms it can run on.
- // therefore, the parents will not be null/empty (as would be the case if the top level
+ // In some cases, a top level server is limited to which platforms it can run on.
+ // Therefore, the parents will not be null/empty (as would be the case if the top level
// server can run on ALL platforms), but instead it will have the subset of platforms
- // the type is valid on. But its the same type - so we only want to show it once. Therefore,
- // once we see a parent that is a top level platform, we don't add the type again for other
- // top level platforms. That's what gotPlatform boolean tracks.
+ // the type is valid on. But its the same type - so we only want to show it once.
+ // This is what gotPlatform tracks - whether we saw a parent platform or not.
+ //
+ // But we also have the case where a server type can run inside multiple parent server types.
+ // We want to show these under all their parents to make it easier for the user to find them.
boolean gotPlatform = false;
for (ResourceType parentType : type.getParentResourceTypes()) {
- boolean isPlatform = (parentType.getCategory() == ResourceCategory.PLATFORM && isEmpty(parentType
+ boolean isParentAPlatform = (parentType.getCategory() == ResourceCategory.PLATFORM && isEmpty(parentType
.getParentResourceTypes()));
- if (!isPlatform || !gotPlatform) {
- treeNodes.add(getTreeNodeInstance(composite, String.valueOf(parentType.getId())));
+ if (!isParentAPlatform || !gotPlatform) {
+ int parentId = parentType.getId();
+ String parentIdString = String.valueOf(parentId);
+ ResourceTypeTreeNode node = getTreeNodeInstance(composite, parentIdString);
+ serversNodes.put(node.getResourceTypeId(), node);
+ if (isParentAPlatform) {
+ topServers.add(node.getResourceTypeId());
+ } else {
+ // we are a child to other type, add it to the list of children
+ ArrayList<Integer> childList = childrenGraph.get(parentId);
+ if (childList == null) {
+ childList = new ArrayList<Integer>();
+ childrenGraph.put(parentId, childList);
+ }
+ childList.add(node.getResourceTypeId());
+ }
}
- if (isPlatform) {
+ if (isParentAPlatform) {
gotPlatform = true;
}
}
@@ -129,14 +154,50 @@ public abstract class ResourceTypeTreeNodeBuilder {
}
}
+ // now set up our UI components to show the data
+ platformsGrid.setSortField(ATTRIB_NAME);
+ platformServicesGrid.setSortField(ATTRIB_NAME);
+ serversGrid.setSortField(ATTRIB_NAME);
+
platformsGrid.setData(platformsRecords.toArray(new ListGridRecord[platformsRecords.size()]));
platformServicesGrid.setData(platformServicesRecords
.toArray(new ListGridRecord[platformServicesRecords.size()]));
- Tree tree = serversGrid.getTree();
- if (tree != null) {
- TreeNode[] treeNodeArray = treeNodes.toArray(new TreeNode[treeNodes.size()]);
- tree.linkNodes(treeNodeArray);
+ Tree tree = new Tree();
+ tree.setModelType(TreeModelType.CHILDREN);
+ tree.setChildrenProperty(ATTRIB_CHILDREN);
+ TreeNode rootNode = new TreeNode("0");
+ tree.setRoot(rootNode);
+
+ for (Integer topServerId : topServers) {
+ ResourceTypeTreeNode topServerNode = serversNodes.get(topServerId);
+ topServerNode = topServerNode.copy();
+ fillHierarchy(topServerNode, serversNodes, childrenGraph);
+ tree.add(topServerNode, rootNode);
}
+ serversGrid.setData(tree);
+ }
+
+ private void fillHierarchy(ResourceTypeTreeNode node,
+ HashMap<Integer, ResourceTypeTreeNode> serversNodes,
+ HashMap<Integer, ArrayList<Integer>> childrenGraph) {
+
+ if (node.getChildren().length > 0) {
+ return; // we've already populated this node's children before; nothing to do
+ }
+
+ ArrayList<Integer> childrenIds = childrenGraph.get(node.getResourceTypeId());
+ if (childrenIds != null) {
+ for (Integer childrenId : childrenIds) {
+ ResourceTypeTreeNode childNode = serversNodes.get(childrenId);
+ if (childNode != null) { // this should never be null, but this let's us continue if we have a bug
+ childNode = childNode.copy();
+ fillHierarchy(childNode, serversNodes, childrenGraph);
+ node.addChild(childNode);
+ }
+ }
+ }
+
+ return;
}
@Override
@@ -184,25 +245,63 @@ public abstract class ResourceTypeTreeNodeBuilder {
public static class ResourceTypeTreeNode extends TreeNode {
- private String id;
+ private int id;
private String parentId;
+ private TreeNode[] children;
+
+ private ResourceTypeTreeNode() {
+ // for use by copy() method
+ }
protected ResourceTypeTreeNode(ResourceTypeTemplateCountComposite composite, String parentId) {
ResourceType resourceType = composite.getType();
- String id = String.valueOf(resourceType.getId());
- setID(id);
- this.id = id;
-
- setParentID(parentId);
+ this.id = resourceType.getId();
this.parentId = parentId;
setAttribute(ATTRIB_ID, id);
- setAttribute(ATTRIB_PARENT_ID, parentId);
setAttribute(ATTRIB_NAME, resourceType.getName());
setAttribute(ATTRIB_PLUGIN, resourceType.getPlugin());
setAttribute(ATTRIB_CATEGORY, resourceType.getCategory().name());
setAttribute(ATTRIB_EDIT, ImageManager.getEditIcon());
+ setChildren(new TreeNode[0]);
+ }
+
+ public int getResourceTypeId() {
+ return this.id;
+ }
+
+ public TreeNode[] getChildren() {
+ return this.children;
+ }
+
+ @Override
+ public void setChildren(TreeNode[] children) {
+ this.children = children;
+ super.setChildren(children);
+ }
+
+ public void addChild(TreeNode newChild) {
+ TreeNode[] newChildren = new TreeNode[this.children.length + 1];
+ System.arraycopy(this.children, 0, newChildren, 0, this.children.length);
+ newChildren[this.children.length] = newChild;
+ setChildren(newChildren);
+ }
+
+ // clone this object and return it - subclasses should override this to copy their own attributes
+ public ResourceTypeTreeNode copy() {
+ ResourceTypeTreeNode dup = new ResourceTypeTreeNode();
+ dup.id = this.id;
+ dup.parentId = this.parentId;
+ dup.children = this.children;
+
+ dup.setAttribute(ATTRIB_ID, this.getAttributeAsInt(ATTRIB_ID));
+ dup.setAttribute(ATTRIB_NAME, this.getAttribute(ATTRIB_NAME));
+ dup.setAttribute(ATTRIB_PLUGIN, this.getAttribute(ATTRIB_PLUGIN));
+ dup.setAttribute(ATTRIB_CATEGORY, this.getAttribute(ATTRIB_CATEGORY));
+ dup.setAttribute(ATTRIB_EDIT, this.getAttribute(ATTRIB_EDIT));
+
+ return dup;
}
@Override
@@ -216,7 +315,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
ResourceTypeTreeNode that = (ResourceTypeTreeNode) o;
- if (!this.id.equals(that.id)) {
+ if (this.id != that.id) {
return false;
}
if (this.parentId == null) {
@@ -228,7 +327,7 @@ public abstract class ResourceTypeTreeNodeBuilder {
@Override
public int hashCode() {
int result = 31;
- result = result * id.hashCode();
+ result = result * id;
result = result + (parentId != null ? parentId.hashCode() : 0);
return result;
}
commit 6d5e400decd1b55624daedda9a8e0a6814155eda
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 20:40:21 2013 +0200
BZ use explicit paging fields, as there is no default. In the specific case, the 'name' field was not unique and thus 'random within the resources with the same name'
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 4ceae82..305d867 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -79,6 +79,7 @@ import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
@@ -148,11 +149,11 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
public Response listAlertDefinitions(
@ApiParam(value = "Page number") @QueryParam("page") Integer page,
@ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
- @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
+ criteria.addSortId(PageOrdering.ASC);
if (page!=null) {
criteria.setPaging(page,pageSize);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index fd8a835..4f4d6b4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -62,6 +62,7 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.rest.domain.EventDefinitionRest;
@@ -243,6 +244,7 @@ public class EventHandlerBean extends AbstractRestBean {
EventSource source = findEventSourceById(sourceId);
EventCriteria criteria = new EventCriteria();
+ criteria.addSortId(PageOrdering.ASC);
criteria.addFilterSourceId(source.getId());
if (startTime>0) {
criteria.addFilterStartTime(startTime);
@@ -291,6 +293,8 @@ public class EventHandlerBean extends AbstractRestBean {
}
EventCriteria criteria = new EventCriteria();
+ criteria.addSortId(PageOrdering.ASC);
+
criteria.addFilterResourceId(resourceId);
if (startTime>0) {
criteria.addFilterStartTime(startTime);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index d65a850..006c8a0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -27,8 +27,6 @@ import java.util.Set;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
@@ -67,6 +65,7 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupDefinition;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
@@ -105,9 +104,6 @@ public class GroupHandlerBean extends AbstractRestBean {
@EJB
GroupDefinitionManagerLocal definitionManager;
- @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
- EntityManager em;
-
@GZIP
@GET
@@ -119,6 +115,8 @@ public class GroupHandlerBean extends AbstractRestBean {
@Context HttpHeaders headers, @Context UriInfo uriInfo) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
+ criteria.addSortId(PageOrdering.ASC);
+
if (q!=null) {
criteria.addFilterName(q);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 81d490b..d46850c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -401,12 +401,12 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
+ criteria.addSortStartTime(PageOrdering.ASC);
if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
}
if (page!=null) {
criteria.setPaging(page,pageSize);
- criteria.addSortStartTime(PageOrdering.ASC);
}
criteria.addSortEndTime(PageOrdering.DESC);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 0c3a7cd..332dfbc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -188,6 +188,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
@Context UriInfo uriInfo) {
ResourceCriteria criteria = new ResourceCriteria();
+ criteria.addSortName(PageOrdering.ASC);
+ criteria.addSortId(PageOrdering.ASC);
if (!status.toLowerCase().equals("all")) {
try {
criteria.addFilterInventoryStatus(InventoryStatus.valueOf(status.toUpperCase()));
@@ -206,7 +208,6 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
if (page!=null) {
criteria.setPaging(page,pageSize);
- criteria.addSortName(PageOrdering.ASC);
}
PageList<Resource> ret = resMgr.findResourcesByCriteria(caller,criteria);
@@ -232,6 +233,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
else {
pc = PageControl.getUnlimitedInstance();
}
+ pc.setPrimarySort("id",PageOrdering.ASC);
PageList<Resource> ret = resMgr.findResourcesByCategory(caller, ResourceCategory.PLATFORM,
InventoryStatus.COMMITTED, pc);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index cd103ca..900ab10 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -24,11 +24,16 @@ package org.rhq.modules.integrationTests.restApi;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.json.JsonPath;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.element.Node;
import com.jayway.restassured.response.Response;
+import com.jayway.restassured.response.ResponseBody;
import org.apache.http.HttpStatus;
import org.junit.Test;
@@ -73,8 +78,8 @@ public class ResourcesTest extends AbstractBase {
.contentType(ContentType.JSON)
.log().everything()
.body("links.self", notNullValue())
- .body("resourceId",is(_platformId))
- .body("typeId",is(_platformTypeId))
+ .body("resourceId", is(_platformId))
+ .body("typeId", is(_platformTypeId))
.body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -94,8 +99,8 @@ public class ResourcesTest extends AbstractBase {
.contentType(WRAPPED_JSON)
.log().everything()
.body("links.self", notNullValue())
- .body("resourceId",is(_platformId))
- .body("typeId",is(_platformTypeId))
+ .body("resourceId", is(_platformId))
+ .body("typeId", is(_platformTypeId))
.body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -277,13 +282,50 @@ public class ResourcesTest extends AbstractBase {
.statusCode(200)
.log().everything()
// .header("Link", allOf(containsString("page=2"), containsString("current")))
- .header("Link",not(containsString("prev")))
+ .header("Link", not(containsString("prev")))
.body("links.self", notNullValue())
.when()
.get("/resource");
}
@Test
+ public void testGetResourcesWithPagingAndUniquenessCheck() throws Exception {
+
+ int currentPage = 0;
+ Set<Integer> seen = new HashSet<Integer>();
+
+ for(;;) {
+ JsonPath path =
+ given()
+ .header("Accept", "application/vnd.rhq.wrapped+json")
+ .with()
+ .queryParam("page", currentPage)
+ .queryParam("ps", 5) // Unusually small to provoke having more than 1 page
+ .queryParam("status","COMMITTED")
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .get("/resource")
+ .jsonPath();
+
+ List<Integer> ids = path.getList("data.resourceId");
+
+ for (Integer id : ids ) {
+ assert !seen.contains(id);
+ seen.add(id);
+ }
+
+ currentPage++;
+ if (currentPage > path.getInt("lastPage")) {
+ break;
+ }
+ System.out.print("+");
+ }
+ System.out.println();
+ }
+
+ @Test
public void testGetResourcesWithPagingAndWrapping() throws Exception {
given()
@@ -314,7 +356,7 @@ public class ResourcesTest extends AbstractBase {
.log().ifError()
.body("links.self", notNullValue())
.header("Link", not(containsString("prev=")))
- .header("Link", anyOf(containsString("current"),containsString("last")))
+ .header("Link", anyOf(containsString("current"), containsString("last")))
.when().get("/resource/platforms");
}
commit c09b8f16d4a4375a01241f2a1f042f59a9130735
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 23 15:14:23 2013 +0200
Support paging in the body with the appropriate media type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 5652f9f..92d2499 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -448,14 +448,14 @@ public class AbstractRestBean {
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",nextPage);
- builder.header("Link",new Link("next",uriBuilder.build().toString()));
+ builder.header("Link",new Link("next",uriBuilder.build().toString()).rfc5988String());
}
if (page>0) {
int prevPage = page -1;
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",prevPage);
- builder.header("Link", new Link("prev",uriBuilder.build().toString()));
+ builder.header("Link", new Link("prev",uriBuilder.build().toString()).rfc5988String());
}
// A link to the last page
@@ -463,12 +463,12 @@ public class AbstractRestBean {
int lastPage = resultList.getTotalSize() / pc.getPageSize();
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
uriBuilder.replaceQueryParam("page",lastPage);
- builder.header("Link", new Link("last",uriBuilder.build().toString()));
+ builder.header("Link", new Link("last",uriBuilder.build().toString()).rfc5988String());
}
// A link to the current page
uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- builder.header("Link", new Link("current",uriBuilder.build().toString()));
+ builder.header("Link", new Link("current",uriBuilder.build().toString()).rfc5988String());
// Create a total size header
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
index 129ccfa..6eecf3e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/Link.java
@@ -59,4 +59,20 @@ public class Link {
href + "; " +
"rel='" + rel + '\'' ;
}
+
+ /**
+ * Return the link in the format of RFC 5988 Web Linking.
+ *
+ * See <a href="http://tools.ietf.org/html/rfc5988#page-7">RFC 5988 Web Linking</a>
+ * @return String that contains the link with href and rel
+ */
+ public String rfc5988String() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("<")
+ .append(href)
+ .append(">; rel=\"")
+ .append(rel)
+ .append("\"");
+ return builder.toString();
+ }
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
index 40ae7b0..75be637 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
@@ -366,13 +366,13 @@ public class EventTest extends AbstractBase {
Headers headers = response.getHeaders();
int found = 0;
for (String link: headers.getValues("Link")) {
- if (link.contains("rel='last'"))
+ if (link.contains("rel=\"last\""))
found++;
- if (link.contains("rel='prev'"))
+ if (link.contains("rel=\"prev\""))
found++;
- if (link.contains("rel='current'"))
+ if (link.contains("rel=\"current\""))
found++;
- assert !link.contains("rel='next");
+ assert !link.contains("rel=\"next\"");
}
assert found == 3;
commit cd1087a1789973d74b85e7bffa99893a32ea603e
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 22 22:37:33 2013 +0200
Support paging in the body with the appropriate media type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 8e4a826..5652f9f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -35,7 +36,9 @@ import java.util.Set;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.CacheControl;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
@@ -66,6 +69,7 @@ import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.GroupRest;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.MetricSchedule;
+import org.rhq.enterprise.server.rest.domain.PagingCollection;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
/**
@@ -77,12 +81,16 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
* @author Heiko W. Rupp
* @author Jay Shaughnessy
*/
+(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML,"application/vnd.rhq.wrapped+json"})
@javax.annotation.Resource(name = "ISPN", mappedName = "java:jboss/infinispan/rhq")
@SuppressWarnings("unchecked")
public class AbstractRestBean {
protected Log log = LogFactory.getLog(getClass().getName());
+ protected final MediaType wrappedCollectionJsonType = new MediaType("application","vnd.rhq.wrapped+json");
+ protected final String wrappedCollectionJson = "application/vnd.rhq.wrapped+json";
+
private static final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
@javax.annotation.Resource( name = "ISPN")
@@ -468,6 +476,52 @@ public class AbstractRestBean {
}
/**
+ * Wrap the passed collection #resultList in an object with paging information
+ * @param builder ResonseBuilder to add the entity to
+ * @param uriInfo UriInfo to construct paging links
+ * @param originalList The original list to obtain the paging info from
+ * @param resultList The list of result items
+ */
+ protected void wrapForPaging(Response.ResponseBuilder builder, UriInfo uriInfo, final PageList<?> originalList, final Collection resultList) {
+
+ PagingCollection pColl = new PagingCollection(resultList);
+ pColl.setTotalSize(originalList.getTotalSize());
+ PageControl pageControl = originalList.getPageControl();
+ pColl.setPageSize(pageControl.getPageSize());
+ int page = pageControl.getPageNumber();
+ pColl.setCurrentPage(page);
+ pColl.setLastPage(originalList.getTotalSize()/pageControl.getPageSize());
+
+ UriBuilder uriBuilder;
+ if (originalList.getTotalSize() > (page +1 ) * pageControl.getPageSize()) {
+ int nextPage = page +1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",nextPage);
+ pColl.addLink(new Link("next",uriBuilder.build().toString()));
+ }
+ if (page > 0) {
+ int prevPage = page -1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",prevPage);
+ pColl.addLink(new Link("prev",uriBuilder.build().toString()));
+ }
+
+ // A link to the last page
+ if (!pageControl.isUnlimited()) {
+ int lastPage = originalList.getTotalSize() / pageControl.getPageSize();
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",lastPage);
+ pColl.addLink( new Link("last",uriBuilder.build().toString()));
+ }
+
+ // A link to the current page
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ pColl.addLink(new Link("current",uriBuilder.build().toString()));
+
+ builder.entity(pColl);
+ }
+
+ /**
* Fetch the group with the passed id
*
* @param groupId id of the resource group
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 6ea3d03..4ceae82 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -46,6 +46,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.GenericEntity;
+import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
@@ -98,7 +99,6 @@ import org.rhq.enterprise.server.rest.domain.Link;
* AlertHandlerBean
* @author Heiko W. Rupp
*/
-@Produces({"application/json","application/xml","text/plain"})
@Path("/alert")
@Api(value = "Deal with Alert Definitions",description = "This api deals with alert definitions. Everything " +
" is purely experimental at the moment and can change without notice at any time.")
@@ -149,6 +149,7 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam(value = "Page number") @QueryParam("page") Integer page,
@ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
@ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
+ @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
@@ -163,10 +164,17 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
ret.add(adr);
}
- Response.ResponseBuilder builder = Response.ok(ret);
- createPagingHeader(builder,uriInfo,defs);
+ Response.ResponseBuilder builder = Response.ok();
- // TODO media type etc
+ MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
+ builder.type(mediaType);
+
+ if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,defs,ret);
+ } else {
+ createPagingHeader(builder,uriInfo,defs);
+ builder.entity(ret); // TODO generic entity for XML
+ }
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 5da3fb9..5c6a06f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -32,7 +32,6 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
@@ -72,7 +71,6 @@ import org.rhq.enterprise.server.rest.domain.*;
* Deal with alert related stuff
* @author Heiko W. Rupp
*/
-@Produces({"application/json","application/xml","text/html"})
@Path("/alert")
@Api(value = "Deal with Alerts",description = "This api deals with alerts that have fired.")
@Stateless
@@ -148,17 +146,22 @@ public class AlertHandlerBean extends AbstractRestBean {
}
MediaType type = headers.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(type);
if (type.equals(MediaType.TEXT_HTML_TYPE)) {
- builder = Response.ok(renderTemplate("listAlerts.ftl",ret),type);
+ builder.entity(renderTemplate("listAlerts.ftl",ret));
} else {
- GenericEntity<List<AlertRest>> entity = new GenericEntity<List<AlertRest>>(ret) {};
- builder = Response.ok(entity);
+ if (type.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,alerts,ret);
+ }
+ else {
+ GenericEntity<List<AlertRest>> entity = new GenericEntity<List<AlertRest>>(ret) {};
+ builder.entity(entity);
+ createPagingHeader(builder,uriInfo,alerts);
+ }
}
- createPagingHeader(builder,uriInfo,alerts);
-
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index 7402550..fd8a835 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -37,13 +37,11 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
@@ -76,7 +74,6 @@ import org.rhq.enterprise.server.rest.domain.EventSourceRest;
*/
@Path("/event")
@Api("Api that deals with Events (e.g snmp traps, logfile lines)")
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@Stateless
@Interceptors(SetCallerInterceptor.class)
public class EventHandlerBean extends AbstractRestBean {
@@ -348,17 +345,20 @@ public class EventHandlerBean extends AbstractRestBean {
}
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(mediaType);
if (mediaType.equals(MediaType.APPLICATION_XML_TYPE)) {
GenericEntity<List<EventRest>> list = new GenericEntity<List<EventRest>>(restEvents) {};
- builder = Response.ok(list, mediaType);
+ builder.entity(list);
+ createPagingHeader(builder,uriInfo,eventList);
+ } else if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) {
+ builder.entity(restEvents);
+ createPagingHeader(builder,uriInfo,eventList);
}
- else {
- builder = Response.ok(restEvents, mediaType);
+ else {
+ wrapForPaging(builder,uriInfo,eventList,restEvents);
}
- createPagingHeader(builder,uriInfo,eventList);
-
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index be2419b..d65a850 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -37,7 +37,6 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.GenericEntity;
@@ -93,7 +92,6 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@Interceptors(SetCallerInterceptor.class)
@Path("/group")
@Api(value="Deal with groups and DynaGroups", description = "Api that deals with resource groups and group definitions")
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
public class GroupHandlerBean extends AbstractRestBean {
private final Log log = LogFactory.getLog(GroupHandlerBean.class);
@@ -142,12 +140,15 @@ public class GroupHandlerBean extends AbstractRestBean {
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listGroup", list));
}
+ else if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,groups,list);
+ }
else {
GenericEntity<List<GroupRest>> ret = new GenericEntity<List<GroupRest>>(list) {};
builder.entity(ret);
+ createPagingHeader(builder,uriInfo,groups);
}
- createPagingHeader(builder,uriInfo,groups);
return builder.build();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index e32ea03..81d490b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -420,16 +420,19 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
- Response.ResponseBuilder builder;
+ Response.ResponseBuilder builder = Response.ok();
+ builder.type(mediaType);
+
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
- builder = Response.ok(renderTemplate("listOperationHistory.ftl", result));
+ builder.entity(renderTemplate("listOperationHistory.ftl", result));
+ } else if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,histories,result);
} else {
GenericEntity<List<OperationHistoryRest>> res = new GenericEntity<List<OperationHistoryRest>>(result) {};
- builder = Response.ok(res);
+ builder.entity(res);
+ createPagingHeader(builder,uriInfo,histories);
}
- createPagingHeader(builder,uriInfo,histories);
-
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index a783ac8..0c3a7cd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -114,7 +114,6 @@ import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
* Class that deals with getting data about resources
* @author Heiko W. Rupp
*/
-(a)Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
@Path("/resource")
@Api(value="Resource related", description = "This endpoint deals with individual resources, not resource groups")
@Interceptors(SetCallerInterceptor.class)
@@ -263,15 +262,19 @@ public class ResourceHandlerBean extends AbstractRestBean {
Response.ResponseBuilder builder = Response.ok();
builder.type(mediaType);
- createPagingHeader(builder,uriInfo,resources);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listResourceWithType", rwtList));
} else {
- GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList) {
+ if (mediaType.equals(wrappedCollectionJsonType)) {
+ wrapForPaging(builder,uriInfo,resources,rwtList);
+ } else {
+ GenericEntity<List<ResourceWithType>> list = new GenericEntity<List<ResourceWithType>>(rwtList) {
};
- builder.entity(list);
+ builder.entity(list);
+ createPagingHeader(builder,uriInfo,resources);
+ }
}
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java
new file mode 100644
index 0000000..4a0f892
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/PagingCollection.java
@@ -0,0 +1,97 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.rest.domain;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * A wrapper for collections with paging entries
+ * @author Heiko W. Rupp
+ */
+@XmlRootElement
+public class PagingCollection<T> {
+
+ Collection<T> data;
+ int pageSize;
+ int currentPage;
+ int lastPage;
+ int totalSize;
+ List<Link> links = new ArrayList<Link>();
+
+ public PagingCollection(Collection<T> data) {
+ this.data = data;
+ }
+
+ public int getCurrentPage() {
+ return currentPage;
+ }
+
+ public void setCurrentPage(int currentPage) {
+ this.currentPage = currentPage;
+ }
+
+ public Collection<T> getData() {
+ return data;
+ }
+
+ public void setData(Collection<T> data) {
+ this.data = data;
+ }
+
+ public int getLastPage() {
+ return lastPage;
+ }
+
+ public void setLastPage(int lastPage) {
+ this.lastPage = lastPage;
+ }
+
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ public void setPageSize(int pageSize) {
+ this.pageSize = pageSize;
+ }
+
+ public int getTotalSize() {
+ return totalSize;
+ }
+
+ public void setTotalSize(int totalSize) {
+ this.totalSize = totalSize;
+ }
+
+ public List<Link> getLinks() {
+ return links;
+ }
+
+ public void setLinks(List<Link> links) {
+ this.links = links;
+ }
+
+ public void addLink(Link link) {
+ links.add(link);
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 7e20630..3a7e961 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test
+ @Test(enabled = false)
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
index ae4e81d..fd154ef 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
@@ -40,6 +40,7 @@ import static com.jayway.restassured.RestAssured.given;
public abstract class AbstractBase {
static final String APPLICATION_JSON = "application/json";
+ static final String WRAPPED_JSON = "application/vnd.rhq.wrapped+json";
private static final String APPLICATION_XML = "application/xml";
private static final String TEXT_CSV = "text/csv";
private static final String TEXT_HTML = "text/html";
@@ -48,6 +49,7 @@ public abstract class AbstractBase {
static Header acceptXml = new Header("Accept", APPLICATION_XML);
static Header acceptHtml = new Header("Accept", TEXT_HTML);
static Header acceptCsv = new Header("Accept", TEXT_CSV);
+ static Header acceptWrappedJson = new Header("Accept",WRAPPED_JSON);
int _platformId ;
int _platformTypeId;
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index e02a723..acbb492 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -39,6 +39,7 @@ import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.instanceOf;
@@ -116,6 +117,22 @@ public class AlertTest extends AbstractBase {
.get("/alert");
}
+ @Test
+ public void testListAlertsWithPagingAndWrapped() throws Exception {
+
+ given()
+ .header(acceptWrappedJson)
+ .queryParam("ps", 2)
+ .queryParam("page", 0)
+ .expect()
+ .statusCode(200)
+ .header("Link", nullValue())
+ .body("totalSize", notNullValue())
+ .log().ifError()
+ .when()
+ .get("/alert");
+ }
+
@Test
public void testGetAlertCountJson() throws Exception {
@@ -192,6 +209,21 @@ public class AlertTest extends AbstractBase {
}
@Test
+ public void testListAllAlertDefinitionsWithWrapping() throws Exception {
+
+ given()
+ .header(acceptWrappedJson)
+ .log().everything()
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("currentPage", Matchers.notNullValue())
+ .body("totalSize", Matchers.notNullValue())
+ .when()
+ .get("/alert/definitions");
+ }
+
+ @Test
public void testRedirectForDefinition() throws Exception {
given()
.header(acceptJson)
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 3515fac..ebd72c0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -306,13 +306,13 @@ public class ContentTest extends AbstractBase {
.as(List.class);
if (resources!=null && resources.size()>0) {
- int resourceId = resources.get(0).getResourceId();
+ int resourceId = (Integer) ((Map < String,Object>)resources.get(0)).get("resourceId");
given()
.pathParam("id", resourceId)
.queryParam("physical", "true") // Also remove target on the EAP instance
.expect()
- .statusCode(200)
+ .statusCode(204)
.when()
.delete("/resource/{id}");
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
index a4ef048..ef575d1 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
@@ -35,6 +35,8 @@ import org.rhq.modules.integrationTests.restApi.d.GroupDef;
import static com.jayway.restassured.RestAssured.expect;
import static com.jayway.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.iterableWithSize;
@@ -69,17 +71,37 @@ public class GroupTest extends AbstractBase {
@Test
public void testGetGroups() throws Exception {
- expect().statusCode(200)
- .when().get("/group");
+ expect()
+ .statusCode(200)
+ .when()
+ .get("/group");
}
@Test
public void testGetGroupsWithPaging() throws Exception {
given()
+ .header(acceptJson)
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .header("Link", notNullValue())
+ .when()
+ .get("/group");
+ }
+
+ @Test
+ public void testGetGroupsWithPagingWrapped() throws Exception {
+ given()
+ .header(acceptWrappedJson)
.queryParam("page",0)
.queryParam("ps",2)
.expect()
.statusCode(200)
+ .log().ifError()
+ .header("Link",nullValue())
+ .body("pageSize",is(2))
+ .body("currentPage",is(0))
.when()
.get("/group");
}
@@ -87,10 +109,11 @@ public class GroupTest extends AbstractBase {
@Test
public void testGetGroupsQuery() throws Exception {
given()
- .queryParam("q","lala")
+ .queryParam("q", "lala")
.expect()
- .statusCode(200)
- .when().get("/group");
+ .statusCode(200)
+ .when()
+ .get("/group");
}
@Test
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index b66d9b5..cd103ca 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -82,6 +82,27 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testGetPlatformJsonWrapping() {
+
+ // Actually this object should not be wrapped
+ // as it is no list
+ given()
+ .header(acceptWrappedJson)
+ .pathParam("id",_platformId)
+ .expect()
+ .statusCode(200)
+ .contentType(WRAPPED_JSON)
+ .log().everything()
+ .body("links.self", notNullValue())
+ .body("resourceId",is(_platformId))
+ .body("typeId",is(_platformTypeId))
+ .body("parentId",is(0))
+ .when()
+ .get("/resource/{id}");
+
+ }
+
+ @Test
public void testGetPlatformAndTypeJson() {
Integer typeId =
@@ -258,7 +279,26 @@ public class ResourcesTest extends AbstractBase {
// .header("Link", allOf(containsString("page=2"), containsString("current")))
.header("Link",not(containsString("prev")))
.body("links.self", notNullValue())
- .when().get("/resource");
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testGetResourcesWithPagingAndWrapping() throws Exception {
+
+ given()
+ .header("Accept", "application/vnd.rhq.wrapped+json")
+ .with()
+ .queryParam("page", 1)
+ .queryParam("ps", 2) // Unusually small to provoke having more than 1 page
+ .queryParam("category", "service")
+ .expect()
+ .statusCode(200)
+ .log().everything()
+ .body("pageSize",is(2))
+ .body("currentPage",is(1))
+ .when()
+ .get("/resource");
}
@Test
commit e725ed0658bae7bd5f33dbbc4a2b30eb02a6057f
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Wed May 22 19:36:09 2013 +0200
Improvements to RHQ irc bot. New set of commands is now supported.
diff --git a/etc/rhq-ircBot/pom.xml b/etc/rhq-ircBot/pom.xml
index 40b6952..6e66187 100644
--- a/etc/rhq-ircBot/pom.xml
+++ b/etc/rhq-ircBot/pom.xml
@@ -41,7 +41,7 @@
<dependency>
<groupId>org.pircbotx</groupId>
<artifactId>pircbotx</artifactId>
- <version>1.7</version>
+ <version>1.9</version>
</dependency>
<dependency>
@@ -50,6 +50,17 @@
<version>2.0</version>
</dependency>
+ <dependency>
+ <groupId>org.jsoup</groupId>
+ <artifactId>jsoup</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.4</version>
+ </dependency>
</dependencies>
<build>
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
index ce7535f..7e8f563 100644
--- a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBot.java
@@ -1,163 +1,63 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
package org.rhq.etc.ircbot;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.j2bugzilla.base.Bug;
-import com.j2bugzilla.base.BugzillaConnector;
-import com.j2bugzilla.base.BugzillaException;
-import com.j2bugzilla.rpc.GetBug;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Properties;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
-import org.apache.xmlrpc.XmlRpcException;
import org.pircbotx.PircBotX;
-import org.pircbotx.User;
-import org.pircbotx.hooks.Listener;
-import org.pircbotx.hooks.ListenerAdapter;
-import org.pircbotx.hooks.events.DisconnectEvent;
-import org.pircbotx.hooks.events.MessageEvent;
-import org.pircbotx.hooks.events.PrivateMessageEvent;
/**
- * An IRC bot for doing helpful stuff on the Freenode #rhq channel.
+ * @author Jirka Kremser
*
- * @author Ian Springer
*/
-public class RhqIrcBot extends ListenerAdapter {
-
- private static final Pattern BUG_PATTERN = Pattern.compile("(?i)(bz|bug)[ ]*(\\d{6,7})");
- private static final Pattern ECHO_PATTERN = Pattern.compile("(?i)echo[ ]+(.+)");
-
- private static final Set<String> JON_DEVS = new HashSet<String>();
- static {
- JON_DEVS.add("ccrouch");
- JON_DEVS.add("ips");
- JON_DEVS.add("jkremser");
- JON_DEVS.add("jsanda");
- JON_DEVS.add("jshaughn");
- JON_DEVS.add("lkrejci");
- JON_DEVS.add("mazz");
- JON_DEVS.add("mtho11");
- JON_DEVS.add("pilhuhn");
- JON_DEVS.add("spinder");
- JON_DEVS.add("stefan_n");
- }
-
- private String server;
- private String channel;
- private BugzillaConnector bzConnector = new BugzillaConnector();
- private Map<Integer, Long> bugLogTimestamps = new HashMap<Integer, Long>();
-
- public RhqIrcBot(String server, String channel) {
- this.server = server;
- this.channel = channel;
- }
-
- @Override
- public void onMessage(MessageEvent event) throws Exception {
- PircBotX bot = event.getBot();
- if (!bot.getNick().equals(bot.getName())) {
- bot.changeNick(bot.getName());
- }
-
- String message = event.getMessage();
- Matcher bugMatcher = BUG_PATTERN.matcher(message);
- while (bugMatcher.find()) {
- int bugId = Integer.valueOf(bugMatcher.group(2));
- GetBug getBug = new GetBug(bugId);
- try {
- bzConnector.executeMethod(getBug);
- } catch (Exception e) {
- bzConnector = new BugzillaConnector();
- bzConnector.connectTo("https://bugzilla.redhat.com");
- try {
- bzConnector.executeMethod(getBug);
- } catch (BugzillaException e1) {
- //e1.printStackTrace();
- Throwable cause = e1.getCause();
- String details = (cause instanceof XmlRpcException) ? cause.getMessage() : e1.getMessage();
- bot.sendMessage(event.getChannel(), "Failed to access BZ " + bugId + ": " + details);
- continue;
- }
- }
- Bug bug = getBug.getBug();
- if (bug != null) {
- String product = bug.getProduct();
- if (product.equals("RHQ Project")) {
- product = "RHQ";
- } else if (product.equals("JBoss Operations Network")) {
- product = "JON";
- }
- Long timestamp = bugLogTimestamps.get(bugId);
- if ((timestamp == null) || ((System.currentTimeMillis() - timestamp) > (5 * 60 * 1000L))) {
- bot.sendMessage(event.getChannel(), "BZ " + bugId + " [product=" + product
- + ", priority=" + bug.getPriority() + ", status=" + bug.getStatus() + "] "
- + bug.getSummary() + " [ https://bugzilla.redhat.com/" + bugId + " ]");
- }
- bugLogTimestamps.put(bugId, System.currentTimeMillis());
- } else {
- bot.sendMessage(event.getChannel(), "BZ " + bugId + " does not exist.");
- }
- }
-
- if (message.matches(".*\\b(jon-team|jboss-on-team)\\b.*")) {
- Set<User> users = bot.getUsers(event.getChannel());
- StringBuilder presentJonDevs = new StringBuilder();
- for (User user : users) {
- String nick = user.getNick();
- if (JON_DEVS.contains(nick) && !nick.equals(event.getUser().getNick())) {
- presentJonDevs.append(nick).append(' ');
- }
- }
- bot.sendMessage(event.getChannel(), presentJonDevs + ": see message from "
- + event.getUser().getNick() + " above");
- }
+public class RhqIrcBot extends PircBotX {
+
+ private static final String TRUSTSTORE_NAME = "cacerts.jks";
+
+ public RhqIrcBot(RhqIrcBotListener rhqBot) {
+ setName("rhq-bot");
+ setVersion("1.1");
+ setFinger("RHQ IRC bot (source code in RHQ git under etc/rhq-ircBot/)");
+
+ setVerbose(true);
+ setAutoNickChange(true);
+
+ getListenerManager().addListener(rhqBot);
+ setSocketTimeout(1 * 60 * 1000); // 1 minute
}
-
- @Override
- public void onPrivateMessage(PrivateMessageEvent privateMessageEvent) throws Exception {
- PircBotX bot = privateMessageEvent.getBot();
- String message = privateMessageEvent.getMessage();
- Matcher echoMatcher = ECHO_PATTERN.matcher(message);
- if (echoMatcher.matches()) {
- String echoMessage = echoMatcher.group(1);
- bot.sendMessage(this.channel, echoMessage);
- } else {
- bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".");
- }
- // TODO: Implement a HELP command.
- }
-
- @Override
- public void onDisconnect(DisconnectEvent disconnectEvent) throws Exception {
- boolean connected = false;
- while (!connected) {
- Thread.sleep(60 * 1000L); // 1 minute
- try {
- PircBotX newBot = createBot(this);
- newBot.connect(this.server);
- newBot.joinChannel(this.channel);
-
- connected = true;
- } catch (Exception e) {
- System.err.println("Failed to reconnect to " + disconnectEvent.getBot().getServer() + " IRC server: " + e);
- }
- }
-
- // Try to clean up the old bot, so it can release any memory, sockets, etc. it's using.
- PircBotX oldBot = disconnectEvent.getBot();
- Set<Listener> oldListeners = new HashSet<Listener>(oldBot.getListenerManager().getListeners());
- for (Listener oldListener : oldListeners) {
- oldBot.getListenerManager().removeListener(oldListener);
- }
- }
-
+
public static void main(String[] args) throws Exception {
- if (args.length != 2) {
- System.err.println("Usage: RhqIrcBot IRC_SERVER IRC_CHANNEL");
+ if (args.length != 2 && args.length != 3) {
+ System.err.println("Usage: RhqIrcBot IRC_SERVER IRC_CHANNEL [rhq-ircBot.properties]");
System.err.println(" e.g.: RhqIrcBot irc.freenode.net '#rhq'");
System.exit(1);
}
@@ -167,26 +67,62 @@ public class RhqIrcBot extends ListenerAdapter {
channel = '#' + channel;
}
- RhqIrcBot rhqBot = new RhqIrcBot(server, channel);
+ RhqIrcBotListener rhqBotListener = new RhqIrcBotListener(server, channel);
+ if (args.length == 3) {
+ File propertyFile = new File(args[2]);
+ if (!propertyFile.exists()) {
+ System.err.println("Provided property file [" + args[2] + "] does not exist");
+ System.exit(2);
+ }
+ Properties properties = new Properties();
+ FileInputStream fis = new FileInputStream(propertyFile);
+ properties.load(fis);
+ String docspaceLogin = properties.getProperty("docspace_login");
+ String docspacePassword = properties.getProperty("docspace_password");
+ if (docspaceLogin == null || docspaceLogin.isEmpty() || docspacePassword == null || docspacePassword.isEmpty()) {
+ System.err.println("The property format has bad format");
+ System.err.println("It must contain following key-value pairs\n");
+ System.err.println("docspace_login=X");
+ System.err.println("docspace_password=Y");
+ System.exit(3);
+ }
+ fis.close();
+
+ setupTrustStore();
+
+ rhqBotListener.setDocspaceLogin(docspaceLogin);
+ rhqBotListener.setDocspacePassword(docspacePassword);
+ }
- PircBotX bot = createBot(rhqBot);
+ PircBotX bot = new RhqIrcBot(rhqBotListener);
bot.connect(server);
bot.joinChannel(channel);
}
-
- private static PircBotX createBot(RhqIrcBot rhqBot) {
- PircBotX bot = new PircBotX();
-
- bot.setName("rhq-bot");
- bot.setVersion("1.0");
- bot.setFinger("RHQ IRC bot (source code in RHQ git under etc/rhq-ircBot/)");
-
- bot.setVerbose(true);
- bot.setAutoNickChange(true);
-
- bot.getListenerManager().addListener(rhqBot);
- bot.setSocketTimeout(1 * 60 * 1000); // 1 minute
- return bot;
+
+ private static void setupTrustStore() {
+ TrustManagerFactory trustManagerFactory;
+ try {
+ trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore keystore;
+ keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ InputStream keystoreStream = RhqIrcBot.class.getResourceAsStream(TRUSTSTORE_NAME);
+ keystore.load(keystoreStream, "rhqirc".toCharArray());
+ trustManagerFactory.init(keystore);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+ SSLContext ctx = SSLContext.getInstance("SSL");
+ ctx.init(null, trustManagers, null);
+
+ SSLContext.setDefault(ctx);
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ } catch (KeyStoreException e) {
+ e.printStackTrace();
+ } catch (CertificateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (KeyManagementException e) {
+ e.printStackTrace();
+ }
}
-
}
diff --git a/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
new file mode 100644
index 0000000..8a7e578
--- /dev/null
+++ b/etc/rhq-ircBot/src/main/java/org/rhq/etc/ircbot/RhqIrcBotListener.java
@@ -0,0 +1,357 @@
+package org.rhq.etc.ircbot;
+
+import java.io.IOException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.j2bugzilla.base.Bug;
+import com.j2bugzilla.base.BugzillaConnector;
+import com.j2bugzilla.base.BugzillaException;
+import com.j2bugzilla.rpc.GetBug;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.xmlrpc.XmlRpcException;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.pircbotx.PircBotX;
+import org.pircbotx.User;
+import org.pircbotx.hooks.Listener;
+import org.pircbotx.hooks.ListenerAdapter;
+import org.pircbotx.hooks.events.DisconnectEvent;
+import org.pircbotx.hooks.events.MessageEvent;
+import org.pircbotx.hooks.events.NickChangeEvent;
+import org.pircbotx.hooks.events.PrivateMessageEvent;
+
+/**
+ * An IRC bot for doing helpful stuff on the Freenode #rhq channel.
+ *
+ * @author Ian Springer
+ * @author Jiri Kremser
+ */
+public class RhqIrcBotListener extends ListenerAdapter<RhqIrcBot> {
+
+ private static final Pattern BUG_PATTERN = Pattern.compile("(?i)(bz|bug)[ ]*(\\d{6,7})");
+ private static final Pattern COMMIT_PATTERN = Pattern.compile("(?i)(\\!commit|cm)[ ]*([0-9a-f]{3,40})");
+ private static final Pattern ECHO_PATTERN = Pattern.compile("(?i)echo[ ]+(.+)");
+ private static final String SUPPORT_LINK = "https://docspace.corp.redhat.com/docs/DOC-124477";
+ private static final String COMMIT_LINK = "https://git.fedorahosted.org/cgit/rhq/rhq.git/commit/?id=%s";
+ private static final String PTO_LINK = "https://mail.corp.redhat.com/home/ccrouch@redhat.com/JBoss%20ON%20OOO?fmt...";
+ private static final DateFormat monthFormat = new SimpleDateFormat("MMM");
+ private static final DateFormat dayInMonthFormat = new SimpleDateFormat("d");
+
+ private static enum Command {
+
+ FORUM("Our forum is available from https://community.jboss.org/en/rhq?view=discussions", true),
+ HELP("You can use one of the following commands: ", true),
+ LISTS("Feel free to enroll to the user list https://lists.fedorahosted.org/mailman/listinfo/rhq-users"
+ + " or the devel list https://lists.fedorahosted.org/mailman/listinfo/rhq-devel", true),
+ LOGS("IRC logs are available from http://transcripts.jboss.org/channel/irc.freenode.org/%23rhq/index.html", true),
+ PTO,
+ SOURCE("The code could be viewed/cloned on https://github.com/rhq-project or https://git.fedorahosted.org/cgit/rhq/rhq.git/", true),
+ SUPPORT,
+ WIKI("Our wiki is available from https://docs.jboss.org/author/display/RHQ/Home", true);
+
+ public static final char PREFIX = '!';
+ private final String staticRespond;
+ private final boolean includeInHelp;
+
+ Command(String staticRespond, boolean includeInHelp) {
+ this.staticRespond = staticRespond;
+ this.includeInHelp = includeInHelp;
+ }
+
+ Command() {
+ this(null, false);
+ }
+ }
+
+ private static final Set<String> JON_DEVS = new HashSet<String>();
+ static {
+ JON_DEVS.add("ccrouch");
+ JON_DEVS.add("ips");
+ JON_DEVS.add("jkremser");
+ JON_DEVS.add("jsanda");
+ JON_DEVS.add("jshaughn");
+ JON_DEVS.add("lkrejci");
+ JON_DEVS.add("mazz");
+ JON_DEVS.add("mtho11");
+ JON_DEVS.add("pilhuhn");
+ JON_DEVS.add("spinder");
+ JON_DEVS.add("stefan_n");
+ JON_DEVS.add("tsegismont");
+ }
+
+ private final String server;
+ private final String channel;
+ private String docspaceLogin;
+ private String docspacePassword;
+ private BugzillaConnector bzConnector = new BugzillaConnector();
+ private final Map<Integer, Long> bugLogTimestamps = new HashMap<Integer, Long>();
+ private final Map<String, String> names = new HashMap<String, String>();
+ private final Pattern commandPattern;
+
+ public RhqIrcBotListener(String server, String channel) {
+ this.server = server;
+ this.channel = channel;
+ StringBuilder commandRegExp = new StringBuilder();
+ commandRegExp.append("(?i)\\").append(Command.PREFIX).append("[ ]*(");
+ for (Command command : Command.values()) {
+ commandRegExp.append(command.name()).append('|');
+ }
+ commandRegExp.deleteCharAt(commandRegExp.length() - 1);
+ commandRegExp.append(')');
+ commandPattern = Pattern.compile(commandRegExp.toString());
+ }
+
+ @Override
+ public void onMessage(MessageEvent<RhqIrcBot> event) throws Exception {
+ PircBotX bot = event.getBot();
+ if (!bot.getNick().equals(bot.getName())) {
+ bot.changeNick(bot.getName());
+ }
+
+ // react to BZs in the messages
+ String message = event.getMessage();
+ Matcher bugMatcher = BUG_PATTERN.matcher(message);
+ while (bugMatcher.find()) {
+ int bugId = Integer.valueOf(bugMatcher.group(2));
+ GetBug getBug = new GetBug(bugId);
+ try {
+ bzConnector.executeMethod(getBug);
+ } catch (Exception e) {
+ bzConnector = new BugzillaConnector();
+ bzConnector.connectTo("https://bugzilla.redhat.com");
+ try {
+ bzConnector.executeMethod(getBug);
+ } catch (BugzillaException e1) {
+ //e1.printStackTrace();
+ Throwable cause = e1.getCause();
+ String details = (cause instanceof XmlRpcException) ? cause.getMessage() : e1.getMessage();
+ bot.sendMessage(event.getChannel(), "Failed to access BZ " + bugId + ": " + details);
+ continue;
+ }
+ }
+ Bug bug = getBug.getBug();
+ if (bug != null) {
+ String product = bug.getProduct();
+ if (product.equals("RHQ Project")) {
+ product = "RHQ";
+ } else if (product.equals("JBoss Operations Network")) {
+ product = "JON";
+ }
+ Long timestamp = bugLogTimestamps.get(bugId);
+ if ((timestamp == null) || ((System.currentTimeMillis() - timestamp) > (5 * 60 * 1000L))) {
+ bot.sendMessage(
+ event.getChannel(),
+ "BZ " + bugId + " [product=" + product + ", priority=" + bug.getPriority() + ", status="
+ + bug.getStatus() + "] " + bug.getSummary() + " [ https://bugzilla.redhat.com/" + bugId
+ + " ]");
+ }
+ bugLogTimestamps.put(bugId, System.currentTimeMillis());
+ } else {
+ bot.sendMessage(event.getChannel(), "BZ " + bugId + " does not exist.");
+ }
+ }
+
+ // react to the commit hashs included in the messages
+ Matcher commitMatcher = COMMIT_PATTERN.matcher(message);
+ while (commitMatcher.find()) {
+ String shaHash = commitMatcher.group(2);
+ String response = String.format(COMMIT_LINK, shaHash);
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
+
+ // react to commands included in the messages
+ Matcher commandMatcher = commandPattern.matcher(message);
+ while (commandMatcher.find()) {
+ Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
+ String response = prepareResponseForCommand(command);
+ bot.sendMessage(event.getChannel(), event.getUser().getNick() + ": " + response);
+ }
+
+ // ping JON devs
+ if (message.matches(".*\\b(jon-team|jboss-on-team)\\b.*")) {
+ Set<User> users = bot.getUsers(event.getChannel());
+ StringBuilder presentJonDevs = new StringBuilder();
+ for (User user : users) {
+ String nick = user.getNick();
+ if (JON_DEVS.contains(nick) && !nick.equals(event.getUser().getNick())) {
+ presentJonDevs.append(nick).append(' ');
+ }
+ }
+ bot.sendMessage(event.getChannel(), presentJonDevs + ": see message from " + event.getUser().getNick()
+ + " above");
+ }
+ }
+
+ @Override
+ public void onPrivateMessage(PrivateMessageEvent<RhqIrcBot> privateMessageEvent) throws Exception {
+ PircBotX bot = privateMessageEvent.getBot();
+ String message = privateMessageEvent.getMessage();
+ Matcher echoMatcher = ECHO_PATTERN.matcher(message);
+ if (echoMatcher.matches()) {
+ String echoMessage = echoMatcher.group(1);
+ bot.sendMessage(this.channel, echoMessage);
+ } else if (message.equalsIgnoreCase(Command.PREFIX + "listrenames")) {
+ //Generate a list of renames in the form of old1 changed to new1, old2 changed to new2, etc
+ StringBuilder users = new StringBuilder();
+ for (Map.Entry<String, String> curUser : names.entrySet()) {
+ users.append(curUser.getKey()).append(" changed to ").append(curUser.getValue()).append(", ");
+ }
+ String usersString = users.substring(0, users.length() - 3);
+ privateMessageEvent.respond("Renamed users: " + usersString);
+ } else {
+ boolean isCommand = false;
+ // react to commands included in the messages
+ Matcher commandMatcher = commandPattern.matcher(message);
+ while (commandMatcher.find()) {
+ Command command = Command.valueOf(commandMatcher.group(1).toUpperCase());
+ String response = prepareResponseForCommand(command);
+ bot.sendMessage(privateMessageEvent.getUser(), response);
+ }
+ if (!isCommand) {
+ bot.sendMessage(privateMessageEvent.getUser(), "Hi, I am " + bot.getFinger() + ".\n"
+ + prepareResponseForCommand(Command.HELP));
+ }
+ }
+ }
+
+ @Override
+ public void onDisconnect(DisconnectEvent<RhqIrcBot> disconnectEvent) throws Exception {
+ boolean connected = false;
+ while (!connected) {
+ Thread.sleep(60 * 1000L); // 1 minute
+ try {
+ PircBotX newBot = new RhqIrcBot(this);
+ newBot.connect(this.server);
+ newBot.joinChannel(this.channel);
+
+ connected = true;
+ } catch (Exception e) {
+ System.err.println("Failed to reconnect to " + disconnectEvent.getBot().getServer() + " IRC server: "
+ + e);
+ }
+ }
+
+ // Try to clean up the old bot, so it can release any memory, sockets, etc. it's using.
+ PircBotX oldBot = disconnectEvent.getBot();
+ Set<Listener> oldListeners = new HashSet<Listener>(oldBot.getListenerManager().getListeners());
+ for (Listener oldListener : oldListeners) {
+ oldBot.getListenerManager().removeListener(oldListener);
+ }
+ }
+
+ @Override
+ public void onNickChange(NickChangeEvent<RhqIrcBot> event) throws Exception {
+ //Store the result
+ names.put(event.getOldNick(), event.getNewNick());
+ }
+
+ private String prepareResponseForCommand(Command command) {
+ if (command.staticRespond != null) {
+ String response = command.staticRespond;
+ if (command == Command.HELP) {
+ for (Command com : Command.values()) {
+ if (com.includeInHelp) {
+ response += Command.PREFIX + com.toString().toLowerCase() + " ";
+ }
+ }
+ }
+ return response;
+ }
+ switch (command) {
+ case SUPPORT:
+ return whoIsOnSupport(SUPPORT_LINK);
+ case PTO:
+ return whoIsOnPto(PTO_LINK);
+ default:
+ System.err.println("Unknown command:" + command);
+ break;
+ }
+ return null;
+ }
+
+ private String whoIsOnSupport(String link) {
+ if (docspaceLogin == null || docspaceLogin.isEmpty() || docspacePassword == null || docspacePassword.isEmpty()) {
+ return "This command is not supported.";
+ }
+ String month = monthFormat.format(new Date());
+ String dayInMonth = dayInMonthFormat.format(new Date());
+ int dayInMonthInt = Integer.parseInt(dayInMonth);
+ try {
+ boolean monthFound = false;
+ String login = docspaceLogin + ":" + docspacePassword;
+ String base64login = new String(Base64.encodeBase64(login.getBytes()));
+ Document doc = Jsoup.connect(link).header("Authorization", "Basic " + base64login).get();
+ Elements cells = doc.select("tr td");
+ for (Element cell : cells) {
+ String cellText = cell.text().toLowerCase();
+ if (cellText.startsWith(month.toLowerCase())) {
+ monthFound = true;
+ if (cellText.substring(cellText.length() - 1, cellText.length()).equals(dayInMonth)) {
+ return cell.firstElementSibling().text() + " is on support this week";
+ }
+ continue;
+ }
+ if (monthFound && cellText.equals(dayInMonth)) {
+ return cell.firstElementSibling().text() + " is on support this week";
+ } else if (monthFound) {
+ if (cell.equals(cell.firstElementSibling()) || cell.equals(cell.lastElementSibling())) {
+ continue; //the first row with name or the last row with a comment
+ }
+ int day = -1;
+ try {
+ day = Integer.parseInt(cellText);
+ if (day > dayInMonthInt) {
+ return cell.parent().previousElementSibling().child(0).text() + " is on support this week";
+ }
+ } catch (NumberFormatException nfe) {
+ break; // next month
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ // fallback solution if SSL is not set correctly
+ String randomDevel = JON_DEVS.toArray(new String[JON_DEVS.size()])[new Random().nextInt(JON_DEVS.size())];
+ return "404 Developer Not Found, selecting randomly " + randomDevel + ". Check the " + SUPPORT_LINK;
+ }
+
+ private static String whoIsOnPto(String link) {
+ String month = monthFormat.format(new Date());
+ String dayInMonth = dayInMonthFormat.format(new Date());
+ try {
+ String onPto = "";
+ Document doc = Jsoup.connect(link).ignoreContentType(true).get();
+ Elements dates = doc.getElementsContainingOwnText(dayInMonth + " " + month);
+ for (Element date : dates) {
+ onPto += date.firstElementSibling().text() + ", ";
+ }
+ if (!onPto.isEmpty()) {
+ return onPto.substring(0, onPto.length() - 2);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "noone is on PTO today";
+ }
+
+ public void setDocspaceLogin(String docspaceLogin) {
+ this.docspaceLogin = docspaceLogin;
+ }
+
+ public void setDocspacePassword(String docspacePassword) {
+ this.docspacePassword = docspacePassword;
+ }
+}
diff --git a/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks
new file mode 100644
index 0000000..3d73cbc
Binary files /dev/null and b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/cacerts.jks differ
diff --git a/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties
new file mode 100644
index 0000000..25e325c
--- /dev/null
+++ b/etc/rhq-ircBot/src/main/resources/org/rhq/etc/ircbot/rhq-ircbot.properties
@@ -0,0 +1,2 @@
+docspace_login=
+docspace_password=
commit 6742d1fda892047e45a0b5cffe9df42957318a54
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 22 14:12:32 2013 +0200
Enable paging on (some) endpoints that return lists
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 0038099..8e4a826 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -59,6 +59,8 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.rest.domain.GroupRest;
@@ -419,6 +421,53 @@ public class AbstractRestBean {
}
/**
+ * Create the paging headers for collections and attach them to the passed builder. Those are represented as
+ * <i>Link:</i> http headers that carry the URL for the pages and the respective relation.
+ * <br/>In addition a <i>X-total-size</i> header is created that contains the whole collection size.
+ * @param builder The ResponseBuilder that receives the headers
+ * @param uriInfo The uriInfo of the incoming request to build the urls
+ * @param resultList The collection with its paging information
+ */
+ protected void createPagingHeader(final Response.ResponseBuilder builder, final UriInfo uriInfo, final PageList<?> resultList) {
+
+ UriBuilder uriBuilder;
+
+ PageControl pc = resultList.getPageControl();
+ int page = pc.getPageNumber();
+
+ if (resultList.getTotalSize()> (pc.getPageNumber() +1 ) * pc.getPageSize()) {
+ int nextPage = page+1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",nextPage);
+
+ builder.header("Link",new Link("next",uriBuilder.build().toString()));
+ }
+
+ if (page>0) {
+ int prevPage = page -1;
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",prevPage);
+ builder.header("Link", new Link("prev",uriBuilder.build().toString()));
+ }
+
+ // A link to the last page
+ if (!pc.isUnlimited()) {
+ int lastPage = resultList.getTotalSize() / pc.getPageSize();
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ uriBuilder.replaceQueryParam("page",lastPage);
+ builder.header("Link", new Link("last",uriBuilder.build().toString()));
+ }
+
+ // A link to the current page
+ uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
+ builder.header("Link", new Link("current",uriBuilder.build().toString()));
+
+
+ // Create a total size header
+ builder.header("X-collection-size",resultList.getTotalSize());
+ }
+
+ /**
* Fetch the group with the passed id
*
* @param groupId id of the resource group
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index d203cd3..6ea3d03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -77,6 +77,7 @@ import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
@@ -143,21 +144,31 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@GZIP
@GET
@Path("/definitions")
- @ApiOperation("List all Alert Definition")
- public List<AlertDefinitionRest> listAlertDefinitions(
- @ApiParam(value = "Page number", defaultValue = "0") @QueryParam("page") int page,
- @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status,
+ @ApiOperation(value = "List all Alert Definition", responseClass = "AlertDefinitionRest", multiValueResponse = true)
+ public Response listAlertDefinitions(
+ @ApiParam(value = "Page number") @QueryParam("page") Integer page,
+ @ApiParam(value = "Page size") @DefaultValue("20") @QueryParam("ps") int pageSize,
+ @ApiParam(value = "Limit to status, UNUSED AT THE MOMENT ") @QueryParam("status") String status, // TODO
@Context UriInfo uriInfo) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
- criteria.setPaging(page,20); // TODO add link to next page
- List<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller, criteria);
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+
+ PageList<AlertDefinition> defs = alertDefinitionManager.findAlertDefinitionsByCriteria(caller, criteria);
List<AlertDefinitionRest> ret = new ArrayList<AlertDefinitionRest>(defs.size());
for (AlertDefinition def : defs) {
AlertDefinitionRest adr = definitionToDomain(def, false, uriInfo);
ret.add(adr);
}
- return ret;
+
+ Response.ResponseBuilder builder = Response.ok(ret);
+ createPagingHeader(builder,uriInfo,defs);
+
+ // TODO media type etc
+
+ return builder.build();
}
@GET
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 4c80bd1..5da3fb9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -90,10 +90,10 @@ public class AlertHandlerBean extends AbstractRestBean {
@ApiErrors({
@ApiError(code = 406, reason = "There are 'resourceId' and 'definitionId' passed as query parameters"),
@ApiError(code = 406, reason = "Page size was 0"),
- @ApiError(code = 406, reason = "Page number was < 1")
+ @ApiError(code = 406, reason = "Page number was < 0")
})
public Response listAlerts(
- @ApiParam(value = "Page number") @QueryParam("page") @DefaultValue("1") int page,
+ @ApiParam(value = "Page number") @QueryParam("page") @DefaultValue("0") int page,
@ApiParam(value = "Page size; use -1 for 'unlimited'") @QueryParam("size") @DefaultValue("100")int size,
@ApiParam(value = "Limit to priority", allowableValues = "High, Medium, Low, All") @DefaultValue("All") @QueryParam("prio") String prio,
@ApiParam(value = "Should full resources and definitions be sent") @QueryParam("slim") @DefaultValue("false") boolean slim,
@@ -108,7 +108,7 @@ public class AlertHandlerBean extends AbstractRestBean {
if (size==0) {
throw new BadArgumentException("size","Must not be 0");
}
- if (page<1) {
+ if (page<0) {
throw new BadArgumentException("page","Must be >=1");
}
@@ -120,7 +120,7 @@ public class AlertHandlerBean extends AbstractRestBean {
criteria.setPageControl(pageControl);
}
else {
- criteria.setPaging(page-1, size); // TODO implement linking to next page
+ criteria.setPaging(page, size);
}
if (since!=null) {
@@ -157,6 +157,8 @@ public class AlertHandlerBean extends AbstractRestBean {
builder = Response.ok(entity);
}
+ createPagingHeader(builder,uriInfo,alerts);
+
return builder.build();
}
@@ -306,7 +308,7 @@ public class AlertHandlerBean extends AbstractRestBean {
@DELETE
@Path("/{id}")
- @ApiOperation(value = "Remove the alert from the lit of alerts")
+ @ApiOperation(value = "Remove the alert from the list of alerts")
public void purgeAlert(@ApiParam(value = "Id of the alert to remove") @PathParam("id") int id) {
alertManager.deleteAlerts(caller, new int[]{id});
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
index becb680..7402550 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/EventHandlerBean.java
@@ -32,6 +32,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -44,6 +45,7 @@ import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiError;
@@ -61,6 +63,7 @@ import org.rhq.core.domain.event.EventSource;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.rest.domain.EventDefinitionRest;
@@ -227,9 +230,19 @@ public class EventHandlerBean extends AbstractRestBean {
@QueryParam("endTime") long endTime,
@ApiParam(value="Select the severity to display. Default is to show all",
allowableValues = "DEBUG, INFO, WARN, ERROR, FATAL") @QueryParam("severity") String severity,
- @Context Request request,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @Context UriInfo uriInfo,
@Context HttpHeaders headers) {
+ if (severity!=null) {
+ try {
+ EventSeverity.valueOf(severity.toUpperCase());
+ } catch (Exception e) {
+ throw new BadArgumentException("severity",severity + " is bad. Allowed values are DEBUG, INFO, WARN, ERROR, FATAL");
+ }
+ }
+
EventSource source = findEventSourceById(sourceId);
EventCriteria criteria = new EventCriteria();
@@ -240,13 +253,19 @@ public class EventHandlerBean extends AbstractRestBean {
if (endTime>0) {
criteria.addFilterEndTime(endTime);
}
- if (startTime==0 && endTime==0) {
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+ else if (startTime==0 && endTime==0) {
PageControl pageControl = new PageControl();
pageControl.setPageSize(200);
criteria.setPageControl(pageControl);
}
+ if (severity!=null) {
+ criteria.addFilterSeverities(EventSeverity.valueOf(severity.toUpperCase()));
+ }
- Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria);
+ Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria, uriInfo);
return builder.build();
}
@@ -259,10 +278,21 @@ public class EventHandlerBean extends AbstractRestBean {
public Response getEventsForResource(@PathParam("id") int resourceId,
@QueryParam("startTime") long startTime,
@QueryParam("endTime") long endTime,
- @QueryParam("severity") String severity,
- @Context Request request,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @ApiParam(value="Select the severity to display. Default is to show all",
+ allowableValues = "DEBUG, INFO, WARN, ERROR, FATAL") @QueryParam("severity") String severity,
+ @Context UriInfo uriInfo,
@Context HttpHeaders headers) {
+ if (severity!=null) {
+ try {
+ EventSeverity.valueOf(severity.toUpperCase());
+ } catch (Exception e) {
+ throw new BadArgumentException("severity",severity + " is bad. Allowed values are DEBUG, INFO, WARN, ERROR, FATAL");
+ }
+ }
+
EventCriteria criteria = new EventCriteria();
criteria.addFilterResourceId(resourceId);
if (startTime>0) {
@@ -271,13 +301,19 @@ public class EventHandlerBean extends AbstractRestBean {
if (endTime>0) {
criteria.addFilterEndTime(endTime);
}
- if (startTime==0 && endTime==0) {
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
+ else if (startTime==0 && endTime==0) {
PageControl pageControl = new PageControl();
pageControl.setPageSize(200);
criteria.setPageControl(pageControl);
}
+ if (severity!=null) {
+ criteria.addFilterSeverities(EventSeverity.valueOf(severity.toUpperCase()));
+ }
- Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria);
+ Response.ResponseBuilder builder = getEventsAsBuilderForCriteria(headers, criteria, uriInfo);
return builder.build();
@@ -304,8 +340,8 @@ public class EventHandlerBean extends AbstractRestBean {
}
- private Response.ResponseBuilder getEventsAsBuilderForCriteria(HttpHeaders headers, EventCriteria criteria) {
- List<Event> eventList = eventManager.findEventsByCriteria(caller, criteria);
+ private Response.ResponseBuilder getEventsAsBuilderForCriteria(HttpHeaders headers, EventCriteria criteria, UriInfo uriInfo) {
+ PageList<Event> eventList = eventManager.findEventsByCriteria(caller, criteria);
List<EventRest> restEvents = new ArrayList<EventRest>(eventList.size());
for (Event event : eventList) {
restEvents.add(convertEvent(event));
@@ -320,6 +356,9 @@ public class EventHandlerBean extends AbstractRestBean {
else {
builder = Response.ok(restEvents, mediaType);
}
+
+ createPagingHeader(builder,uriInfo,eventList);
+
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
index 6791bdf..be2419b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/GroupHandlerBean.java
@@ -116,12 +116,17 @@ public class GroupHandlerBean extends AbstractRestBean {
@Path("/")
@ApiOperation(value = "List all groups", multiValueResponse = true, responseClass = "GroupRest")
public Response getGroups(@ApiParam("String to search in the group name") @QueryParam("q") String q,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
@Context HttpHeaders headers, @Context UriInfo uriInfo) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
if (q!=null) {
criteria.addFilterName(q);
}
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ }
PageList<ResourceGroup> groups = resourceGroupManager.findResourceGroupsByCriteria(caller, criteria);
@@ -142,6 +147,8 @@ public class GroupHandlerBean extends AbstractRestBean {
builder.entity(ret);
}
+ createPagingHeader(builder,uriInfo,groups);
+
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index 8bc2cb9..e32ea03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -29,6 +29,7 @@ import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -353,7 +354,6 @@ public class OperationsHandlerBean extends AbstractRestBean {
public Response outcome(
@ApiParam("Name of the submitted job.") @PathParam("id") String jobName,
@Context UriInfo uriInfo,
- @Context Request request,
@Context HttpHeaders httpHeaders) {
MediaType mediaType = httpHeaders.getAcceptableMediaTypes().get(0);
@@ -395,21 +395,26 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,MediaType.TEXT_HTML})
public Response listHistory(
@ApiParam("Id of a resource to limit to") @QueryParam("resourceId") int resourceId,
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
@Context UriInfo uriInfo,
- @Context Request request,
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
}
+ if (page!=null) {
+ criteria.setPaging(page,pageSize);
+ criteria.addSortStartTime(PageOrdering.ASC);
+ }
criteria.addSortEndTime(PageOrdering.DESC);
- PageList<ResourceOperationHistory> list = opsManager.findResourceOperationHistoriesByCriteria(caller, criteria);
+ PageList<ResourceOperationHistory> histories = opsManager.findResourceOperationHistoriesByCriteria(caller, criteria);
List<OperationHistoryRest> result = new ArrayList<OperationHistoryRest>();
- for (ResourceOperationHistory roh : list) {
+ for (ResourceOperationHistory roh : histories) {
OperationHistoryRest historyRest = historyToHistoryRest(roh,uriInfo);
result.add(historyRest);
}
@@ -422,6 +427,9 @@ public class OperationsHandlerBean extends AbstractRestBean {
GenericEntity<List<OperationHistoryRest>> res = new GenericEntity<List<OperationHistoryRest>>(result) {};
builder = Response.ok(res);
}
+
+ createPagingHeader(builder,uriInfo,histories);
+
return builder.build();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 70cc588..a783ac8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -211,7 +211,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
PageList<Resource> ret = resMgr.findResourcesByCriteria(caller,criteria);
- Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers,uriInfo,ret, page, pageSize);
+ Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers,uriInfo,ret);
return builder.build();
}
@@ -221,13 +221,22 @@ public class ResourceHandlerBean extends AbstractRestBean {
@Path("/platforms")
@Cache(isPrivate = true,maxAge = 300)
@ApiOperation(value = "List all platforms in the system", multiValueResponse = true, responseClass = "ResourceWithType")
- public Response getPlatforms(@Context HttpHeaders headers,
- @Context UriInfo uriInfo) {
+ public Response getPlatforms(
+ @ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @Context HttpHeaders headers, @Context UriInfo uriInfo) {
+
+ PageControl pc;
+ if (page!=null) {
+ pc = new PageControl(page,pageSize);
+ }
+ else {
+ pc = PageControl.getUnlimitedInstance();
+ }
- PageControl pc = new PageControl();
PageList<Resource> ret = resMgr.findResourcesByCategory(caller, ResourceCategory.PLATFORM,
InventoryStatus.COMMITTED, pc);
- Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers, uriInfo, ret, null, 20);
+ Response.ResponseBuilder builder = getResponseBuilderForResourceList(headers, uriInfo, ret);
return builder.build();
}
@@ -239,13 +248,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
* @param headers HttpHeaders from the request
* @param uriInfo Uri from the request
* @param resources List of resources
- * @param page Page of pageSize. If null, paging is ignored
- * @param pageSize number of elements on a page
* @return An initialized ResponseBuilder
*/
private Response.ResponseBuilder getResponseBuilderForResourceList(HttpHeaders headers, UriInfo uriInfo,
- PageList<Resource> resources, Integer page,
- int pageSize) {
+ PageList<Resource> resources) {
List<ResourceWithType> rwtList = new ArrayList<ResourceWithType>(resources.size());
for (Resource r : resources) {
putToCache(r.getId(), Resource.class, r);
@@ -256,25 +262,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
Response.ResponseBuilder builder = Response.ok();
builder.type(mediaType);
- UriBuilder uriBuilder;
- if (page!=null) {
- // TODO look a the page control and check if there is a next page at all
- if (resources.getTotalSize()> page*pageSize) {
- int nextPage = page+1;
- uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- uriBuilder.replaceQueryParam("page",nextPage);
-
- builder.header("Link",new Link("next",uriBuilder.build().toString()));
- }
-
- if (page>1) {
- int prevPage = page -1;
- uriBuilder = uriInfo.getRequestUriBuilder(); // adds ?q, ?ps and ?category if needed
- uriBuilder.replaceQueryParam("page",prevPage);
- builder.header("prev",uriBuilder.build().toString());
- }
- }
+ createPagingHeader(builder,uriInfo,resources);
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
builder.entity(renderTemplate("listResourceWithType", rwtList));
@@ -294,7 +283,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiError(code = 404, reason = NO_RESOURCE_FOR_ID)
public ResourceWithChildren getHierarchy(@ApiParam("Id of the resource to start with") @PathParam("id")int baseResourceId) {
// TODO optimize to do less recursion
- Resource start = obtainResource(baseResourceId);
+ Resource start = fetchResource(baseResourceId);
return getHierarchy(start);
}
@@ -425,7 +414,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
if (avail.getResourceId() != resourceId)
throw new IllegalArgumentException("Resource Ids do not match");
- Resource resource = obtainResource(resourceId);
+ Resource resource = fetchResource(resourceId);
AvailabilityType at;
at = AvailabilityType.valueOf(avail.getType());
@@ -541,15 +530,6 @@ public class ResourceHandlerBean extends AbstractRestBean {
}
- private Resource obtainResource(int resourceId) {
- Resource resource = resMgr.getResource(caller, resourceId);
- if (resource == null) {
- resource = resMgr.getResource(caller, resourceId);
- if (resource != null)
- putToCache(resourceId, Resource.class, resource);
- }
- return resource;
- }
@GZIP
@AddLinks
@@ -565,7 +545,7 @@ public class ResourceHandlerBean extends AbstractRestBean {
criteria.addFilterResourceIds(resourceId);
- List<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
+ PageList<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
List<Link> links = new ArrayList<Link>(alerts.size());
for (Alert al : alerts) {
Link link = new Link();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 3a7e961..7e20630 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test(enabled = false)
+ @Test
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index fca0f50..e02a723 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -23,6 +23,7 @@ import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.response.Response;
+import org.hamcrest.Matchers;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.AlertCondition;
@@ -34,7 +35,10 @@ import org.rhq.modules.integrationTests.restApi.d.Group;
import static com.jayway.restassured.RestAssured.delete;
import static com.jayway.restassured.RestAssured.expect;
import static com.jayway.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.instanceOf;
@@ -54,6 +58,7 @@ public class AlertTest extends AbstractBase {
.header(acceptJson)
.expect()
.statusCode(200)
+ .log().ifError()
.when()
.get("/alert");
@@ -66,6 +71,7 @@ public class AlertTest extends AbstractBase {
.header(acceptXml)
.expect()
.statusCode(200)
+ .log().ifError()
.when()
.get("/alert");
}
@@ -95,6 +101,23 @@ public class AlertTest extends AbstractBase {
}
@Test
+ public void testListAlertsWithPaging() throws Exception {
+
+ given()
+ .header(acceptJson)
+ .queryParam("ps", 2)
+ .queryParam("page", 0)
+ .expect()
+ .statusCode(200)
+ .header("Link", anyOf(containsString("current"), Matchers.containsString("last")))
+ .header("X-collection-size", notNullValue())
+ .log().ifError()
+ .when()
+ .get("/alert");
+ }
+
+
+ @Test
public void testGetAlertCountJson() throws Exception {
given()
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
index 2e74181..40ae7b0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/EventTest.java
@@ -23,13 +23,17 @@ import java.util.List;
import java.util.Map;
import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.response.Headers;
import com.jayway.restassured.response.Response;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.Event;
import org.rhq.modules.integrationTests.restApi.d.EventSource;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
import static com.jayway.restassured.RestAssured.given;
/**
@@ -261,6 +265,131 @@ public class EventTest extends AbstractBase {
}
@Test
+ public void testAddGetEventOnSourceWithPaging() throws Exception {
+
+ EventSource es = new EventSource();
+ es.setResourceId(_platformId);
+ es.setName("Event Log"); // Name of the event definition
+ es.setLocation("-x-test-location");
+
+ Response response =
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .pathParam("id",_platformId)
+ .body(es)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/event/{id}/sources");
+
+ EventSource eventSource = response.as(EventSource.class);
+
+ long now = System.currentTimeMillis();
+ try {
+
+ // Add an event
+ Event event = new Event(eventSource.getId(),now,"Li la lu 1:->");
+ Event event1 = new Event(eventSource.getId(),now,"Li la lu 2:->");
+ Event event2 = new Event(eventSource.getId(),now,"Li la lu 3:->");
+ Event event3 = new Event(eventSource.getId(),now,"Li la lu 4:->");
+ List<Event> events = new ArrayList<Event>(4);
+ events.add(event);
+ events.add(event1);
+ events.add(event2);
+ events.add(event3);
+
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .pathParam("id",eventSource.getId())
+ .body(events)
+ .expect()
+ .statusCode(204) // no content returned
+ .log().ifError()
+ .when()
+ .post("/event/source/{id}/events");
+
+
+ // and retrieve it again from the event source
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", eventSource.getId())
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .when()
+ .get("/event/source/{id}/events");
+ List list = response.as(List.class);
+ assert list.size()>0;
+
+ // Get the list of events from the resource
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", _platformId)
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .header("Link",not(containsString("prev")))
+ .when()
+ .get("/event/{id}/events");
+ list = response.as(List.class);
+ assert list.size()==2;
+
+ response =
+ given()
+ .header(acceptJson)
+ .pathParam("id", _platformId)
+ .queryParam("startTime",now - 10)
+ .queryParam("endTime",now + 10)
+ .queryParam("page",1)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .header("X-collection-size", CoreMatchers.is("4"))
+ .header("Link",not(containsString("next")))
+ .when()
+ .get("/event/{id}/events");
+
+ Headers headers = response.getHeaders();
+ int found = 0;
+ for (String link: headers.getValues("Link")) {
+ if (link.contains("rel='last'"))
+ found++;
+ if (link.contains("rel='prev'"))
+ found++;
+ if (link.contains("rel='current'"))
+ found++;
+ assert !link.contains("rel='next");
+ }
+ assert found == 3;
+
+ }
+ finally {
+
+ // Delete the source again
+ given()
+ .pathParam("id", eventSource.getId())
+ .expect()
+ .statusCode(204)
+ .when()
+ .delete("/event/source/{id}");
+ }
+ }
+
+ @Test
public void testDeleteUnknownSource() throws Exception {
given()
.pathParam("id", 123)
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
index 05bae96..a4ef048 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/GroupTest.java
@@ -74,6 +74,17 @@ public class GroupTest extends AbstractBase {
}
@Test
+ public void testGetGroupsWithPaging() throws Exception {
+ given()
+ .queryParam("page",0)
+ .queryParam("ps",2)
+ .expect()
+ .statusCode(200)
+ .when()
+ .get("/group");
+ }
+
+ @Test
public void testGetGroupsQuery() throws Exception {
given()
.queryParam("q","lala")
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 23480a0..b66d9b5 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -44,6 +44,8 @@ import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.not;
/**
* Test the resources part
@@ -242,7 +244,7 @@ public class ResourcesTest extends AbstractBase {
}
@Test
- public void testPaging() throws Exception {
+ public void testGetResourcesWithPaging() throws Exception {
given()
.header("Accept", "application/json")
@@ -252,12 +254,31 @@ public class ResourcesTest extends AbstractBase {
.queryParam("category", "service")
.expect()
.statusCode(200)
- .header("Link", containsString("page=2"))
+ .log().everything()
+ // .header("Link", allOf(containsString("page=2"), containsString("current")))
+ .header("Link",not(containsString("prev")))
.body("links.self", notNullValue())
.when().get("/resource");
}
@Test
+ public void testGetPlatformsWithPaging() throws Exception {
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("page", 0)
+ .queryParam("ps", 5)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .body("links.self", notNullValue())
+ .header("Link", not(containsString("prev=")))
+ .header("Link", anyOf(containsString("current"),containsString("last")))
+ .when().get("/resource/platforms");
+ }
+
+ @Test
public void testGetPlatformXml() {
assert _platformId!=0 : "Setup did not run or was no success";
commit e5d22cac1559f8f2dc699d3ebe3f54d0abf74a1a
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue May 21 22:10:26 2013 +0200
BZ 962853 - make getRresourceId return an int instead of a string.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 703e897..8273737 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -25,19 +25,11 @@ package org.rhq.enterprise.server.rest.domain;
import java.util.ArrayList;
import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementRef;
-import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlRootElement;
import com.wordnik.swagger.annotations.ApiClass;
import com.wordnik.swagger.annotations.ApiProperty;
-import org.jboss.resteasy.spi.touri.URITemplate;
-
/**
* A (partial) resource with some type information
* @author Heiko W. Rupp
@@ -69,7 +61,6 @@ public class ResourceWithType {
}
@ApiProperty("Name of the resource")
- @XmlElement
public String getResourceName() {
return resourceName;
}
@@ -79,17 +70,15 @@ public class ResourceWithType {
}
@ApiProperty("ID of the resource")
- @XmlID
- public String getResourceId() {
- return String.valueOf(resourceId);
+ public int getResourceId() {
+ return resourceId;
}
public void setResourceId(int resourceId) {
this.resourceId = resourceId;
}
- @ApiProperty("Name of the resource type of teh resource")
- @XmlElement
+ @ApiProperty("Name of the resource type of the resource")
public String getTypeName() {
return typeName;
}
@@ -99,7 +88,6 @@ public class ResourceWithType {
}
@ApiProperty("Id of the resource type of the resource")
- @XmlElement
public Integer getTypeId() {
return typeId;
}
@@ -109,7 +97,6 @@ public class ResourceWithType {
}
@ApiProperty("Name of the plugin defining the resource type")
- @XmlElement
public String getPluginName() {
return pluginName;
}
@@ -136,7 +123,6 @@ public class ResourceWithType {
this.status = status;
}
- @XmlElementRef
public List<Link> getLinks() {
return links;
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
index 9f6a02b..ae4e81d 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AbstractBase.java
@@ -98,8 +98,7 @@ public abstract class AbstractBase {
if (res!=null && res.get(0)!=null) {
- String tmp = ((Map <String,String>)res.get(0)).get("resourceId");
- int pid =Integer.valueOf(tmp);
+ Integer pid = ((Map <String,Integer>)res.get(0)).get("resourceId");
given()
.pathParam("id", pid)
@@ -125,9 +124,9 @@ public abstract class AbstractBase {
assert res != null;
for (Object entry : res) {
if (entry instanceof Map) {
- Map<String,String> map = (Map<String, String>) entry;
+ Map<String,Object> map = (Map<String, Object>) entry;
if (!map.get("resourceName").equals(REST_TEST_DUMMY)) {
- return Integer.valueOf(map.get("resourceId"));
+ return (Integer)map.get("resourceId");
}
}
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 7e3f45a..3515fac 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -30,6 +30,7 @@ import com.jayway.restassured.response.Response;
import org.junit.Test;
import org.rhq.modules.integrationTests.restApi.d.CreateCBRRequest;
+import org.rhq.modules.integrationTests.restApi.d.Resource;
import static com.jayway.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
@@ -41,6 +42,8 @@ import static org.hamcrest.Matchers.isOneOf;
*/
public class ContentTest extends AbstractBase {
+ private static final String DEPLOYED_WAR_NAME = "test-simple.war";
+
@Test
public void testUpload() throws Exception {
@@ -144,6 +147,8 @@ public class ContentTest extends AbstractBase {
@Test
public void testCreatePackageBasedResource() throws Exception {
+ wipeWarArchiveIfNecessary();
+
InputStream in =
getClass().getClassLoader().getResourceAsStream("test-simple.war");
@@ -187,7 +192,7 @@ public class ContentTest extends AbstractBase {
assert resources.size()>0;
- int as7Id = Integer.valueOf((String)resources.get(0).get("resourceId"));
+ int as7Id = (Integer)resources.get(0).get("resourceId");
int createdResourceId=-1;
// create child of eap6 as deployment
@@ -203,7 +208,7 @@ public class ContentTest extends AbstractBase {
// set plugin config (path) and deploy config (runtime-name)
resource.getPluginConfig().put("path","deployment");
- resource.getResourceConfig().put("runtimeName","test-simple.war");
+ resource.getResourceConfig().put("runtimeName", DEPLOYED_WAR_NAME);
Response response =
given()
@@ -285,6 +290,34 @@ public class ContentTest extends AbstractBase {
}
+
+ private void wipeWarArchiveIfNecessary() {
+
+ @SuppressWarnings("unchecked")
+ List<Resource> resources =
+ given()
+ .queryParam("q",DEPLOYED_WAR_NAME)
+ .queryParam("category", "SERVICE")
+ .header(acceptJson)
+ .expect()
+ .log().everything()
+ .when()
+ .get("/resource")
+ .as(List.class);
+
+ if (resources!=null && resources.size()>0) {
+ int resourceId = resources.get(0).getResourceId();
+
+ given()
+ .pathParam("id", resourceId)
+ .queryParam("physical", "true") // Also remove target on the EAP instance
+ .expect()
+ .statusCode(200)
+ .when()
+ .delete("/resource/{id}");
+ }
+ }
+
@Test
public void testCreateCBRBadHandle() throws Exception {
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index cc9558b..23480a0 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -69,8 +69,11 @@ public class ResourcesTest extends AbstractBase {
.expect()
.statusCode(200)
.contentType(ContentType.JSON)
- .log().ifError()
+ .log().everything()
.body("links.self", notNullValue())
+ .body("resourceId",is(_platformId))
+ .body("typeId",is(_platformTypeId))
+ .body("parentId",is(0))
.when()
.get("/resource/{id}");
@@ -101,9 +104,9 @@ public class ResourcesTest extends AbstractBase {
.log().everything()
.expect()
.statusCode(200)
- .body("id",is(typeId))
- .body("name",is("Linux"))
- .body("pluginName",is("Platforms"))
+ .body("id", is(typeId))
+ .body("name", is("Linux"))
+ .body("pluginName", is("Platforms"))
.log().everything()
.when()
.get("/resource/type/{typeId}");
@@ -187,7 +190,7 @@ public class ResourcesTest extends AbstractBase {
given()
.header("Accept", "application/json")
.with()
- .queryParam("status","NeW")
+ .queryParam("status", "NeW")
.expect()
.statusCode(200)
.when()
@@ -203,7 +206,7 @@ public class ResourcesTest extends AbstractBase {
.header("Accept", "application/json")
.with()
.queryParam("q", platformName)
- .queryParam("status","Frobnitz")
+ .queryParam("status", "Frobnitz")
.queryParam("category", "platform")
.expect()
.statusCode(406)
@@ -322,6 +325,26 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testCreatePlatformJson() throws Exception {
+
+ Resource resource = new Resource();
+ resource.setResourceName("dummy-test");
+ resource.setTypeName("Linux");
+
+ given()
+ .header(acceptJson)
+ .contentType(ContentType.JSON)
+ .body(resource)
+ .expect()
+ .statusCode(201)
+ .log().everything()
+ .body("resourceId",instanceOf(Number.class))
+ .when()
+ .post("/resource/platforms");
+
+ }
+
+ @Test
public void testCreatePlatformWithBadType() throws Exception {
Resource resource = new Resource();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
index ea78d09..e7e1b9e 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/UserTest.java
@@ -94,7 +94,7 @@ public class UserTest extends AbstractBase {
.when()
.get("/user/favorites/resource");
JsonPath jp = r.jsonPath();
- assert jp.getList("resourceId").contains(String.valueOf(_platformId));
+ assert jp.getList("resourceId").contains(_platformId);
}
finally {
given()
@@ -131,7 +131,7 @@ public class UserTest extends AbstractBase {
.when()
.get("/user/favorites/resource");
JsonPath jp = r.jsonPath();
- assert jp.getList("resourceId").contains(String.valueOf(_platformId));
+ assert jp.getList("resourceId").contains(_platformId);
}
finally {
given()
commit ec4f0228529bf490d44fc3be5407080f9360ef6c
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Tue May 21 21:45:23 2013 +0200
Print the failing class along with the failed field.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index d7cc470..867ea16 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -67,8 +67,8 @@ public final class CriteriaQueryGenerator {
private static final Log LOG = LogFactory.getLog(CriteriaQueryGenerator.class);
public enum AuthorizationTokenType {
- RESOURCE, // specifies the resource alias to join on for standard res-group-role-subject authorization checking
- GROUP; // specifies the group alias to join on for standard group-role-subject authorization checking
+ RESOURCE, // specifies the resource alias to join on for standard res-group-role-subject authorization checking
+ GROUP; // specifies the group alias to join on for standard group-role-subject authorization checking
}
private Criteria criteria;
@@ -333,8 +333,8 @@ public final class CriteriaQueryGenerator {
results.append("FROM ").append(className).append(' ').append(alias).append(NL);
if (countQuery == false) {
- /*
- * don't fetch in the count query to avoid: "query specified join fetching,
+ /*
+ * don't fetch in the count query to avoid: "query specified join fetching,
* but the owner of the fetched association was not present in the select list"
*/
for (String fetchField : getFetchFields(criteria)) {
@@ -383,7 +383,7 @@ public final class CriteriaQueryGenerator {
/*
* do not prefix the alias when:
- *
+ *
* 1) if the suffix is numerical, which allows us to sort by column ordinal
* 2) if the user wants full control and has explicitly chosen to disable alias prepending
*/
@@ -655,7 +655,7 @@ public final class CriteriaQueryGenerator {
} catch (RuntimeException re) {
LOG.error("Could not get JPQL translation for '" + searchExpression + "': "
+ ThrowableUtil.getAllMessages(re, true));
- throw re; // don't wrap exceptions that are already RuntimeExceptions in another RuntimeException
+ throw re; // don't wrap exceptions that are already RuntimeExceptions in another RuntimeException
} catch (Exception e) {
LOG.error("Could not get JPQL translation for '" + searchExpression + "': "
+ ThrowableUtil.getAllMessages(e, true));
@@ -694,7 +694,7 @@ public final class CriteriaQueryGenerator {
Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
persistentBagFields.add(field);
} catch (NoSuchFieldException e) {
- LOG.warn("Failed to add persistent bag collection.", e);
+ LOG.warn("Failed to add persistent bag collection on class [" + criteria.getPersistentClass().getName() +"]: ", e);
}
}
@@ -703,7 +703,7 @@ public final class CriteriaQueryGenerator {
Field field = criteria.getPersistentClass().getDeclaredField(fieldName);
joinFetchFields.add(field);
} catch (NoSuchFieldException e) {
- LOG.warn("Failed to add join fetch field.", e);
+ LOG.warn("Failed to add join fetch field on class [" + criteria.getPersistentClass().getName() + "]: ", e);
}
}
@@ -741,7 +741,7 @@ public final class CriteriaQueryGenerator {
/**
* The groupBy clause can be set if and only if the projection is altered. The passed argument should not be
- * prefixed with 'group by'; that part of the query will be auto-generated if the argument is non-null. The
+ * prefixed with 'group by'; that part of the query will be auto-generated if the argument is non-null. The
* new projection must follow standard rules as they apply to statements with groupBy clauses.
*/
public void setGroupByClause(String groupByClause) {
@@ -753,7 +753,7 @@ public final class CriteriaQueryGenerator {
/**
* The having clause can be set if and only if the groupBy clause is set. The passed argument should not be
- * prefixed with 'having'; that part of the query will be auto-generated if the argument is non-null. The
+ * prefixed with 'having'; that part of the query will be auto-generated if the argument is non-null. The
* having clause must follow standard rules as they apply to statements with groupBy clauses.
*/
public void setHavingClause(String havingClause) {
commit 18aa1bc699a26717acfa2ba9af2ac072aafc2ce3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue May 21 15:06:55 2013 -0400
add jboss logging to eclipse classpath
diff --git a/.classpath b/.classpath
index 53037dd..2487128 100644
--- a/.classpath
+++ b/.classpath
@@ -230,6 +230,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/jboss-common-core/2.2.17.GA/jboss-common-core-2.2.17.GA.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/logging/jboss-logging/3.1.2.GA/jboss-logging-3.1.2.GA.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/servlet/jstl/1.1.2/jstl-1.1.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/struts-menu/struts-menu/2.3/struts-menu-2.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/junit/junit/3.8.2/junit-3.8.2.jar"/>
commit 3ef61c1860a590b16b461b81f85b0011b2ee620d
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon May 20 13:36:45 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - New method for creating an alert definitions was added to SLSB, because the UI requires the ids of newly created alert conditions.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
index b90b209..8fe6d4b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionEditor.java
@@ -140,7 +140,7 @@ public class ConditionEditor extends EnhancedVLayout {
private AlertCondition existingCondition;
public ConditionEditor(HashSet<AlertCondition> conditions, Map<Integer, AlertCondition> modifiedConditions,
- SelectItem conditionExpression, ResourceType rtype, Runnable closeFunc, AlertCondition existingCondition) {
+ SelectItem conditionExpression, ResourceType rtype, AlertCondition existingCondition, Runnable closeFunc) {
super();
this.editMode = existingCondition != null;
this.existingCondition = existingCondition;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
index 782e4b5..8f4a36f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ConditionsEditor.java
@@ -196,7 +196,7 @@ public class ConditionsEditor extends EnhancedVLayout {
}
});
- table.addTableAction(MSG.common_button_edit(), null, new AbstractTableAction(TableActionEnablement.SINGLE) {
+ table.addTableAction(MSG.view_alert_definition_editCondition(), null, new AbstractTableAction(TableActionEnablement.SINGLE) {
public void executeAction(ListGridRecord[] selection, Object actionValue) {
AlertCondition condition = getDataSource().copyValues(selection[0]);
showConditionEditor(condition);
@@ -252,7 +252,7 @@ public class ConditionsEditor extends EnhancedVLayout {
final int numConditions = conditions.size();
final ConditionEditor newConditionEditor = new ConditionEditor(conditions, modifiedConditions,
ConditionsEditor.this.conditionExpression, ConditionsEditor.this.resourceType,
- new Runnable() {
+ existingCondition, new Runnable() {
@Override
public void run() {
updated = updated || numConditions != conditions.size()
@@ -260,7 +260,7 @@ public class ConditionsEditor extends EnhancedVLayout {
winModal.markForDestroy();
refresh();
}
- }, existingCondition);
+ });
winModal.addItem(newConditionEditor);
winModal.show();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
index 2cbe8c6..d69f7f4 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
@@ -197,15 +197,14 @@ public class ResourceAlertDefinitionsView extends AbstractAlertDefinitionsView {
protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals,
final AsyncCallback<AlertDefinition> resultReceiver) {
if (alertDefinition.getId() == 0) {
- GWTServiceLookup.getAlertDefinitionService().createAlertDefinition(alertDefinition,
- Integer.valueOf(resource.getId()), new AsyncCallback<Integer>() {
+ GWTServiceLookup.getAlertDefinitionService().createAlertDefinitionAndReturn(alertDefinition,
+ Integer.valueOf(resource.getId()), new AsyncCallback<AlertDefinition>() {
@Override
- public void onSuccess(Integer result) {
+ public void onSuccess(AlertDefinition result) {
CoreGUI.getMessageCenter().notify(
new Message(MSG.view_alert_definitions_create_success(), Severity.Info));
- alertDefinition.setId(result.intValue());
ResourceAlertDefinitionsView.this.refresh();
- resultReceiver.onSuccess(alertDefinition);
+ resultReceiver.onSuccess(result);
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index c86d0cd..25742f5 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -146,10 +146,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+ unregisterHandler();
setAlertDefinition(getAlertDefinition()); // reverts data back to original
makeViewOnly();
}
@@ -159,6 +156,15 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
addMember(tabSet);
addMember(buttons);
}
+
+ @Override
+ protected void onDraw() {
+ super.onDraw();
+ if (alertDefinition == null || alertDefinition.getId() == 0) {
+ // disable the back button when creating new definition
+ setBackButtonDisabled(true);
+ }
+ }
public AlertDefinition getAlertDefinition() {
return alertDefinition;
@@ -197,8 +203,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
recovery.makeEditable();
dampening.makeEditable();
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
+ unregisterHandler();
handlerRegistration = addVisibilityChangedHandler(new VisibilityChangedHandler() {
public void onVisibilityChanged(VisibilityChangedEvent event) {
if (!event.getIsVisible()) {
@@ -207,15 +212,13 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
if (value) {
save();
}
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
}
});
}
}
});
// disable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(true);
+ setBackButtonDisabled(true);
}
public void makeViewOnly() {
@@ -228,6 +231,7 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
notifications.makeViewOnly();
recovery.makeViewOnly();
dampening.makeViewOnly();
+ setBackButtonDisabled(false);
}
public void saveAlertDefinition() {
@@ -249,20 +253,13 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
new AsyncCallback<AlertDefinition>() {
@Override
public void onSuccess(final AlertDefinition alertDef) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
setAlertDefinition(alertDef);
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+ unregisterHandler();
}
@Override
public void onFailure(Throwable caught) {
- if (handlerRegistration != null)
- handlerRegistration.removeHandler();
- // enable the back button
- ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
-
+ unregisterHandler();
// no error handling, the notification is done in the subclasses of AbstractAlertDefinitionsView
}
});
@@ -270,4 +267,22 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
tabSet.selectTab(generalPropertiesTab);
}
}
+
+ private void setBackButtonDisabled(boolean enabled) {
+ Canvas layoutCandidate = getParentElement();
+ if (layoutCandidate instanceof EnhancedVLayout) {
+ EnhancedVLayout parentLayout = (EnhancedVLayout) getParentElement();
+ Canvas backButton = parentLayout.getMember("backButton");
+ if (backButton != null) {
+ backButton.setDisabled(enabled);
+ }
+ }
+ }
+
+ private void unregisterHandler() {
+ if (handlerRegistration != null) {
+ handlerRegistration.removeHandler();
+ handlerRegistration = null;
+ }
+ }
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
index 0921b2b..794a67f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
@@ -32,6 +32,9 @@ public interface AlertDefinitionGWTService extends RemoteService {
int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException;
+ AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId)
+ throws RuntimeException;
+
AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition, boolean purgeInternals)
throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
index 181eef5..da1d981 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
@@ -66,8 +66,18 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
@Override
public int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
try {
- int results = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(), alertDefinition, resourceId, true);
- return results;
+ int result = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(), alertDefinition, resourceId, true);
+ return result;
+ } catch (Throwable t) {
+ throw getExceptionToThrowToClient(t);
+ }
+ }
+
+ @Override
+ public AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
+ try {
+ AlertDefinition result = alertDefManager.createAlertDefinitionAndRerurnIt(getSessionSubject(), alertDefinition, resourceId, true);
+ return SerialUtility.prepare(result, "createAlertDefinitionAndReturn");
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
@@ -77,9 +87,9 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
public AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition,
boolean resetMatching) throws RuntimeException {
try {
- AlertDefinition results = alertDefManager.updateAlertDefinition(getSessionSubject(), alertDefinitionId,
+ AlertDefinition result = alertDefManager.updateAlertDefinition(getSessionSubject(), alertDefinitionId,
alertDefinition, resetMatching);
- return SerialUtility.prepare(results, "updateAlertDefinition");
+ return SerialUtility.prepare(result, "updateAlertDefinition");
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index d00a969..8f8fec5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -201,19 +201,30 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public int createDependentAlertDefinition(Subject subject, AlertDefinition alertDefinition, int resourceId)
throws InvalidAlertDefinitionException {
-
- return createAlertDefinitionInternal(subject, alertDefinition, resourceId, false, false);
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, false,
+ false);
+ return newAlertDefinition.getId();
}
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean validateNotificationConfiguration)
- throws InvalidAlertDefinitionException {
-
- return createAlertDefinitionInternal(subject, alertDefinition, resourceId, true, validateNotificationConfiguration);
+ public int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
+ validateNotificationConfiguration);
+ return newAlertDefinition.getId();
+ }
+
+ @Override
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
+ validateNotificationConfiguration);
+ return newAlertDefinition;
}
- private int createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ private AlertDefinition createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
checkAlertDefinition(subject, null, alertDefinition, resourceId, validateNotificationConfiguration);
// if this is an resource alert definition, set up the link to a resource
@@ -279,7 +290,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
AlertDefinitionEvent.CREATED);
}
- return alertDefinition.getId();
+ return alertDefinition;
}
private void fixRecoveryId(AlertDefinition definition) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index 5afa1f9..ee0e161 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -65,6 +65,29 @@ public interface AlertDefinitionManagerLocal {
*/
int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean finalizeNotificationConfiguration)
throws InvalidAlertDefinitionException;
+
+ /**
+ * Creates a new alert definition. Note that the suject is checked to have necessary authz, which might not
+ * be what you want in all use cases. See {@link #createDependentAlertDefinition(Subject, AlertDefinition, int)}
+ * for further discussion of this. The only difference between
+ * {@link GroupAlertDefinitionManagerLocal#createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)}
+ * and this method is the return type.
+ *
+ * @param subject the user creating the alert definition
+ * @param alertDefinition the new alert definition to persist
+ * @param resourceId the resource id for which the def is being created
+ * @param finalizeNotificationConfiguration if true, the configuration of the def's notifications is validated.
+ * This is NOT what you want if, for example, you are merely creating a copy of an existing definition.
+ * Some notifications might require more input when creating the notification than is then persisted in their configs
+ * (prominent example being the CLI alert sender).
+ * This would then cause the validation to fail every time you created a copy of a definition and tried
+ * to persist it. Note that passing false AND having new, unpersisted notifications in the alert definition can
+ * lead to invalid configuration being stored for the notifications.
+ * @return the instance of newly created alert definition
+ * @throws InvalidAlertDefinitionException
+ */
+ AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException;
/**
* This is exactly the same as {@link #createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)} but
commit b638cc12a5796b7ccb3789bf94768303b0ce0e3c
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Mon May 20 13:29:43 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - I18n (Instead of "Edit", now the button label says "Edit Condition").
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 00a68ef..b630706 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -977,6 +977,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Trait Value
view_alert_definition_condition_editor_option_operation = Operation Execution
view_alert_definition_condition_editor_option_resource_configuration = Resource Configuration Change
view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = View Group Definition
view_alert_definition_for_type = View Template
view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index a27fb3c..cab205f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -993,6 +993,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Změna hodno
view_alert_definition_condition_editor_option_operation = Spuštění operace
view_alert_definition_condition_editor_option_resource_configuration = Změna konfigurace zdroje
view_alert_definition_condition_editor_resource_configuration_tooltip = Podmínka je splněna, když se změní konfigurace zdroje.
+view_alert_definition_editCondition = Editovat podmínku
view_alert_definition_for_group = Zobrazit definici skupiny
view_alert_definition_for_type = Zobrazit šablonu
view_alert_definition_notification_cliScript_editor_anotherUser = Jiný uživatel
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 902951d..057785a 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -883,6 +883,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Änderung de
view_alert_definition_condition_editor_option_operation = Ausführung der Operation
view_alert_definition_condition_editor_option_resource_configuration = Änderung der Konfiguration der Ressource
##view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = Gruppendefinition ansehen
view_alert_definition_for_type = Vorlage ansehen
view_alert_definition_notification_cliScript_editor_anotherUser = Anderer Benutzer
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index 8f47413..a929966 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -969,6 +969,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = トレイト
view_alert_definition_condition_editor_option_operation = オペレーションの実行
view_alert_definition_condition_editor_option_resource_configuration = リソース構成の変化
view_alert_definition_condition_editor_resource_configuration_tooltip = この条件はリソース構成が変更されると引き起こされます
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = ビューグループ定義
view_alert_definition_for_type = ビューテンプレート
view_alert_definition_notification_cliScript_editor_anotherUser = 別のユーザー
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 5d19d06..da0a8a5 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -846,6 +846,7 @@ view_alert_definition_condition_editor_option_metric_threshold = 측정 절대
view_alert_definition_condition_editor_option_metric_trait_change = 특성값의 변화
view_alert_definition_condition_editor_option_resource_configuration = 자원 구성의 변화
view_alert_definition_condition_editor_resource_configuration_tooltip = 이 조건은 자원 구성이 변경되면 발생합니다.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = 뷰 그룹 정의
view_alert_definition_notification_cliScript_editor_anotherUser = 다른 사용자
view_alert_definition_notification_cliScript_editor_existingScript = 기존의 스크립트
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index 743c4b5..9f342d7 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -977,6 +977,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Mudan\u00E7a
view_alert_definition_condition_editor_option_operation = Execu\u00E7\u00E3o de Opera\u00E7\u00E3o
view_alert_definition_condition_editor_option_resource_configuration = Mudan\u00E7a na Configura\u00E7\u00E3o do Recurso
view_alert_definition_condition_editor_resource_configuration_tooltip = Essa condi\u00E7\u00E3o \u00E9 disparada quando a configura\u00E7\u00E3o do recurso for alterada.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = Visualizar Defini\u00E7\u00E3o de Grupo
view_alert_definition_for_type = Visualizar Template
view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 772c4e4..c8ee796 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -943,6 +943,7 @@
#view_alert_definition_condition_editor_option_operation = Operation Execution
#view_alert_definition_condition_editor_option_resource_configuration = Resource Configuration Change
#view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
#view_alert_definition_for_group = View Group Definition
#view_alert_definition_for_type = View Template
#view_alert_definition_notification_cliScript_editor_anotherUser = Another User
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 03dfa4e..147b9f8 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -963,6 +963,7 @@ view_alert_definition_condition_editor_option_metric_trait_change = Trait Value
view_alert_definition_condition_editor_option_operation = Operation Execution
view_alert_definition_condition_editor_option_resource_configuration = \u8d44\u6e90\u914d\u7f6e\u6539\u53d8
view_alert_definition_condition_editor_resource_configuration_tooltip = This condition is triggered when the resource configuration changes.
+##view_alert_definition_editCondition = Edit Condition
view_alert_definition_for_group = \u67e5\u770b\u7ec4\u5b9a\u4e49
view_alert_definition_for_type = \u67e5\u770b\u6a21\u677f
view_alert_definition_notification_cliScript_editor_anotherUser = \u5176\u4ed6\u7528\u6237
commit edaffb818aec221eb0db5338fcf2e669b06e5a70
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 17 17:09:35 2013 -0400
BZ 963982 - make sure we persist the token when the registration was successful, even if the server endpoint was bad
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
index 6e1a95a..a8d8bdf 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
@@ -1376,6 +1376,7 @@ public class AgentMain {
try {
AgentRegistrationResults results = remote_pojo.registerAgent(request);
failover_list = results.getFailoverList();
+ token = results.getAgentToken(); // make sure our finally block gets this - BZ 963982
// Try to do a simple connect to each server in the failover list
// If only some of the servers are unreachable, just keep going;
@@ -1407,7 +1408,6 @@ public class AgentMain {
m_registration = results;
got_registered = true;
retry = false;
- token = results.getAgentToken();
LOG.info(AgentI18NResourceKeys.AGENT_REGISTRATION_RESULTS, results);
} finally {
// stores the new one if successful; restores the old one if we failed for some reason to register
commit 92fd97dd84324980487972bda6f424114e1e712d
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 17 14:11:32 2013 +0200
BZ 962858 check passed resource id and return 404 if invalid
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 288e9f7..70cc588 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -559,6 +559,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiOperation("Get a list of links to the alerts for the passed resource")
public List<Link> getAlertsForResource(@ApiParam("Id of the resource to query") @PathParam("id") int resourceId) {
AlertCriteria criteria = new AlertCriteria();
+
+ // Check for resource existence
+ fetchResource(resourceId);
+
criteria.addFilterResourceIds(resourceId);
List<Alert> alerts = alertManager.findAlertsByCriteria(caller, criteria);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 3efd807..cc9558b 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -593,6 +593,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAlertsForUnknownResource() throws Exception {
+ given()
+ .header("Accept", "application/json")
+ .pathParam("id", 12345)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/alerts");
+ }
+
+ @Test
public void testSchedulesForResource() throws Exception {
given()
.header("Accept", "application/json")
commit b8207e9ec0efcf679af774e870f1c3b70fafc6fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 17 09:26:14 2013 +0200
Disable for the moment
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
index 7e20630..3a7e961 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -703,7 +703,7 @@ public class ConfigurationHelperTest {
}
- @Test
+ @Test(enabled = false)
public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
Configuration config = new Configuration();
commit 9a040dd824209eb9e71bb22c7cf7d80a7c468485
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Fri May 17 12:41:31 2013 +0200
[BZ 958169] - Modified alert definition is not saved on confirming the save message after clicking on 'Back to List' button - Making the "Back to List" button disabled when editing the alert definition.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
index 14b6abf..d915cb0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/EditAlertDefinitionForm.java
@@ -1,8 +1,5 @@
package org.rhq.enterprise.gui.coregui.client.alert.definitions;
-import java.util.Map;
-
-import org.rhq.core.domain.alert.AlertCondition;
import org.rhq.core.domain.alert.AlertDefinition;
/**
@@ -12,8 +9,6 @@ public interface EditAlertDefinitionForm {
AlertDefinition getAlertDefinition();
-// Map<Integer, AlertCondition> getUpdatedAlertConditions();
-
boolean isResetMatching();
void setAlertDefinition(AlertDefinition alertDef);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
index b4504c9..c86d0cd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/SingleAlertDefinitionView.java
@@ -28,6 +28,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
+import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
@@ -145,7 +146,10 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
cancelButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
setAlertDefinition(getAlertDefinition()); // reverts data back to original
makeViewOnly();
}
@@ -193,6 +197,8 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
recovery.makeEditable();
dampening.makeEditable();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
handlerRegistration = addVisibilityChangedHandler(new VisibilityChangedHandler() {
public void onVisibilityChanged(VisibilityChangedEvent event) {
if (!event.getIsVisible()) {
@@ -201,12 +207,15 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
if (value) {
save();
}
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
}
});
}
}
});
+ // disable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(true);
}
public void makeViewOnly() {
@@ -240,13 +249,21 @@ public class SingleAlertDefinitionView extends EnhancedVLayout {
new AsyncCallback<AlertDefinition>() {
@Override
public void onSuccess(final AlertDefinition alertDef) {
- handlerRegistration.removeHandler();
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
setAlertDefinition(alertDef);
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
}
@Override
public void onFailure(Throwable caught) {
- // nothing, the notification is done in the subclasses of AbstractAlertDefinitionsView
+ if (handlerRegistration != null)
+ handlerRegistration.removeHandler();
+ // enable the back button
+ ((EnhancedVLayout) getParentElement()).getMember("backButton").setDisabled(false);
+
+ // no error handling, the notification is done in the subclasses of AbstractAlertDefinitionsView
}
});
} else {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
index efab26d..41819e1 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/buttons/BackButton.java
@@ -41,6 +41,7 @@ public class BackButton extends StretchImgButton {
public BackButton(String title, final String anchor) {
this();
setTitle("<b>" + title + "</b>");
+ setID("backButton");
addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
CoreGUI.goToView(anchor);
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png
new file mode 100644
index 0000000..c323816
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_end.png differ
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png
new file mode 100644
index 0000000..d6cf484
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_start.png differ
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png
new file mode 100644
index 0000000..2addd3a
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/buttons/back/back_Disabled_stretch.png differ
commit d074bd8fa3daf63342bd5426e8599b0cb8f10cef
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:39 2013 +0200
We don't need standalone-osgi.xml
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 05619cb..e9f3bbe 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -220,6 +220,7 @@
<fileset dir="${jboss.home}/standalone/configuration">
<include name="standalone-ha.xml" />
<include name="standalone.xml" />
+ <include name="standalone-osgi.xml" />
<include name="standalone-full-ha.xml" />
</fileset>
</delete>
commit 4e91d0dc17e549213f61ee6a9251423d65c4ccce
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:23 2013 +0200
Fix a small typo
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 5415ed0..902951d 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1235,7 +1235,7 @@ view_core_uncaught = Es ist eine nicht abgefangene Ausnahme aufgetreten.
view_dashboardManager_deleteFail = Konnte das Dashboard nicht löschen.
view_dashboardManager_deleted = Dashboard {0} erfolgreich gelöscht
view_dashboardManager_error = Konnte das Dashboard nicht auf dem Server sichern
-view_dashboardManager_saved = Das Dashboard {0} wurde auf dem Server geichert
+view_dashboardManager_saved = Das Dashboard {0} wurde auf dem Server gesichert
view_dashboardManager_success = Dashboard gespeichert
view_dashboard_favorites_error1 = Konnte die Ressoucen-Lesezeichen nicht laden
view_dashboardsManager_error1 = Konnte das neue Dashboard nicht hinzufügen
commit ba97ade9666a32cd20e071110c98a45e32d7f9fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu May 16 21:47:08 2013 +0200
BZ 961656 - enable LDAP support for the REST-api as well.
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
index 5caa45e..99e2f4d 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
@@ -39,6 +39,7 @@ public class SecurityDomainJBossASClient extends JBossASClient {
public static final String SECURITY_DOMAIN = "security-domain";
public static final String CACHE_TYPE = "cache-type";
public static final String AUTHENTICATION = "authentication";
+ public static final String LOGIN_MODULE = "login-module";
public static final String LOGIN_MODULES = "login-modules";
public static final String CLASSIC = "classic";
public static final String CODE = "code";
@@ -376,6 +377,36 @@ public class SecurityDomainJBossASClient extends JBossASClient {
return;
}
+ /**
+ * send a :flush-cache operation to the passed security domain
+ * @param domain simple name of the domain
+ * @throws Exception
+ */
+ public void flushSecurityDomainCache(String domain) throws Exception {
+ Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN,domain);
+ ModelNode request = createRequest("flush-cache",addr);
+ ModelNode result = execute(request);
+ if (!isSuccess(result)) {
+ log.warn("Flushing " + domain + " failed - principals may be longer cached than expected");
+ }
+ }
+
+ /**
+ * Check if a certain login module is present inside the passed security domain
+ * @param domainName Name of the security domain
+ * @param moduleName Name of the Login module - wich usually is it FQCN
+ * @return True if the module is present
+ * @throws Exception
+ */
+ public boolean securityDomainHasLoginModule(String domainName, String moduleName) throws Exception {
+ Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN,domainName);
+ addr.add(AUTHENTICATION,CLASSIC);
+ addr.add(LOGIN_MODULE,moduleName);
+ ModelNode request = createRequest("read-resource", addr);
+ ModelNode response = execute(request);
+ return isSuccess(response);
+ }
+
/** Immutable helper */
public static class LoginModuleRequest {
private AppConfigurationEntry entry;
diff --git a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
index 319b990..a98b367 100644
--- a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
+++ b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/jboss-web.xml
@@ -2,4 +2,6 @@
<jboss-web>
<security-domain>RHQRESTSecurityDomain</security-domain>
+ <!-- see https://community.jboss.org/wiki/JBossAS7SecurityAuditing for the next tag -->
+ <!--<disable-audit>false</disable-audit>-->
</jboss-web>
diff --git a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
index fb75d94..b601346 100644
--- a/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-examples-war/src/main/webapp/WEB-INF/web.xml
@@ -10,7 +10,7 @@
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</auth-constraint>
</security-constraint>
@@ -21,7 +21,7 @@
<security-role>
<description>This is valid for all principals, as we do internal checks</description>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</security-role>
</web-app>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
index 1ef5880..28f365f 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/jboss-web.xml
@@ -3,4 +3,6 @@
<jboss-web>
<context-root>rest</context-root>
<security-domain>RHQRESTSecurityDomain</security-domain>
+ <!-- see https://community.jboss.org/wiki/JBossAS7SecurityAuditing for the next tag -->
+ <!--<disable-audit>false</disable-audit>-->
</jboss-web>
diff --git a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
index f96839d..f336c60 100644
--- a/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/rest-war/src/main/webapp/WEB-INF/web.xml
@@ -57,7 +57,7 @@
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</auth-constraint>
</security-constraint>
@@ -68,7 +68,7 @@
<security-role>
<description>This is valid for all principals, as we do internal checks</description>
- <role-name>all</role-name>
+ <role-name>rest-user</role-name>
</security-role>
</web-app>
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 8173e68..0b9c078 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -278,6 +278,9 @@ public class InstallerServiceImpl implements InstallerService {
// Set up the logging subsystem
ServerInstallUtil.configureLogging(mcc, serverProperties);
+ ServerInstallUtil.createUserSecurityDomain(mcc);
+ ServerInstallUtil.createRestSecurityDomain(mcc);
+
// create a keystore whose cert has a CN of this server's public endpoint address
File keystoreFile = ServerInstallUtil.createKeystore(serverDetails != null ? serverDetails
: getServerDetailsFromPropertiesOnly(serverProperties), appServerConfigDir);
@@ -601,7 +604,7 @@ public class InstallerServiceImpl implements InstallerService {
* Save the given properties to the server's .properties file.
*
* Note that this is private - it is not exposed to the installer UI. It should have no need to save
- * this data outside of the normal installation process (see {@link #install()}).
+ * this data outside of the normal installation process (see {@link #install}).
*
* @param serverProperties the server properties to save
* @throws Exception if failed to save the properties to the .properties file
@@ -1013,9 +1016,6 @@ public class InstallerServiceImpl implements InstallerService {
// create the security domain needed by the datasources
ServerInstallUtil.createDatasourceSecurityDomain(mcc, serverProperties);
- // create the security domain needed by REST
- ServerInstallUtil.createRESTSecurityDomain(mcc, serverProperties);
-
// set up REST cache
ServerInstallUtil.createNewCaches(mcc, serverProperties);
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
index d6e0d10..3a19833 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
@@ -38,6 +38,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
+import javax.security.auth.login.AppConfigurationEntry;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.Project;
@@ -133,8 +135,6 @@ public class ServerInstallUtil {
"jboss.management.https.port", 6443));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_MGMT_NATIVE,
"jboss.management.native.port", 6999));
- defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_OSGI_HTTP,
- "rhq.server.socket.binding.port.osgi-http", 7090, false));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_REMOTING,
"rhq.server.socket.binding.port.remoting", 3447));
defaultSocketBindings.add(new SocketBindingInfo(SocketBindingJBossASClient.DEFAULT_BINDING_TXN_RECOVERY_ENV,
@@ -146,7 +146,10 @@ public class ServerInstallUtil {
private static final String RHQ_DATASOURCE_NAME_NOTX = "NoTxRHQDS";
private static final String RHQ_DATASOURCE_NAME_XA = "RHQDS";
private static final String RHQ_DS_SECURITY_DOMAIN = "RHQDSSecurityDomain";
+ private static final String RHQ_USER_SECURITY_DOMAIN = "RHQUserSecurityDomain";
private static final String RHQ_REST_SECURITY_DOMAIN = "RHQRESTSecurityDomain";
+ private static final String JDBC_LOGIN_MODULE_NAME = "org.rhq.enterprise.server.core.jaas.JDBCLoginModule";
+ private static final String DELEGATIG_LOGIN_MODULE_NAME = "org.rhq.enterprise.server.core.jaas.DelegatingLoginModule";
private static final String JDBC_DRIVER_POSTGRES = "postgres";
private static final String JDBC_DRIVER_ORACLE = "oracle";
private static final String JMS_ALERT_CONDITION_QUEUE = "AlertConditionQueue";
@@ -299,6 +302,48 @@ public class ServerInstallUtil {
}
/**
+ * Create the standard user security domain with the JDBCLogin module installed
+ *
+ * @param mcc ModelControllerClient to talk to the underlying AS
+ * @throws Exception If anything goes wrong
+ */
+ public static void createUserSecurityDomain(ModelControllerClient mcc) throws Exception {
+
+ Map<String,String> options = new HashMap<String, String>(2);
+ options.put("hashAlgorithm", "MD5");
+ options.put("hashEncoding", "base64");
+
+ SecurityDomainJBossASClient.LoginModuleRequest loginModuleRequest = new SecurityDomainJBossASClient.LoginModuleRequest(JDBC_LOGIN_MODULE_NAME,
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, options);
+
+
+ SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+ client.createNewSecurityDomain(RHQ_USER_SECURITY_DOMAIN,loginModuleRequest);
+
+ }
+
+ /**
+ * Create a security domain for container managed security used with the rhq-rest.war
+ * @param mcc ModelControllerClient to talk to the underlying AS.
+ * @throws Exception If anything goes wrong
+ */
+ public static void createRestSecurityDomain(ModelControllerClient mcc) throws Exception {
+
+ Map<String,String> options = new HashMap<String, String>(2);
+ options.put("delegateTo", RHQ_USER_SECURITY_DOMAIN);
+ options.put("roles", "rest-user");
+
+ SecurityDomainJBossASClient.LoginModuleRequest loginModuleRequest = new SecurityDomainJBossASClient.LoginModuleRequest(DELEGATIG_LOGIN_MODULE_NAME,
+ AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT, options);
+
+
+ SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+ client.createNewSecurityDomain(RHQ_REST_SECURITY_DOMAIN,loginModuleRequest);
+ }
+
+
+
+ /**
* Creates the JMS Queues required for Drift and Alerting.
*
* @param mcc the JBossAS management client
@@ -367,28 +412,6 @@ public class ServerInstallUtil {
return;
}
- /**
- * Creates the security domain for REST.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the obfuscated password to store in the security domain
- * @throws Exception
- */
- public static void createRESTSecurityDomain(ModelControllerClient mcc, HashMap<String, String> serverProperties)
- throws Exception {
-
- final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final String securityDomain = RHQ_REST_SECURITY_DOMAIN;
- if (!client.isSecurityDomain(securityDomain)) {
- String dsJndiName = "java:jboss/datasources/" + RHQ_DATASOURCE_NAME_XA;
- client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- LOG.info("Security domain [" + securityDomain + "] created");
- } else {
- LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
- }
- }
/**
* Creates the Infinispan caches for RHQ.
@@ -856,7 +879,7 @@ public class ServerInstallUtil {
/**
* Returns a database connection with the given set of properties providing the settings that allow for a successful
* database connection. If <code>props</code> is <code>null</code>, it will use the server properties from
- * {@link #getServerProperties()}.
+ * {@link #getServerProperties}.
*
* @param connectionUrl
* @param userName
@@ -898,7 +921,7 @@ public class ServerInstallUtil {
* Use the internal JBossAS mechanism to de-obfuscate a password back to its
* clear text form. This is not true encryption.
*
- * @param obfuscatedPasswordd the obfuscated password
+ * @param obfuscatedPassword the obfuscated password
* @return the clear-text password
*/
public static String deobfuscatePassword(String obfuscatedPassword) {
@@ -1003,7 +1026,7 @@ public class ServerInstallUtil {
/**
* This will create the database schema in the database. <code>props</code> define the connection to the database -
*
- * <p>Note that if the {@link #isDatabaseSchemaExist(Properties) schema already exists}, it will be purged of all
+ * <p>Note that if the {@link #isDatabaseSchemaExist schema already exists}, it will be purged of all
* data/tables and recreated.</p>
*
* @param props the full set of server properties
@@ -1039,7 +1062,7 @@ public class ServerInstallUtil {
/**
* This will update an existing database schema so it can be upgraded to the latest schema version.
*
- * <p>Note that if the {@link #isDatabaseSchemaExist(Properties) schema does not already exist}, errors will
+ * <p>Note that if the {@link #isDatabaseSchemaExist schema does not already exist}, errors will
* occur.</p>
*
* @param props the full set of server properties
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
index 95dd58f..73eeca5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentService.java
@@ -57,7 +57,6 @@ import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceMBean, MBeanRegistration {
private Log log = LogFactory.getLog(CustomJaasDeploymentService.class.getName());
- private MBeanServer mbeanServer = null;
/**
* Constructor for {@link CustomJaasDeploymentService}.
@@ -70,21 +69,51 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
*/
public void installJaasModules() {
try {
- log.info("Installing RHQ Server's JAAS login modules");
+ log.info("Updating RHQ Server's JAAS login modules");
Properties systemConfig = LookupUtil.getSystemManager().getSystemConfiguration(
LookupUtil.getSubjectManager().getOverlord());
- registerJaasModules(systemConfig);
+ updateJaasModules(systemConfig);
} catch (Exception e) {
log.fatal("Error deploying JAAS login modules", e);
throw new RuntimeException(e);
}
}
+ @Override
+ public void upgradeRhqUserSecurityDomainIfNeeded() {
+ try {
+ Properties systemConfig = LookupUtil.getSystemManager().getSystemConfiguration(
+ LookupUtil.getSubjectManager().getOverlord());
+
+ String value = systemConfig.getProperty(SystemSetting.LDAP_BASED_JAAS_PROVIDER.getInternalName());
+ boolean isLdapAuthenticationEnabled = (value != null) ? RHQConstants.LDAPJAASProvider.equals(value) : false;
+
+ if (isLdapAuthenticationEnabled) {
+
+ ModelControllerClient mcc = null;
+ mcc = ManagementService.getClient();
+ final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
+
+ boolean ldapModulesPresent = client.securityDomainHasLoginModule(RHQ_USER_SECURITY_DOMAIN,
+ "org.rhq.enterprise.server.core.jaas.LdapLoginModule");
+
+
+ if (!ldapModulesPresent) {
+ log.info("Updating RHQ Server's JAAS login modules with LDAP support");
+ updateJaasModules(systemConfig);
+ }
+ }
+ } catch (Exception e) {
+ log.fatal("Error deploying JAAS login modules", e);
+ throw new RuntimeException(e);
+ }
+
+ }
+
/**
* @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer,javax.management.ObjectName)
*/
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
- this.mbeanServer = server;
return name;
}
@@ -107,13 +136,13 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
}
/**
- * Will register the necessary JAAS login Modules. The RHQ_USER_SECURITY_DOMAIN will be created, or recreated
- * if it already exists. This allows us to add/remove ldap support as it is enabled or disabled.
- *
- * @param systemConfig
+ * Will update the necessary JAAS login Modules. The RHQ_USER_SECURITY_DOMAIN will be created, or recreated
+ * if it already exists. This allows us to add/remove ldap support as it is enabled or disabled.
+ *
+ * @param systemConfig System configuration to read the LDAP settings from
* @throws Exception
*/
- private void registerJaasModules(Properties systemConfig) throws Exception {
+ private void updateJaasModules(Properties systemConfig) throws Exception {
ModelControllerClient mcc = null;
try {
@@ -144,7 +173,7 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE, getJdbcOptions(systemConfig));
loginModules.add(jdbcPrincipalCheckLoginModule);
- // this is the LDAP module that checks the LDAP for auth
+ // this is the LDAP module that checks the LDAP for auth
Map<String, String> ldapModuleOptionProperties = getLdapOptions(systemConfig);
try {
validateLdapOptions(ldapModuleOptionProperties);
@@ -170,7 +199,8 @@ public class CustomJaasDeploymentService implements CustomJaasDeploymentServiceM
client.createNewSecurityDomain(RHQ_USER_SECURITY_DOMAIN,
loginModules.toArray(new LoginModuleRequest[loginModules.size()]));
- log.info("Security domain [" + RHQ_USER_SECURITY_DOMAIN + "] created with login modules " + loginModules);
+ client.flushSecurityDomainCache("RHQRESTSecurityDomain");
+ log.info("Security domain [" + RHQ_USER_SECURITY_DOMAIN + "] re-created with login modules " + loginModules);
} catch (Exception e) {
throw new Exception("Error registering RHQ JAAS modules", e);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
index 8d53e2b..47fcc48 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CustomJaasDeploymentServiceMBean.java
@@ -41,4 +41,12 @@ public interface CustomJaasDeploymentServiceMBean {
* Installs the JAAS Modules that JON Server uses to allow users to log in.
*/
void installJaasModules();
+
+ /**
+ * Called from the startup bean and will upgrade an existing
+ * RHQUserSecurityDomain if needed - that is if the system
+ * settings say that LDAP support is enabled, but the underlying
+ * modules are not present
+ */
+ void upgradeRhqUserSecurityDomainIfNeeded();
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index 90ffbaf..7963b26 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -95,7 +95,7 @@ import org.rhq.enterprise.server.util.concurrent.AvailabilityReportSerializer;
* This startup singleton EJB performs the rest of the RHQ Server startup initialization.
* In order for it to do its work properly, we must ensure everything has been deployed and started;
* specifically, all EJBs must have been deployed and available.
- *
+ *
* This bean is not meant for client consumption - it is only for startup initialization.
*/
@Singleton
@@ -195,7 +195,7 @@ public class StartupBean implements StartupLocal {
initScheduler(); // make sure this is initialized before starting the plugin deployer
startPluginDeployer(); // make sure this is initialized before starting the server plugin container
startServerPluginContainer(); // before comm in case an agent wants to talk to it
- installJaasModules();
+ upgradeRhqUserSecurityDomainIfNeeded();
startServerCommunicationServices();
startScheduler();
scheduleJobs();
@@ -396,8 +396,7 @@ public class StartupBean implements StartupLocal {
*
* @throws RuntimeException
*/
- private void installJaasModules() throws RuntimeException {
- log.info("Installing JAAS login modules...");
+ private void upgradeRhqUserSecurityDomainIfNeeded() throws RuntimeException {
try {
CustomJaasDeploymentServiceMBean jaas_mbean;
@@ -406,9 +405,9 @@ public class StartupBean implements StartupLocal {
Class<?> iface = CustomJaasDeploymentServiceMBean.class;
jaas_mbean = (CustomJaasDeploymentServiceMBean) MBeanServerInvocationHandler.newProxyInstance(mbs, name,
iface, false);
- jaas_mbean.installJaasModules();
+ jaas_mbean.upgradeRhqUserSecurityDomainIfNeeded();
} catch (Exception e) {
- throw new RuntimeException("Cannot install JAAS login modules!", e);
+ throw new RuntimeException("Cannot upgrade JAAS login modules!", e);
}
}
@@ -632,7 +631,7 @@ public class StartupBean implements StartupLocal {
log.error("Cannot schedule server plugin jobs.", e);
}
- // Alerting Availability Duration Job (create only, nothing actually scheduled here)
+ // Alerting Availability Duration Job (create only, nothing actually scheduled here)
try {
schedulerBean.scheduleTriggeredJob(AlertAvailabilityDurationJob.class, false, null);
} catch (Exception e) {
@@ -647,7 +646,7 @@ public class StartupBean implements StartupLocal {
* immediately begin to send any persisted guaranteed messages that might already exist. This method must be called
* at a time when the server is ready to accept messages from agents because any guaranteed messages that are
* delivered might trigger the agents to send messages back to the server.
- *
+ *
* NOTE: we don't need to do this - so far, none of the messages the server sends to the agent are marked
* with "guaranteed delivery" (this is on purpose and a good thing) so we don't need to start all the agent clients
* in case they have persisted messages. Since the number of agents could be large this cache could be huge and
@@ -673,7 +672,7 @@ public class StartupBean implements StartupLocal {
* Starts the embedded agent, but only if the embedded agent is installed and it is enabled.
*
* @throws RuntimeException if the agent is installed and enabled but failed to start
- *
+ *
* @deprecated we don't have an embedded agent anymore, leaving this in case we resurrect it
*/
private void startEmbeddedAgent() throws RuntimeException {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
new file mode 100644
index 0000000..d89c04b
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/DelegatingLoginModule.java
@@ -0,0 +1,209 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.rhq.enterprise.server.core.jaas;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
+
+import org.rhq.core.util.StringUtil;
+
+/**
+ * A login module that just delegates all work to a different security domain.<p/>
+ * When you use container managed security (CMS), EAP 6.1 requires the security domain being
+ * already present in standalone.xml
+ *
+ * With our setup we (re)-create the security domain of RHQUserSecurityDomain dynamically,
+ * which makes CMS fail on startup and also on re-create.
+ *
+ * The approach of just exchanging login modules does not work correctly either (principals
+ * keep being cached, server goes into need-reload state).
+ *
+ * So we now have a security domain for the CMS for the REST api that just delegates to the
+ * RHQUserSecuritDomain.
+ *
+ * <pre>
+ * <security-domain name="RHQRESTSecurityDomain" cache-type="default">
+ * <authentication>
+ * <login-module code="org.rhq.enterprise.server.core.jaas.DelegatingLoginModule" flag="required">
+ * <module-option name="delegateTo" value="RHQUserSecurityDomain"/>
+ * <module-option name="additionalRoles" value="rest-user"/>
+ * </login-module>
+ * </authentication>
+ * </security-domain>
+ *</pre>
+ *
+ * @author Heiko W. Rupp
+ */
+@SuppressWarnings("unused")
+public class DelegatingLoginModule extends UsernamePasswordLoginModule {
+
+ private static Log LOG = LogFactory.getLog("DelegatingLoginModule");
+
+ LoginContext loginContext;
+ private String[] usernamePassword;
+ private Principal identity;
+ private List<String> rolesList;
+ private boolean debugEnabled;
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+ Map<String, ?> options) {
+
+ debugEnabled = log.isDebugEnabled();
+
+ super.initialize(subject, callbackHandler, sharedState, options);
+
+ /* This is the login context (=security domain) we want to delegate to */
+ String delegateTo = (String) options.get("delegateTo");
+
+ /* Comma separated list of roles that should be set for the principal */
+ String additionalRoles = (String) options.get("roles");
+ rolesList = StringUtil.explode(additionalRoles, ",");
+
+ if (delegateTo ==null || delegateTo.isEmpty()) {
+ delegateTo = "other";
+ LOG.warn("module-option 'delegateTo' was not set. Defaults to 'other'.");
+ }
+
+ if (debugEnabled) {
+ log.debug("Delegating to " + delegateTo + " with roles " + additionalRoles);
+ }
+
+ // Now create the context for later use
+ try {
+ loginContext = new LoginContext(delegateTo, new DelegateCallbackHandler());
+ } catch (LoginException e) {
+ log.warn("Initialize failed : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Do the actual login work - we obtain the user/password passed in and then try to
+ * log into the delegated context. If this succeeds, we tell the super-module,
+ * so this can do further processing (especially running the #commit() method).
+ *
+ * @return True on success
+ * @throws LoginException If anything goes wrong
+ */
+ @Override
+ public boolean login() throws LoginException {
+ try {
+ // Get the username / password the user entred and save if for later use
+ usernamePassword = super.getUsernameAndPassword();
+
+ // Try to log in via the delegate
+ loginContext.login();
+
+ // Nix out the password
+ usernamePassword[1] = null;
+
+ // login was success, so we can continue
+ identity = createIdentity(usernamePassword[0]);
+ useFirstPass=true;
+
+ // This next flag is important. Without it the principal will not be
+ // propagated
+ loginOk = true;
+
+ if (debugEnabled) {
+ log.debug("Login ok for " + usernamePassword[0]);
+ }
+
+ return true;
+ } catch (Exception e) {
+ if (debugEnabled) {
+ LOG.debug("Login failed for : " + usernamePassword[0] + ": " + e.getMessage());
+ }
+ loginOk = false;
+ return false;
+ }
+ }
+
+
+ @Override
+ protected String getUsersPassword() throws LoginException {
+
+ // This is not used but abstract in super.
+ return null;
+ }
+
+ @Override
+ protected Principal getIdentity() {
+ return identity;
+ }
+
+
+ @Override
+ protected Group[] getRoleSets() throws LoginException {
+
+ SimpleGroup roles = new SimpleGroup("Roles");
+
+ for (String role : rolesList ) {
+ roles.addMember( new SimplePrincipal(role));
+ }
+ Group[] roleSets = { roles };
+ return roleSets;
+ }
+
+
+ /**
+ * Handle the callbacks from the other security domain that we delegate to
+ */
+ private class DelegateCallbackHandler implements CallbackHandler {
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ if (debugEnabled) {
+ LOG.debug("private handle callbacks");
+ }
+ for (Callback cb : callbacks) {
+ if (cb instanceof NameCallback) {
+ NameCallback nc = (NameCallback) cb;
+ nc.setName(usernamePassword[0]);
+ }
+ else if (cb instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) cb;
+ pc.setPassword(usernamePassword[1].toCharArray());
+ }
+ else {
+ throw new UnsupportedCallbackException(cb,"Callback " + cb + " not supported");
+ }
+ }
+ }
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
index 10fef1a..d12336e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCLoginModule.java
@@ -50,7 +50,7 @@ import org.rhq.enterprise.server.RHQConstants;
* this value is "SELECT password FROM principals WHERE principal=?"
*
* dsJndiName
- * JNDI name of the datasource to use. Default value is java:/HypericDS
+ * JNDI name of the datasource to use. Default value is java:/jboss/datasources/RHQDS
* </pre>
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
index 5640f3f..2b761f6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/JDBCPrincipalCheckLoginModule.java
@@ -38,6 +38,7 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.crypto.CryptoUtil;
import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
import org.rhq.enterprise.server.RHQConstants;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
index e476eeb..6b7add6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.core.jaas;
@@ -42,8 +42,8 @@ import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
/**
- * A login module for authenticating against an LDAP directory server using JNDI, based on configuration properites LDAP
- * module options:
+ * A login module for authenticating against an LDAP directory server using JNDI, based on configuration properties.<br/
+ * LDAP module options:
*
* <pre>
* java.naming.factory.initial
@@ -72,7 +72,7 @@ import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
* BaseDN
* The base of the LDAP tree we are authenticating against. For example:
* o=Covalent Technologies,c=US. Multiple LDAP bases can be used by
- * seperating each DN by ';'
+ * separating each DN by ';'
*
* BindDN
* The BindDN to use if the LDAP server does not support anonymous searches.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
index 52cd33d..de3b836 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
@@ -464,7 +464,7 @@ public class SystemManagerBean implements SystemManagerLocal, SystemManagerRemot
}
} else if (property == SystemSetting.AGENT_MAX_QUIET_TIME_ALLOWED) {
long time = Long.parseLong(value);
- // minimum should be 3 * the agent ping interval, any less risks unwanted backfilling
+ // minimum should be 3 * the agent ping interval, any less risks unwanted backfilling
if (time < 1000L * 60 * 3) {
throw new InvalidSystemConfigurationException("Agent Max Quiet Time Allowed must be at least 3 minutes");
}
commit b9ce1ee3cc01fd2bf5614f10e164a1f4cebfe42c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 16 13:11:14 2013 -0400
BZ 957282 957288 add bundle target of "Base Directory"
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 4a26d19..ad22370 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1337,6 +1337,10 @@
<value-context>pluginConfiguration</value-context>
<value-name>homeDir</value-name>
</destination-base-dir>
+ <destination-base-dir name="Base Directory" description="The base directory for server content, such as '[install-dir]/standalone' (i.e. the value found in the 'Base Directory' connection property)">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>baseDir</value-name>
+ </destination-base-dir>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
<value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
commit f9052819e3da19359081274d62eb6b0f75dd63e2
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Thu May 16 14:28:01 2013 +0200
Bug 962787 - GloballyUncaughtException when changing a parameter in Connection Settings tab of a compatible group after a plugin update
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
index 8b5be2c..b3ccb10 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/configuration/GroupConfigurationEditor.java
@@ -1,8 +1,7 @@
/*
* RHQ Management Platform
- * Copyright 2010-2011, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.gui.coregui.client.components.configuration;
@@ -71,10 +70,10 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.PopupWindow;
import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedToolStrip;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
/**
* A SmartGWT widget for editing a group of RHQ {@link Configuration}s that conform to the same
@@ -638,28 +637,20 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
}
private Property getProperty(Configuration configuration, Property referenceProperty, Integer index) {
- LinkedList<Property> propertyHierarchy = new LinkedList<Property>();
- Property currentProperty = referenceProperty;
- propertyHierarchy.add(currentProperty);
- do {
- if (currentProperty.getParentMap() != null) {
- currentProperty = currentProperty.getParentMap();
- } else if (currentProperty.getParentList() != null) {
- currentProperty = currentProperty.getParentList();
- } else if (currentProperty.getConfiguration() == null) {
- throw new IllegalStateException(currentProperty + " has no parent.");
- }
- propertyHierarchy.addFirst(currentProperty);
- } while (currentProperty.getConfiguration() == null);
-
- Property property = configuration.get(propertyHierarchy.get(0).getName());
- for (int i = 1, propertyHierarchySize = propertyHierarchy.size(); i < propertyHierarchySize; i++) {
- String childPropertyName = propertyHierarchy.get(i).getName();
+ List<Property> referenceHierarchy = getParentFirstPropertiesHierarchy(referenceProperty);
+ // Add referenceProperty to the configuration, creating parents if necessary
+ Property property = configuration.get(referenceHierarchy.get(0).getName());
+ if (property == null) {
+ property = createPropertyByExample(referenceHierarchy.get(0));
+ configuration.put(property);
+ }
+ for (int i = 1; i < referenceHierarchy.size(); i++) {
+ String childPropertyName = referenceHierarchy.get(i).getName();
if (property instanceof PropertyMap) {
PropertyMap propertyMap = (PropertyMap) property;
property = propertyMap.get(childPropertyName);
if (property == null) {
- property = new PropertySimple(childPropertyName, null);
+ property = createPropertyByExample(referenceHierarchy.get(i));
propertyMap.put(property);
}
} else if (property instanceof PropertyList) {
@@ -667,7 +658,7 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
if (index < propertyList.getList().size()) {
property = propertyList.getList().get(index);
} else {
- property = new PropertySimple(childPropertyName, null);
+ property = createPropertyByExample(referenceHierarchy.get(i));
propertyList.add(property);
}
}
@@ -676,6 +667,35 @@ public class GroupConfigurationEditor extends ConfigurationEditor {
return property;
}
+ private List<Property> getParentFirstPropertiesHierarchy(Property bottomProperty) {
+ LinkedList<Property> propertyHierarchy = new LinkedList<Property>();
+ for (Property currentProperty = bottomProperty; currentProperty != null; ) {
+ propertyHierarchy.addFirst(currentProperty);
+ if (currentProperty.getParentMap() != null) {
+ currentProperty = currentProperty.getParentMap();
+ } else if (currentProperty.getParentList() != null) {
+ currentProperty = currentProperty.getParentList();
+ } else if (currentProperty.getConfiguration() == null) {
+ throw new IllegalStateException(currentProperty + " has no parent.");
+ } else {
+ currentProperty = null;
+ }
+ }
+ return new ArrayList<Property>(propertyHierarchy);
+ }
+
+ private <T extends Property> T createPropertyByExample(T example) {
+ T property = null;
+ if (example instanceof PropertyMap) {
+ property = (T) new PropertyMap(example.getName());
+ } else if (example instanceof PropertyList) {
+ property = (T) new PropertyList(example.getName());
+ } else {
+ property = (T) new PropertySimple(example.getName(), null);
+ }
+ return property;
+ }
+
private boolean isAggregateProperty(PropertySimple propertySimple) {
return (getConfiguration(propertySimple) == getConfiguration());
}
commit ac38cd855156fd93958f82b40ca5cf75a3f6593d
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 17:13:18 2013 -0400
BZ 951382 - for upgrades, let's use the agent preferences upgrade feature
to set the cert store locations explicitly and copy the files
from data/ to conf/ which is the new default location. Note that if
customers already explicitly set the locations of their cert stores,
we leave those intact and continue using what the customer asked to use.
We only do anything IF those settings weren't set and thus defaults
were taking effect.
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
index 4fe7df9..3f9a89b 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
@@ -58,7 +58,7 @@ public interface AgentConfigurationConstants {
/**
* This is the current schema version that our agent configuration knows about.
*/
- int CURRENT_CONFIG_SCHEMA_VERSION = 6;
+ int CURRENT_CONFIG_SCHEMA_VERSION = 7;
/**
* Flag to indicate if the agent's configuration has been setup.
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
index 6c0a2ce..27e68f9 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationUpgrade.java
@@ -18,10 +18,17 @@
*/
package org.rhq.enterprise.agent;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;
+import mazz.i18n.Logger;
+
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.enterprise.agent.i18n.AgentI18NFactory;
+import org.rhq.enterprise.agent.i18n.AgentI18NResourceKeys;
+import org.rhq.enterprise.communications.ServiceContainerConfigurationConstants;
import org.rhq.enterprise.communications.util.prefs.PreferencesUpgrade;
import org.rhq.enterprise.communications.util.prefs.PreferencesUpgradeStep;
@@ -31,6 +38,8 @@ import org.rhq.enterprise.communications.util.prefs.PreferencesUpgradeStep;
* @author John Mazzitelli
*/
public class AgentConfigurationUpgrade extends PreferencesUpgrade {
+ private static final Logger LOG = AgentI18NFactory.getLogger(AgentConfigurationUpgrade.class);
+
/**
* This is a convenience method that upgrades the given agent preferences to the latest configuration schema
* version.
@@ -58,7 +67,8 @@ public class AgentConfigurationUpgrade extends PreferencesUpgrade {
list.add(new Step2to3()); // goes from v2 to v3
list.add(new Step3to4()); // goes from v3 to v4
list.add(new Step4to5()); // goes from v4 to v5
- list.add(new Step5to6());
+ list.add(new Step5to6()); // goes from v5 to v6
+ list.add(new Step6to7()); // goes from v6 to v7
return list;
}
@@ -139,4 +149,55 @@ public class AgentConfigurationUpgrade extends PreferencesUpgrade {
preferences.put(AgentConfigurationConstants.SERVER_ALIAS, "rhqserver");
}
}
+
+ static class Step6to7 extends PreferencesUpgradeStep {
+ public int getSupportedConfigurationSchemaVersion() {
+ return 7;
+ }
+
+ public void upgrade(Preferences preferences) {
+ // This new schema version indicates when we changed the default locations for our keystore/truststore
+ // files. Before if these comm settings weren't set, we assumed a default of "data" directory, but now
+ // we assume a default of "conf" directory (if that directory exists). See BZ 951382.
+ File confDir = new File("conf");
+ if (!confDir.exists()) {
+ return; // conf/ doesn't exist (perhaps we are running in a test?) - do nothing and just fallback to the standard defaults
+ }
+
+ String dataDir = preferences.get(AgentConfigurationConstants.DATA_DIRECTORY,
+ AgentConfigurationConstants.DEFAULT_DATA_DIRECTORY);
+
+ String prefNamesFileNames[][] = {
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_KEYSTORE_FILE_NAME },
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE_NAME } };
+
+ for (String[] prefNameFileName : prefNamesFileNames) {
+ String value = preferences.get(prefNameFileName[0], null);
+ if (value == null) {
+ File newFile = new File(confDir, prefNameFileName[1]);
+ value = newFile.getAbsolutePath();
+ preferences.put(prefNameFileName[0], value);
+
+ File oldFile = new File(dataDir, prefNameFileName[1]);
+ if (oldFile.exists()) {
+ try {
+ FileUtil.copyFile(oldFile, newFile);
+ oldFile.delete();
+ } catch (Exception e) {
+ LOG.error(e, AgentI18NResourceKeys.CERT_FILE_COPY_ERROR, oldFile, newFile);
+ }
+ }
+ LOG.debug(AgentI18NResourceKeys.CERT_FILE_LOCATION, prefNameFileName[0], value);
+ }
+ }
+
+ return;
+ }
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
index 21a39a9..16c110a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
@@ -28,6 +28,9 @@ import mazz.i18n.annotation.I18NResourceBundle;
*/
@I18NResourceBundle(baseName = "agent-messages", defaultLocale = "en")
public interface AgentI18NResourceKeys {
+ @I18NMessage("Failed to move old cert file [{0}] to new default location [{1}] - agent communication may fail!")
+ String CERT_FILE_COPY_ERROR = "AgentConfiguration.cert-file-copy-error";
+
@I18NMessage("Explicitly setting file location [{0}] to [{1}]")
String CERT_FILE_LOCATION = "AgentConfiguration.cert-file-location";
commit 3034e3c906a352723834aa4adce41355d7310bce
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 12:30:18 2013 -0400
provide another sample plugin that demonstrates using the embedded plugin extension model
diff --git a/.classpath b/.classpath
index aa4c157..53037dd 100644
--- a/.classpath
+++ b/.classpath
@@ -189,6 +189,8 @@
<classpathentry kind="src" path="modules/integration-tests/jndi-access/jndi-access-test/src/test/resources"/>
<classpathentry kind="src" path="modules/integration-tests/mod_cluster-plugin-test/src/test/java"/>
<classpathentry kind="src" path="etc/samples/skeleton-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/embedded-ext-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/skinny-platform/src/main/java"/>
<classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/samples/simplereport-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
diff --git a/etc/samples/embedded-ext-plugin/pom.xml b/etc/samples/embedded-ext-plugin/pom.xml
new file mode 100644
index 0000000..9427d71
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq.sample.embeddedextplugin</groupId>
+ <artifactId>embedded-ext-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>Embedded Ext RHQ Plugin</name>
+ <description>A sample plugin showing plugin embedded extention</description>
+
+ <properties>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-native-system</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq.sample.skeletonplugin</groupId>
+ <artifactId>skeleton-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Maven Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
+
diff --git a/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java b/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java
new file mode 100644
index 0000000..6e823c3
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/src/main/java/org/rhq/sample/embeddedextplugin/EmbeddedExtensionDiscoveryComponent.java
@@ -0,0 +1,58 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.embeddedextplugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.sample.skeletonplugin.SamplePluginDiscoveryComponent;
+
+/**
+ * This is a discovery class for the embedded extension resource type.
+ */
+public class EmbeddedExtensionDiscoveryComponent extends SamplePluginDiscoveryComponent {
+ private final Log log = LogFactory.getLog(EmbeddedExtensionDiscoveryComponent.class);
+
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ log.info("Discovering embedded extension resources");
+ Set<DiscoveredResourceDetails> discoveredResources = super.discoverResources(context); // call the parent discovery code
+ Set<DiscoveredResourceDetails> extendedResources = new HashSet<DiscoveredResourceDetails>();
+
+ int i = -1;
+ for (DiscoveredResourceDetails discoveredResource : discoveredResources) {
+ String key = "Embedded Extension Resource Key" + (++i > 0 ? String.valueOf(i) : "");
+ String name = "Embedded Extension Resource";
+ String description = "This describes the Embedded Extension Resource";
+
+ discoveredResource.setResourceKey(key);
+ discoveredResource.setResourceName(name);
+ discoveredResource.setResourceDescription(description);
+
+ extendedResources.add(discoveredResource);
+ }
+
+ return extendedResources;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..16dbb7b
--- /dev/null
+++ b/etc/samples/embedded-ext-plugin/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="EmbeddedExtPlugin"
+ displayName="Embedded Extension Plugin"
+ version="1.0"
+ package="org.rhq.sample.embeddedextplugin"
+ description="Defines a resource type that uses the embedded extension model."
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="SkeletonPlugin" useClasses="true" />
+
+ <server name="Embedded Extension Resource"
+ discovery="EmbeddedExtensionDiscoveryComponent"
+ class="org.rhq.sample.skeletonplugin.SamplePluginServerComponent"
+ description="A resource that embeds the skeleton plugin type"
+ sourcePlugin="SkeletonPlugin"
+ sourceType="Sample Plugin Server">
+ </server>
+
+</plugin>
commit 8cbe5ffb7379c26403f9083bc7b0642f490ff9eb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 15 11:47:55 2013 -0400
provide some additions to the sample skeleton plugin
add a new "skinny platform" plugin sample, used mainly for testing - provides a minimal plugin you can use to run an agent with
diff --git a/etc/samples/skeleton-plugin/pom.xml b/etc/samples/skeleton-plugin/pom.xml
index 56c816e..998bb47 100644
--- a/etc/samples/skeleton-plugin/pom.xml
+++ b/etc/samples/skeleton-plugin/pom.xml
@@ -15,7 +15,7 @@
<description>A template for building a custom RHQ Agent plugin</description>
<properties>
- <rhq.version>4.3.0</rhq.version>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
</properties>
<dependencies>
@@ -42,30 +42,6 @@
<scope>provided</scope> <!-- provided by the agent/plugin-container -->
</dependency>
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>javax.persistence</groupId>
- <artifactId>persistence-api</artifactId>
- <version>1.0</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>hibernate-annotations</groupId>
- <artifactId>hibernate-annotations</artifactId>
- <version>3.2.1.GA</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
- <!-- Fix for the Javac bug requiring annotations to be available when compiling classes. (fixed in JDK 6) -->
- <dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>2.1</version>
- <scope>provided</scope> <!-- provided by the agent/plugin-container -->
- </dependency>
-
<!--
Uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog
All three are provided to your plugin by the agent/plugin-container.
@@ -143,79 +119,6 @@
</plugins>
</build>
- <profiles>
- <profile>
- <id>dev</id>
- <properties>
- <!-- define the location of your RHQ root directory - typically rhq.rootDir is overridden in Maven's settings.xml -->
- <rhq.rootDir>/rhq/trunk</rhq.rootDir>
- <rhq.defaultDevContainerPath>dev-container</rhq.defaultDevContainerPath>
- <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
- <rhq.deploymentDir>${rhq.containerDir}/${rhq.agentPluginDir}</rhq.deploymentDir>
- </properties>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>deploy</id>
- <phase>compile</phase>
- <configuration>
- <target>
- <mkdir dir="${rhq.deploymentDir}" />
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Updating ${deployment.file}...</echo>
- <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- <execution>
- <id>deploy-jar-meta-inf</id>
- <phase>package</phase>
- <configuration>
- <target>
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
- <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}">
- <patternset>
- <include name="META-INF/**" />
- </patternset>
- </unjar>
- <jar destfile="${deployment.file}"
- manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF"
- update="true">
- </jar>
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- <execution>
- <id>undeploy</id>
- <phase>clean</phase>
- <configuration>
- <target>
- <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
- <echo>*** Deleting ${deployment.file}...</echo>
- <delete file="${deployment.file}" />
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
-
<repositories>
<repository>
<id>jboss-public-repository-group</id>
diff --git a/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java
new file mode 100644
index 0000000..b8a81ab
--- /dev/null
+++ b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildDiscoveryComponent.java
@@ -0,0 +1,47 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.skeletonplugin;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+public class SamplePluginChildDiscoveryComponent implements ResourceDiscoveryComponent {
+ private final Log log = LogFactory.getLog(SamplePluginChildDiscoveryComponent.class);
+
+ @Override
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ log.info("Discovering my custom plugin's child resources");
+ HashSet<DiscoveredResourceDetails> set = new HashSet<DiscoveredResourceDetails>();
+ String key = "My Child Resource Key";
+ String name = "My Child Resource";
+ String version = "1.0";
+ String description = "This describes My Child Resource";
+ DiscoveredResourceDetails resource = new DiscoveredResourceDetails(context.getResourceType(), key, name,
+ version, description, null, null);
+ set.add(resource);
+ return set;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java
new file mode 100644
index 0000000..a3303e7
--- /dev/null
+++ b/etc/samples/skeleton-plugin/src/main/java/org/rhq/sample/skeletonplugin/SamplePluginChildServiceComponent.java
@@ -0,0 +1,61 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.sample.skeletonplugin;
+
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
+
+public class SamplePluginChildServiceComponent implements ResourceComponent, MeasurementFacet {
+ private final Log log = LogFactory.getLog(SamplePluginChildServiceComponent.class);
+
+ public void start(ResourceContext context) {
+ log.info("Starting child resource [" + context.getResourceKey() + "]");
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+
+ public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) {
+ for (MeasurementScheduleRequest request : requests) {
+ String name = request.getName();
+ try {
+ Number value = new Integer(2); // dummy measurement value
+ report.addData(new MeasurementDataNumeric(request, value.doubleValue()));
+ } catch (Exception e) {
+ log.error("Failed to obtain measurement [" + name + "]. Cause: " + e);
+ }
+ }
+
+ return;
+ }
+}
diff --git a/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
index 4f4966d..cde11c5 100644
--- a/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
+++ b/etc/samples/skeleton-plugin/src/main/resources/META-INF/rhq-plugin.xml
@@ -15,6 +15,7 @@
<plugin name="SkeletonPlugin"
displayName="Skeleton Plugin"
version="1.0"
+ description="This is a skeleton plugin that can be used to start your own custom plugin."
package="org.rhq.sample.skeletonplugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xmlns:rhq-plugin"
@@ -110,5 +111,24 @@
<resource-configuration>
<c:simple-property name="port" type="integer" displayName="Port on which to listen" />
</resource-configuration>
+
+ <!--
+ CHANGE: You can optionally define children resource types to represent internal services within your
+ server resource type.
+ -->
+ <service name="Sample Plugin Child Service"
+ discovery="SamplePluginChildDiscoveryComponent"
+ class="SamplePluginChildServiceComponent"
+ description="This is a child service found under the main, top-level server resource type.">
+
+ <plugin-configuration>
+ <c:simple-property name="SamplePluginChildProperty" displayName="Sample Plugin Child Property" default="Value" />
+ </plugin-configuration>
+
+ <metric property="ChildMeasurementName"
+ displayName="The Child Measurement Name"
+ description="Describes what this child measurement is actually telling you" />
+
+ </service>
</server>
</plugin>
diff --git a/etc/samples/skinny-platform/pom.xml b/etc/samples/skinny-platform/pom.xml
new file mode 100644
index 0000000..994462f
--- /dev/null
+++ b/etc/samples/skinny-platform/pom.xml
@@ -0,0 +1,60 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq.sample.skinnyplugin</groupId>
+ <artifactId>rhq-skinny-platform-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>RHQ Skinny Platform Plugin</name>
+ <description> A very slimmed down platform plugin, used for testing.</description>
+
+ <properties>
+ <rhq.version>4.8.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-plugin-api</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-native-system</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the agent/plugin-container -->
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>jboss-public-repository-group</id>
+ <name>JBoss Public Maven Repository Group</name>
+ <url>https://repository.jboss.org/nexus/content/groups/public/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
diff --git a/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java
new file mode 100644
index 0000000..0c123b1
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformComponent.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.plugins.skinnyplatform;
+
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+
+public class PlatformComponent implements ResourceComponent<PlatformComponent> {
+ public void start(ResourceContext<PlatformComponent> context) {
+ }
+
+ public void stop() {
+ }
+
+ public AvailabilityType getAvailability() {
+ return AvailabilityType.UP;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java
new file mode 100644
index 0000000..b53b1c3
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/java/org/rhq/plugins/skinnyplatform/PlatformDiscoveryComponent.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.plugins.skinnyplatform;
+
+import java.net.InetAddress;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+
+@SuppressWarnings("rawtypes")
+public class PlatformDiscoveryComponent implements ResourceDiscoveryComponent {
+
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext context) {
+ String pcName = context.getPluginContainerName();
+ String hostname = getHostname();
+
+ String name = (pcName != null ? pcName : hostname);
+ String key = "skinny:" + name;
+ String description = context.getResourceType().getDescription();
+ String version = "1.0";
+
+ DiscoveredResourceDetails discoveredResource = new DiscoveredResourceDetails(context.getResourceType(), key,
+ name, version, description, null, null);
+
+ HashSet<DiscoveredResourceDetails> results = new HashSet<DiscoveredResourceDetails>();
+ results.add(discoveredResource);
+ return results;
+ }
+
+ private String getHostname() {
+ String name;
+ try {
+ name = InetAddress.getLocalHost().getHostAddress();
+ } catch (Exception e) {
+ name = null;
+ }
+
+ // we fought the good fight but we just can't get this machine's hostname, give a generic platform name
+ if (name == null) {
+ name = "Unnamed Skinny Platform";
+ }
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml b/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..fd50a2a
--- /dev/null
+++ b/etc/samples/skinny-platform/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<plugin name="Skinny Platform"
+ displayName="Skinny Platform"
+ version="1.0"
+ package="org.rhq.plugins.skinnyplatform"
+ description="Provides a slimmed down, single platform resource type - used mainly for testing."
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <platform name="Generic Platform"
+ class="PlatformComponent"
+ discovery="PlatformDiscoveryComponent"
+ description="A generic platform with very little functionality.">
+ </platform>
+
+</plugin>
commit 98cb0afd7a2bcfcb8f74f3d8182fb9798edd2b49
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue May 14 10:38:22 2013 -0700
[BZ 960646] - Trivial: strengthen opacity on new Availability chart.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 5ef57a8..a301e73 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -243,7 +243,7 @@ public class AvailabilityOverUnderGraphType {
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
})
- .attr("opacity", ".3")
+ .attr("opacity", ".75")
.attr("fill", function (d) {
return calcBarFill(d);
});
@@ -265,7 +265,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "12px")
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-weight", "bold")
- .attr("fill", "#003168")
+ .attr("fill", "#545454")
.text(availChartContext.chartTitle);
svg.append("text")
commit cf37517727392d04d8ab11182fd94474571462d8
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Tue May 14 09:20:26 2013 -0700
[BZ 960646] - UXD updates to new Availability Charts.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index fbce610..5ef57a8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -169,9 +169,9 @@ public class AvailabilityOverUnderGraphType {
.orient("bottom"),
calcBarY = function (d) {
- var ABOVE = -10,
+ var ABOVE = -6,
BELOW = 0,
- STRADDLE = -5,
+ STRADDLE = -3,
offset;
if (d.availType === 'DOWN') {
@@ -198,19 +198,19 @@ public class AvailabilityOverUnderGraphType {
calcBarFill = function (d) {
if (d.availType === 'DOWN') {
- return "#FF1919"; // red
+ return "#c5888b"; // red
}
else if (d.availType === 'DISABLED') {
return "url(#diagonalHatchFill)"; // grey diagonal hatches
}
else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
+ return "#d8d8d8"; // gray
}
else if (d.availType === 'UP') {
- return "#198C19"; // green
+ return "#8cbe89"; // green
}
else if (d.availType === 'WARN') {
- return "#FFA500"; // orange
+ return "#e1b36b"; // orange
}
else if (d.availType === 'EMPTY') {
return "#CCC"; // gray
@@ -238,12 +238,12 @@ public class AvailabilityOverUnderGraphType {
return calcBarY(d);
})
.attr("height", function (d) {
- return 10;
+ return 6;
})
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
})
- .attr("opacity", ".9")
+ .attr("opacity", ".3")
.attr("fill", function (d) {
return calcBarFill(d);
});
@@ -251,7 +251,7 @@ public class AvailabilityOverUnderGraphType {
// create x-axis
svg.append("g")
.attr("class", "x axis")
- .attr("fill", "#50505a")
+ .attr("fill", "#b0b0b0")
.attr("stroke-width", "0.5")
.attr("transform", "translate(0," + height + ")")
.attr("letter-spacing", "3")
@@ -274,7 +274,7 @@ public class AvailabilityOverUnderGraphType {
.attr("y", 28)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartUpLabel);
@@ -284,7 +284,7 @@ public class AvailabilityOverUnderGraphType {
.attr("y", 39)
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-size", "9px")
- .attr("fill", "#50505a")
+ .attr("fill", "#545454")
.style("text-anchor", "end")
.text(availChartContext.chartDownLabel);
commit af1fdd5d865ab295969f80949b36c3c38c70ccef
Author: Jirka Kremser <jkremser(a)redhat.com>
Date: Tue May 14 13:21:44 2013 +0200
Fixing a typo in a sample CLI script.
diff --git a/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js b/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
index 9739cb1..a965edf 100644
--- a/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
+++ b/modules/enterprise/remoting/cli/src/main/samples/deploy-to-and-restart-JBAS.js
@@ -146,7 +146,7 @@ function _restartFunction(asResourceType) {
(asResourceType.name == "JBossAS7 Standalone Server" ||
asResourceType.name == "Managed Server")) {
- return _restartAS7);
+ return _restartAS7;
} else {
throw "The resource group the destination targets doesn't seem to be a JBoss AS server group.";
}
commit 9a3b4d105099320c6c6794ff04e12285c5399667
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu May 9 15:15:02 2013 +0200
[BZ 620603] - Re-enabling the limited JOIN FETCH reporting
with a more informative message, asking the users to co-operate in
identifying the individual uses of the problematic JOIN FETCH queries that
we potentially missed.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
index f826e41..8eb4b3e 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -15,8 +15,8 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
/**
- * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries.
- * It will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
+ * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries. It
+ * will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
* that Hibernate itself offers that merely dumps a message about in-memory filtering of results resulting from the use
* of JOIN FETCH together with limits.
*
@@ -24,7 +24,7 @@ import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
*/
public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
- private static Log LOG = LogFactory.getLog("JOIN FETCH Perf");
+ private static Log LOG = LogFactory.getLog("JOIN FETCH Performance");
public JoinFetchReportingQueryTranslator(String queryIdentifier, String query, Map enabledFilters,
SessionFactoryImplementor factory) {
@@ -49,11 +49,14 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
}
}
- public void report() {
+ public void report(String method) {
if (time != 0) {
time = System.currentTimeMillis() - time;
- LOG.warn("List with first: " + firstRow + ", max: " + maxRows + " took " + time + "ms:\n" +
- getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" + extractRHQCalls(new Exception()));
+ LOG.warn("Encountered a query with potentially bad performance. While this is not a bug and the " +
+ "system functions as designed, please report this to RHQ community so that we can reimplement our" +
+ " code to work better.\n" + method + "() with first: " + firstRow + ", max: " + maxRows + " took "
+ + time + "ms:\n" + getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" +
+ extractRHQCalls(new Exception()));
}
}
@@ -80,7 +83,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
List ret = super.list(session, queryParameters);
- usage.report();
+ usage.report("list");
return ret;
}
@@ -91,7 +94,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
Iterator ret = super.iterate(queryParameters, session);
- usage.report();
+ usage.report("iterate");
return ret;
}
@@ -103,7 +106,7 @@ public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
ScrollableResults ret = super.scroll(queryParameters, session);
- usage.report();
+ usage.report("scroll");
return ret;
}
diff --git a/modules/core/domain/src/main/resources/META-INF/persistence.xml b/modules/core/domain/src/main/resources/META-INF/persistence.xml
index a15fd2e..1bbd8c2 100644
--- a/modules/core/domain/src/main/resources/META-INF/persistence.xml
+++ b/modules/core/domain/src/main/resources/META-INF/persistence.xml
@@ -21,9 +21,7 @@
<!--<property name="com.intellij.javaee.persistence.datasource" value="rhq-oracle" />-->
<property name="com.intellij.javaee.persistence.datasource" value="rhq-postgres" />
- <!-- Used only for debugging the usages of JOIN FETCHes
<property name="hibernate.query.factory_class" value="org.rhq.core.domain.util.JoinFetchReportingQueryTranslatorFactory" />
- -->
<!-- This value doesn't have any theoretical grounds and is purely based on experiments. Value of 32 gives
the best compromise between the quick load of queries with low and high limits (i.e. page size in tens vs.
commit db62629626fdd9049cf89cfa58dc5b14b2a98ea9
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu May 9 13:11:50 2013 +0200
[BZ 620603] - Don't use JOIN FETCH in criteria queries with limits.
Use the "manual" initialization of lazy fields and collections in
that case instead.
Together with the "hibernate.default_batch_fetch_size" setting in the
hibernate configuration, this offers superior performance over the join
fetch and in memory filtering of results when the number of rows in the
"primary" tables times the number of rows in the "join-fetched" table
is non-trivial.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
new file mode 100644
index 0000000..f826e41
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -0,0 +1,110 @@
+package org.rhq.core.domain.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.ScrollableResults;
+import org.hibernate.engine.spi.QueryParameters;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.engine.spi.SessionImplementor;
+import org.hibernate.event.spi.EventSource;
+import org.hibernate.hql.internal.ast.QueryTranslatorImpl;
+
+/**
+ * This class can be used to quickly identify and analyze usages of JOIN FETCH together with limits on JPA queries.
+ * It will log the JPA, generated SQL and a filtered stacktrace for each such usage. This is to enhance the diagnostics
+ * that Hibernate itself offers that merely dumps a message about in-memory filtering of results resulting from the use
+ * of JOIN FETCH together with limits.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslator extends QueryTranslatorImpl {
+
+ private static Log LOG = LogFactory.getLog("JOIN FETCH Perf");
+
+ public JoinFetchReportingQueryTranslator(String queryIdentifier, String query, Map enabledFilters,
+ SessionFactoryImplementor factory) {
+ super(queryIdentifier, query, enabledFilters, factory);
+ }
+
+ private class JoinFetchUsage {
+ private long time;
+ private Integer firstRow;
+ private Integer maxRows;
+
+ public JoinFetchUsage(QueryParameters queryParameters) {
+ boolean collect = containsCollectionFetches();
+ boolean hasLimit =
+ queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
+
+ if (collect && hasLimit) {
+ firstRow = queryParameters.getRowSelection().getFirstRow();
+ maxRows = queryParameters.getRowSelection().getMaxRows();
+
+ time = System.currentTimeMillis();
+ }
+ }
+
+ public void report() {
+ if (time != 0) {
+ time = System.currentTimeMillis() - time;
+ LOG.warn("List with first: " + firstRow + ", max: " + maxRows + " took " + time + "ms:\n" +
+ getQueryString() + "\n\nSQL:\n" + getSQLString() + "\n" + extractRHQCalls(new Exception()));
+ }
+ }
+
+ private String extractRHQCalls(Throwable t) {
+ StringBuilder bld = new StringBuilder();
+
+ StackTraceElement[] elements = t.getStackTrace();
+
+ //skip the report() and list() calls, hence 2
+ for (int i = 2; i < elements.length; ++i) {
+ StackTraceElement e = elements[i];
+ if (e.getClassName().startsWith("org.rhq")) {
+ bld.append("\n").append(e.toString());
+ }
+ }
+
+ return bld.toString();
+ }
+ }
+
+ @Override
+ public List list(SessionImplementor session, QueryParameters queryParameters) throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ List ret = super.list(session, queryParameters);
+
+ usage.report();
+
+ return ret;
+ }
+
+ @Override
+ public Iterator iterate(QueryParameters queryParameters, EventSource session) throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ Iterator ret = super.iterate(queryParameters, session);
+
+ usage.report();
+
+ return ret;
+ }
+
+ @Override
+ public ScrollableResults scroll(QueryParameters queryParameters, SessionImplementor session)
+ throws HibernateException {
+ JoinFetchUsage usage = new JoinFetchUsage(queryParameters);
+
+ ScrollableResults ret = super.scroll(queryParameters, session);
+
+ usage.report();
+
+ return ret;
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
new file mode 100644
index 0000000..71e1bf2
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
@@ -0,0 +1,27 @@
+package org.rhq.core.domain.util;
+
+import java.util.Map;
+
+import org.hibernate.engine.spi.SessionFactoryImplementor;
+import org.hibernate.hql.spi.FilterTranslator;
+import org.hibernate.hql.spi.QueryTranslator;
+import org.hibernate.hql.spi.QueryTranslatorFactory;
+
+/**
+ * A query translator factory to be set in the hibernate configuration to report the usage of JOIN FETCH with limit.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslatorFactory implements QueryTranslatorFactory {
+ @Override
+ public QueryTranslator createQueryTranslator(String queryIdentifier, String queryString, Map filters,
+ SessionFactoryImplementor factory) {
+ return new JoinFetchReportingQueryTranslator(queryIdentifier, queryString, filters, factory);
+ }
+
+ @Override
+ public FilterTranslator createFilterTranslator(String queryIdentifier, String queryString, Map filters,
+ SessionFactoryImplementor factory) {
+ return new JoinFetchReportingQueryTranslator(queryIdentifier, queryString, filters, factory);
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
index 6963141..f87a814 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/PageControl.java
@@ -276,6 +276,10 @@ public class PageControl implements Serializable, Cloneable {
orderingFields = new LinkedList<OrderingField>();
}
+ public boolean isUnlimited() {
+ return getPageNumber() == 0 && getPageSize() == SIZE_UNLIMITED;
+ }
+
// TODO (ips, 10/12/11): Incorporate firstRecord field into equals() and hashCode().
@Override
@@ -334,4 +338,4 @@ public class PageControl implements Serializable, Cloneable {
return new PageControl(pageNumber, pageSize, getOrderingFieldsAsArray());
}
-}
\ No newline at end of file
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
index ce7ab20..af5842a 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/UnlimitedPageControl.java
@@ -30,6 +30,11 @@ public class UnlimitedPageControl extends PageControl {
}
@Override
+ public boolean isUnlimited() {
+ return true;
+ }
+
+ @Override
public void reset() {
getOrderingFields().clear();
}
diff --git a/modules/core/domain/src/main/resources/META-INF/persistence.xml b/modules/core/domain/src/main/resources/META-INF/persistence.xml
index 8e28c68..a15fd2e 100644
--- a/modules/core/domain/src/main/resources/META-INF/persistence.xml
+++ b/modules/core/domain/src/main/resources/META-INF/persistence.xml
@@ -20,6 +20,16 @@
<!--<property name="com.intellij.javaee.persistence.datasource" value="rhq-oracle" />-->
<property name="com.intellij.javaee.persistence.datasource" value="rhq-postgres" />
+
+ <!-- Used only for debugging the usages of JOIN FETCHes
+ <property name="hibernate.query.factory_class" value="org.rhq.core.domain.util.JoinFetchReportingQueryTranslatorFactory" />
+ -->
+
+ <!-- This value doesn't have any theoretical grounds and is purely based on experiments. Value of 32 gives
+ the best compromise between the quick load of queries with low and high limits (i.e. page size in tens vs.
+ thousands) in an inventory with 30 agents and >20000 resources. -->
+ <property name="hibernate.default_batch_fetch_size" value="32"/>
+
</properties>
</persistence-unit>
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
index 9066916..afa622f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/RHQDomain.gwt.xml
@@ -40,10 +40,11 @@
<!-- These classes are overriden for GWT because their original form doesn't gwt-compile. -->
<exclude name="**/ObfuscatedPropertySimple.*"/>
+ <exclude name="**/JoinFetchReporting*.*" />
</source>
<!--<generate-with class="org.rhq.core.rebind.RecordBuilderGenerator">
<when-type-assignable class="org.rhq.core.domain.util.Recordizable"/>
</generate-with>-->
-</module>
\ No newline at end of file
+</module>
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
new file mode 100644
index 0000000..e92696e
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslator.java
@@ -0,0 +1,9 @@
+package org.rhq.core.domain.util;
+
+/**
+ * GWT friendly impl of this beast.
+ *
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslator {
+}
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
new file mode 100644
index 0000000..9bd8512
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/core/domain/util/JoinFetchReportingQueryTranslatorFactory.java
@@ -0,0 +1,7 @@
+package org.rhq.core.domain.util;
+
+/**
+ * @author Lukas Krejci
+ */
+public class JoinFetchReportingQueryTranslatorFactory {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
index 8f0d2cc..d7cc470 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java
@@ -308,7 +308,11 @@ public final class CriteriaQueryGenerator {
public String getQueryString(boolean countQuery) {
StringBuilder results = new StringBuilder();
+
+ PageControl pc = getPageControl(criteria);
+
results.append("SELECT ");
+
if (countQuery) {
if (groupByClause == null) { // non-grouped method
// use count(*) instead of count(alias) due to https://bugzilla.redhat.com/show_bug.cgi?id=699842
@@ -325,7 +329,9 @@ public final class CriteriaQueryGenerator {
results.append(projection).append(NL);
}
}
+
results.append("FROM ").append(className).append(' ').append(alias).append(NL);
+
if (countQuery == false) {
/*
* don't fetch in the count query to avoid: "query specified join fetching,
@@ -336,19 +342,28 @@ public final class CriteriaQueryGenerator {
addPersistentBag(fetchField);
} else {
if (this.projection == null) {
- /*
+ /*
* if not altering the projection, join fetching can be using
* to retrieve the associated instance in the same SELECT
+ *
+ * We further avoid a JOIN FETCH when executing queries with limits.
+ * Such execution has performance problems that we solve by initializing the fields
+ * "manually" in the CriteriaQueryRunner and by defining a default batch fetch size in the
+ * persistence.xml.
*/
- results.append("LEFT JOIN FETCH ").append(alias).append('.').append(fetchField).append(NL);
+ if (pc.isUnlimited()) {
+ results.append("LEFT JOIN FETCH ").append(alias).append('.').append(fetchField).append(NL);
+ } else {
+ addJoinFetch(fetchField);
+ }
} else {
- /*
+ /*
* if the projection is altered (perhaps converting it into a constructor query), then all
* fields specified in the fetch must be in the explicit return list. this is not possible
* today with constructor queries, so any altered projection will implicitly disable fetching.
* instead, we'll record which fields need to be explicitly fetched after the primary query
* returns the bulk of the data, and use a similar methodology at the SLSB layer to eagerly
- * load those before returning the PageList back to the caller.
+ * load those before returning the PageList back to the caller.
*/
addJoinFetch(fetchField);
}
@@ -357,7 +372,6 @@ public final class CriteriaQueryGenerator {
}
// figure out the 'LEFT JOIN's needed for 'ORDER BY' tokens
- PageControl pc = getPageControl(criteria);
List<String> orderingFieldRequiredJoins = new ArrayList<String>();
List<String> orderingFieldTokens = new ArrayList<String>();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
index d2a28d5..a788fb0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryRunner.java
@@ -25,6 +25,7 @@ package org.rhq.enterprise.server.util;
import java.lang.reflect.Field;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
@@ -46,7 +47,7 @@ public class CriteriaQueryRunner<T> {
private Criteria criteria;
private CriteriaQueryGenerator queryGenerator;
private EntityManager entityManager;
- private boolean automaticFetching;;
+ private boolean automaticFetching;
public CriteriaQueryRunner(Criteria criteria, CriteriaQueryGenerator queryGenerator, EntityManager entityManager) {
this(criteria, queryGenerator, entityManager, true);
@@ -61,7 +62,7 @@ public class CriteriaQueryRunner<T> {
}
public PageList<T> execute() {
- PageList<T> results = null;
+ PageList<T> results;
PageControl pageControl = CriteriaQueryGenerator.getPageControl(criteria);
Restriction criteriaRestriction = criteria.getRestriction();
@@ -109,7 +110,7 @@ public class CriteriaQueryRunner<T> {
initPersistentBags(entity);
}
}
- if (queryGenerator.isProjectionAltered() && !queryGenerator.getJoinFetchFields().isEmpty()) {
+ if (!queryGenerator.getJoinFetchFields().isEmpty()) {
for (T entity : results) {
initJoinFetchFields(entity);
}
@@ -148,7 +149,15 @@ public class CriteriaQueryRunner<T> {
private void initialize(Object entity, Field field) {
try {
field.setAccessible(true);
- Hibernate.initialize(field.get(entity));
+
+ Object instance = field.get(entity);
+
+ Hibernate.initialize(instance);
+
+ if (instance instanceof Iterable) {
+ Iterator<?> it = ((Iterable<?>)instance).iterator();
+ while(it.hasNext()) it.next();
+ }
} catch (Exception e) {
LOG.warn("Could not initialize " + field);
}
diff --git a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
index c012d90..8259fde 100644
--- a/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
+++ b/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/safeinvoker/HibernateDetachUtility.java
@@ -419,7 +419,7 @@ public class HibernateDetachUtility {
String assistNameDelimiter = assistClassName.contains("javassist") ? "_$$_" : "$$";
assistClassName = assistClassName.substring(0, assistClassName.indexOf(assistNameDelimiter));
- if (!replacement.getClass().getName().contains("hibernate")) {
+ if (replacement != null && !replacement.getClass().getName().contains("hibernate")) {
nullOutUninitializedFields(replacement, checkedObjects, checkedObjectCollisionMap,
depth + 1, serializationType);
@@ -607,4 +607,4 @@ public class HibernateDetachUtility {
// ignore this
}
}
-}
\ No newline at end of file
+}
commit 6079e06ac677015c8f87838e7ac8e52cc766d5f6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon May 13 12:36:17 2013 +0200
Bug 962379 - [as7] Garbage Collector Resource misses 'collection-count' and 'collection-time' per minute metrics
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 742c4d5..4a26d19 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -7214,8 +7214,8 @@
<c:simple-property name="includeRuntime" readOnly="true" default="true"/>
</plugin-configuration>
- <metric property="collection-count" description="The total number of collections that have occurred."/>
- <metric property="collection-time" description="The approximate accumulated collection elapsed time in milliseconds."/>
+ <metric property="collection-count" description="The total number of collections that have occurred." measurementType="trendsup"/>
+ <metric property="collection-time" description="The approximate accumulated collection elapsed time in milliseconds." measurementType="trendsup"/>
<metric property="name" dataType="trait" description="The name representing this garbage collector"/>
<metric property="valid" dataType="trait" description="Whether this this memory manager is valid in the Java virtual machine."/>
commit 8130e34b50dfc81ae0074ac789d784d159b7b9aa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 10 17:01:01 2013 -0400
BZ 699893 911692 - if the user ran EAP 5 with cmd line option -Djboss.server.data.dir=/some/data/dir
then the AS5 plugin should look there, too, to try to find the jnp-service.url file
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
index 01eb105..670347f 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerDiscoveryComponent.java
@@ -500,32 +500,42 @@ public class ApplicationServerDiscoveryComponent implements ResourceDiscoveryCom
}
private String getJnpURL(JBossInstanceInfo cmdLine, File installHome, File configDir) {
- File jnpServiceUrlFile = new File(configDir, "data/jnp-service.url");
- if (jnpServiceUrlFile.exists() && jnpServiceUrlFile.canRead()) {
- BufferedReader br = null;
- try {
- br = new BufferedReader(new FileReader(jnpServiceUrlFile));
- String jnpUrl = br.readLine();
- if (jnpUrl != null) {
- if (log.isDebugEnabled()) {
- log.debug("Read JNP URL from jnp-service.url file: " + jnpUrl);
+ ArrayList<File> possibleJnpServiceUrlFiles = new ArrayList<File>(2);
+ possibleJnpServiceUrlFiles.add(new File(configDir, "data/jnp-service.url"));
+ // if the app server was told to go somewhere else to store its data files, look in there too (BZ 699893)
+ if (cmdLine.getSystemProperties() != null) {
+ String dataDir = cmdLine.getSystemProperties().getProperty("jboss.server.data.dir");
+ if (dataDir != null) {
+ possibleJnpServiceUrlFiles.add(new File(dataDir, "jnp-service.url"));
+ }
+ }
+ for (File jnpServiceUrlFile : possibleJnpServiceUrlFiles) {
+ if (jnpServiceUrlFile.exists() && jnpServiceUrlFile.canRead()) {
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new FileReader(jnpServiceUrlFile));
+ String jnpUrl = br.readLine();
+ if (jnpUrl != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Read JNP URL from jnp-service.url file: " + jnpUrl);
+ }
+ return jnpUrl;
}
- return jnpUrl;
- }
- } catch (IOException ioe) {
- // Nothing to do
- } finally {
- if (br != null) {
- try {
- br.close();
- } catch (IOException e) {
- // nada
+ } catch (IOException ioe) {
+ // Nothing to do
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ // nada
+ }
}
}
}
}
- log.warn("Failed to read JNP URL from '" + jnpServiceUrlFile + "'.");
+ log.warn("Failed to read JNP URL from: " + possibleJnpServiceUrlFiles);
// Above did not work, so fall back to our previous scheme
JnpConfig jnpConfig = getJnpConfig(installHome, configDir, cmdLine.getSystemProperties());
commit d2523a093115225352825051b5a795a7226a7c23
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri May 10 15:56:04 2013 -0400
BZ 903402 - fix code if windows drive is missing but otherwise the path is absolute
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
index 35a2263..e3c4a27 100644
--- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
+++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/helper/JBossInstanceInfo.java
@@ -243,7 +243,7 @@ public class JBossInstanceInfo {
for (String pathElement : this.classPath) {
if (pathElement.endsWith("run.jar")) {
runJar = new File(pathElement);
- if (!runJar.isAbsolute()) {
+ if (!runJar.isAbsolute() && !runJar.exists()) {
runJar = new File(this.processInfo.getExecutable().getCwd(), runJar.getPath());
}
if (!runJar.exists()) {
diff --git a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
index 9dadd39..b515af7 100644
--- a/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
+++ b/modules/plugins/jboss-as/src/main/java/org/rhq/plugins/jbossas/helper/JBossInstanceInfo.java
@@ -237,7 +237,7 @@ public class JBossInstanceInfo {
for (String pathElement : this.classPath) {
if (pathElement.endsWith("run.jar")) {
runJar = new File(pathElement);
- if (!runJar.isAbsolute()) {
+ if (!runJar.isAbsolute() && !runJar.exists()) {
runJar = new File(this.processInfo.getExecutable().getCwd(), runJar.getPath());
}
if (!runJar.exists()) {
commit 01d875b284d842df2ac4f099598b5f2a5f320bf2
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 16:34:51 2013 +0200
Provide the old method signature as fallback in case other plugins that inherit from this one, still need it.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index 9eb63f9..48fbf1f 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -53,12 +53,23 @@ public enum JBossProductType {
}
/**
+ * Determine the product type of a JBoss install. This implies an api version of 1.x which
+ * is a JBossAS 7.x
+ * @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
+ * @return the product type
+ * @deprecated "Use the version with the apiVersion"
+ */
+ @Deprecated
+ public static JBossProductType determineJBossProductType(File homeDir) {
+ return determineJBossProductType(homeDir,"1.0");
+ }
+
+ /**
* Determines the product type of a JBoss product installation.
*
- *
* @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
*
- * @param apiVersion
+ * @param apiVersion Api version of the domain api.
* @return the product type
*/
public static JBossProductType determineJBossProductType(File homeDir, String apiVersion) {
commit 3bba88c36f7d4a91ac5ac824c0e5b7fd43c3dd0b
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 14:39:21 2013 +0200
BZ 961787 - try to determine AS/WFLY via domain api version before falling back to directory names, as this is more reliable.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
index 9a4d5bd..cc13406 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
@@ -193,7 +193,8 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
serverPluginConfig.setHostname(managementHostPort.host);
serverPluginConfig.setPort(managementHostPort.port);
pluginConfig.setSimpleValue("realm", hostConfig.getManagementSecurityRealm());
- JBossProductType productType = JBossProductType.determineJBossProductType(homeDir);
+ String apiVersion = hostConfig.getDomainApiVersion();
+ JBossProductType productType = JBossProductType.determineJBossProductType(homeDir, apiVersion);
serverPluginConfig.setProductType(productType);
pluginConfig.setSimpleValue("hostXmlFileName", getHostXmlFileName(commandLine));
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index 9edfb2f..9eb63f9 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -37,7 +37,7 @@ public enum JBossProductType {
JPP("JPP", "JBoss EAP 6", "JBoss Portal Platform 6", "Portal Platform"),
// EWP("EWP", "JBoss EWP 6", "JBoss Enterprise Web Platform 6", "EWP"),
SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP"),
- WILDFLY8("WildFly","WildFly 8" ,"WildFly Appliction Server 8" , "WildFly");
+ WILDFLY8("WildFly","WildFly 8" ,"WildFly Application Server 8" , "WildFly");
public final String SHORT_NAME;
public final String NAME;
@@ -55,13 +55,28 @@ public enum JBossProductType {
/**
* Determines the product type of a JBoss product installation.
*
+ *
* @param homeDir the JBoss product installation directory (e.g. /opt/jboss-as-7.1.1.Final)
*
+ * @param apiVersion
* @return the product type
*/
- public static JBossProductType determineJBossProductType(File homeDir) {
+ public static JBossProductType determineJBossProductType(File homeDir, String apiVersion) {
try {
- return determineJBossProductTypeViaProductConfFile(homeDir);
+ JBossProductType jBossProductType = determineJBossProductTypeViaProductConfFile(homeDir);
+ if (jBossProductType==null) {
+ // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
+ // and thus have no product type. So we need to check differently
+ // AS 7.0/1 use a domain api version of 1.x, while WildFly uses version 2.0+
+ // like 2.0 in "urn:jboss:domain:2.0" from <server xmlns="..." > element in standalone.xml
+ if (apiVersion.startsWith("1")) {
+ jBossProductType = JBossProductType.AS;
+ } else {
+ // We should later check for newer WildFly versions to differentiate them
+ jBossProductType = JBossProductType.WILDFLY8;
+ }
+ }
+ return jBossProductType;
} catch (Exception e) {
// TODO: Log an error.
return determineJBossProductTypeViaHomeDirName(homeDir);
@@ -109,9 +124,7 @@ public enum JBossProductType {
throw new RuntimeException("Unknown product type: " + slot);
}
} else {
- // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
- // so we need another way to distinguish them
- productType = determineJBossProductTypeViaHomeDirName(homeDir);
+ productType = null;
}
return productType;
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
index a8909ff..329246e 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/helper/HostConfiguration.java
@@ -233,6 +233,14 @@ public class HostConfiguration {
return securityPropertyFile;
}
+ public String getDomainApiVersion() {
+
+ String version = document.getFirstChild().getAttributes().getNamedItem("xmlns").getTextContent();
+
+ version = version.substring(version.lastIndexOf(':')+1);
+ return version;
+ }
+
/**
* Run the passed xpathExpression on the prepopulated hostXml document and
* return the target element or attribute as a String.
commit 8868d16074902e9996f00cce8db697d02fce21ad
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 12:18:26 2013 +0200
BZ 960959 apply inventory status filtering with COMMITTED as default for searches.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
index 138ca40..2dde3a4 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java
@@ -52,7 +52,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Use this to get the global fields for this Criteria field type. Don't use inspection as the field names
* for this abstract base class do not conform (for legacy reasons) to the prefix convention help by the
* subclasses.
- *
+ *
* @return The set of global fields for this Criteria field type. Meaning, usable by all subclasses.
*/
public List<String> getGlobalFields() {
@@ -76,7 +76,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* private NonBindingOverrideFilter filterResourceOnly; // requires overrides - finds only those associated with a resource
* ...
* filterOverrides.put("resourceTypeOnly", "resourceType IS NOT NULL"); // notice no ? parameter
- *
+ *
* Note: Typically a null value is analogous to OFF.
*/
public enum NonBindingOverrideFilter {
@@ -87,12 +87,12 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Apply a restriction to reduce the cost of the {@link Criteria}-based query generation and execution routines.
*/
public enum Restriction {
- /**
+ /**
* This returns an empty {@link PageList} result whose {@link PageList#getTotalSize()} method otherwise
* contains the correct value.
*/
COUNT_ONLY,
- /**
+ /**
* This will return the {@link PageList} result whose {@link PageList#isUnbounded()} returned true, meaning
* that the value contained within {@link PageList#getTotalSize()} is invalid / undefined.
*/
@@ -121,10 +121,10 @@ public abstract class Criteria implements Serializable, BaseCriteria {
// All Criteria support sorting on ID
protected PageOrdering sortId;
-
+
// All Criteria support filtering on ID
protected Integer filterId;
-
+
// All Criteria support filtering on IDs
protected List<Integer> filterIds;
@@ -176,7 +176,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
addSortField("id");
this.sortId = sortId;
}
-
+
public void addFilterId(Integer filterId) {
this.filterId = filterId;
}
@@ -189,6 +189,13 @@ public abstract class Criteria implements Serializable, BaseCriteria {
orderingFieldNames.add("sort" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1));
}
+ /**
+ * Sets the paging constraints to return items [pageNumber * pageSize , ((pageNumber+1) * pageSize) -1 ].
+ * For this to work correctly, you also need to set the sort
+ * criteria (do not rely on implicit id-sorting to work correctly.
+ * @param pageNumber The page to fetch. This is 0-based.
+ * @param pageSize The number of items to return.
+ */
public void setPaging(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
@@ -196,7 +203,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
/**
* If the pageControl is set, then this criteria object will completely ignore any
- * calls made to setPaging(pageNumber, pageSize) as well as addSortField(fieldName),
+ * calls made to setPaging(pageNumber, pageSize) as well as addSortField(fieldName),
* which is useful from a server-side calling context where the PageControl object
* will already have been created for you by the extensions at the JSF layer.
*/
@@ -248,7 +255,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
/**
* If set to true, string-based filters will use exact string matches;
- * Default is 'false', which means we'll fuzzy match
+ * Default is 'false', which means we'll fuzzy match
*/
public void setStrict(boolean strict) {
this.strict = strict;
@@ -262,9 +269,9 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* By default, two queries will be generated for this Criteria: one which fetches the requested page/subset of
* entity results, and one which fetches the total cardinality of the result set. If you wish to only retrieve one
* of those pieces of data, you can do so by setting a restriction on the query generation and execution routines.
- *
+ *
* The restriction, once set, can be removed by passing NULL to this method.
- *
+ *
* @see Restriction
*/
public void setRestriction(Restriction restriction) {
@@ -325,7 +332,7 @@ public abstract class Criteria implements Serializable, BaseCriteria {
* Somewhat analogous to JPA's Query.getSingleResult. Wrap a CriteriaQuery result with this method when
* expecting a single result from the fetch. If the result set has only one entry it is returned. Otherwise
* a RuntimeException is thrown, indicating whether no results, or multiple results were found.
- *
+ *
* @param result
* @return
* @throws RuntimeException In not exactly one result is found. The message will include either the String
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 7a198bd..0038099 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -52,8 +52,6 @@ import org.infinispan.Cache;
import org.infinispan.manager.CacheContainer;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
@@ -349,6 +347,7 @@ public class AbstractRestBean {
rwt.setTypeName(resourceType.getName());
rwt.setTypeId(resourceType.getId());
rwt.setPluginName(resourceType.getPlugin());
+ rwt.setStatus(res.getInventoryStatus().name());
Resource parent = res.getParentResource();
if (parent != null) {
rwt.setParentId(parent.getId());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
index cea84c2..3879f73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/BadArgumentException.java
@@ -23,7 +23,10 @@ import javax.ejb.ApplicationException;
/**
* Exception if arguments are bad.
* Don't use java.lang.IllegalArgumentException, as this is no
- * Application Exception and gets wrapped
+ * Application Exception and gets wrapped.
+ *
+ * The ExceptionMapper translates this into a 406 repsonse code
+ *
* @author Heiko W. Rupp
*/
@ApplicationException(rollback = false, inherited = true)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 3e1d195..288e9f7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -177,14 +177,28 @@ public class ResourceHandlerBean extends AbstractRestBean {
@GET @GZIP
@Path("/")
+ @ApiError(code = 406, reason = "The passed inventory status was invalid")
@ApiOperation(value = "Search for resources by the given search string, possibly limited by category and paged", responseClass = "ResourceWithType")
- public Response getResourcesByQuery(@ApiParam("String to search in the resource name") @QueryParam("q") String q,
+ public Response getResourcesByQuery(@ApiParam("Limit results to param in the resource name") @QueryParam("q") String q,
@ApiParam("Limit to category (PLATFORM, SERVER, SERVICE") @QueryParam("category") String category,
@ApiParam("Page size for paging") @QueryParam("ps") @DefaultValue("20") int pageSize,
- @ApiParam("Page for paging") @QueryParam("page") Integer page,
+ @ApiParam("Page for paging, 0-based") @QueryParam("page") Integer page,
+ @ApiParam(value = "Limit to Inventory status of the resources", allowableValues = "ALL, NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED")
+ @DefaultValue("COMMITTED") @QueryParam("status") String status,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
+
ResourceCriteria criteria = new ResourceCriteria();
+ if (!status.toLowerCase().equals("all")) {
+ try {
+ criteria.addFilterInventoryStatus(InventoryStatus.valueOf(status.toUpperCase()));
+ } catch (IllegalArgumentException iae) {
+ throw new BadArgumentException("status","Value " + status + " is not in the list of allowed values: ALL, NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED" );
+ }
+ } else {
+ // JavaDoc says to explicitly set to null in order to get all Status
+ criteria.addFilterInventoryStatus(null);
+ }
if (q!=null) {
criteria.addFilterName(q);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
index 6b9aace..703e897 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/ResourceWithType.java
@@ -52,6 +52,7 @@ public class ResourceWithType {
Integer typeId;
String pluginName;
Integer parentId;
+ String status;
List<Link> links = new ArrayList<Link>();
private String ancestry;
@@ -126,6 +127,15 @@ public class ResourceWithType {
this.parentId = parentId;
}
+ @ApiProperty(value = "Inventory status of the resource.",allowableValues = "NEW, IGNORED, COMMITTED, DELETED, UNINVENTORIED" )
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
@XmlElementRef
public List<Link> getLinks() {
return links;
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index c71bbd8..3efd807 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -113,7 +113,6 @@ public class ResourcesTest extends AbstractBase {
@Test
public void testGetPlatformUILink() {
- Response response =
given()
.header(acceptJson)
.pathParam("id", _platformId)
@@ -145,6 +144,74 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testResourceQueryAllStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","all")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(200)
+ .body("links.self", notNullValue())
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryCommittedStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","committed")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(200)
+ .body("links.self", notNullValue())
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryNewStatus() throws Exception {
+
+ // Unfortunately we can not assume that there are
+ // any resources in other states than COMMITTED
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("status","NeW")
+ .expect()
+ .statusCode(200)
+ .when()
+ .get("/resource");
+ }
+
+ @Test
+ public void testResourceQueryBadStatus() throws Exception {
+ String json = get("/resource/platforms.json").asString();
+ String platformName = JsonPath.with(json).get("[0].resourceName");
+
+ given()
+ .header("Accept", "application/json")
+ .with()
+ .queryParam("q", platformName)
+ .queryParam("status","Frobnitz")
+ .queryParam("category", "platform")
+ .expect()
+ .statusCode(406)
+ .when()
+ .get("/resource");
+ }
+
+ @Test
public void testResourceQueryCategory() throws Exception {
with()
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
index 6cbcea0..f060101 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/Resource.java
@@ -33,6 +33,7 @@ public class Resource {
String typeName;
String pluginName;
Integer parentId;
+ String status;
int typeId;
List<Map> links;
String ancestry;
@@ -103,4 +104,12 @@ public class Resource {
public void setAncestry(String ancestry) {
this.ancestry = ancestry;
}
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
}
commit c12f45a0dac01b601ce05fc7046042b83e51b184
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri May 10 11:15:25 2013 +0200
Make this test use the RHQ server, so that no external EAP needs to be set up.
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
index 5532b13..7e3f45a 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ContentTest.java
@@ -176,7 +176,7 @@ public class ContentTest extends AbstractBase {
List<Map<String,Object>> resources =
given()
.header(acceptJson)
- .queryParam("q","EAP (127.0.0.1:9990)") // TODO fragile -- better search for it?
+ .queryParam("q","EAP (127.0.0.1:6990)") // TODO Can we identify the RHQ server itself better?
.queryParam("category","SERVER")
.expect()
.statusCode(200)
@@ -188,6 +188,7 @@ public class ContentTest extends AbstractBase {
assert resources.size()>0;
int as7Id = Integer.valueOf((String)resources.get(0).get("resourceId"));
+ int createdResourceId=-1;
// create child of eap6 as deployment
try {
@@ -223,25 +224,33 @@ public class ContentTest extends AbstractBase {
int status = response.getStatusCode();
String location = response.getHeader("Location");
- System.out.println("Location " + location + "\n\n");
+ System.out.println("\nLocation " + location + "\n\n");
assert location!=null;
// We need to check what we got. A 302 means the deploy is still
// in progress, so we need to wait a little longer
while (status==302) {
- status =
+ response =
given()
.header(acceptJson)
.log().everything()
.expect()
- .statusCode(isOneOf(200,201,302))
+ .statusCode(isOneOf(200, 201, 302))
.log().everything()
.when()
- .get(location)
- .getStatusCode();
+ .get(location);
+
+ status = response.getStatusCode();
}
+ createdResourceId = response.jsonPath().getInt("resourceId");
+
+ System.out.println("\n Deploy is done, resource Id = " + createdResourceId + " \n");
+ System.out.flush();
+
+ assert createdResourceId != -1;
+
} finally {
// Remove the uploaded content
@@ -254,47 +263,23 @@ public class ContentTest extends AbstractBase {
.when()
.delete("/content/{handle}");
+ System.out.println("\n Content removed \n");
+ System.out.flush();
+
+
+ // We need to wait here a little, as the machinery is not used to
+ // quick create-delete-cycles
+ Thread.sleep(20*1000L);
- // try to remove the created resource
- Response response =
given()
- .queryParam("q", "test-simple.war")
.header(acceptJson)
+ .queryParam("physical", "true") // Also remove target on the EAP instance
+ .pathParam("id",createdResourceId)
+ .log().everything()
.expect()
.log().everything()
.when()
- .get("/resource");
-
- List links = response.body().jsonPath().getList("links");
-
- System.out.println(links);
- assert links!=null;
-
- if (links.size()>0) {
-
- String link = null;
- @SuppressWarnings("unchecked")
- List<Map<String,Map<String,String>>> listOfMaps = (List<Map<String, Map<String, String>>>) links.get(0);
-
- for (Map<String,Map<String,String>> map : listOfMaps) {
- if (map.containsKey("self")) {
- link = map.get("self").get("href");
- break;
- }
- }
-
- assert link != null;
-
- System.out.println("Link: " + link);
-
- given()
- .header(acceptJson)
- .queryParam("physical","true") // Also remove target on the EAP instance
- .expect()
- .log().everything()
- .when()
- .delete(link);
- }
+ .delete("/resource/{id}");
}
commit 80e9f520ab6dfa5fa42357aa7fa5dbfdeb98d631
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 9 21:50:21 2013 -0400
BZ 951382 - if keystore/truststore is left undefined in agent config, we'll explicitly set the pref for the user using the "conf/" location
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
index d959552..6e1a95a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentMain.java
@@ -2313,6 +2313,9 @@ public class AgentMain {
* @throws Exception if any error causes the startup to fail
*/
private void startCommServices(BootstrapLatchCommandListener listener) throws Exception {
+ // BZ 951382 - if any locations for keystore/truststore are not configured, set our own defaults to the conf/ directory
+ assignDefaultLocationToKeystoreTruststoreFiles();
+
// create our client sender so we can send commands to our server
// do this before we create our auto-discovery listener and start the server-side services
// since it will be needed by the listener very quickly if the server is already online
@@ -2348,6 +2351,41 @@ public class AgentMain {
return;
}
+ private void assignDefaultLocationToKeystoreTruststoreFiles() {
+ File confDir = new File("conf");
+ if (!confDir.exists()) {
+ return; // conf/ doesn't exist (perhaps we are running in a test?) - do nothing and just fallback to the standard defaults
+ }
+
+ String prefNamesFileNames[][] = {
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_KEYSTORE_FILE_NAME },
+ { ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_FILE,
+ ServiceContainerConfigurationConstants.DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_FILE_NAME },
+ { AgentConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE,
+ AgentConfigurationConstants.DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_FILE_NAME } };
+
+ Preferences prefs = m_configuration.getPreferences();
+ for (String[] prefNameFileName : prefNamesFileNames) {
+ String value = prefs.get(prefNameFileName[0], null);
+ if (value == null) {
+ value = new File(confDir, prefNameFileName[1]).getAbsolutePath();
+ prefs.put(prefNameFileName[0], value);
+ LOG.debug(AgentI18NResourceKeys.CERT_FILE_LOCATION, prefNameFileName[0], value);
+ }
+ }
+
+ try {
+ prefs.flush();
+ } catch (Exception e) {
+ LOG.warn(AgentI18NResourceKeys.CANNOT_STORE_PREFERENCES, "keystore/truststore files", e);
+ }
+
+ return;
+ }
+
private boolean isAutoDiscoveryEnabled() {
return m_autoDiscoveryListener != null;
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
index 10761ff..21a39a9 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/i18n/AgentI18NResourceKeys.java
@@ -28,6 +28,9 @@ import mazz.i18n.annotation.I18NResourceBundle;
*/
@I18NResourceBundle(baseName = "agent-messages", defaultLocale = "en")
public interface AgentI18NResourceKeys {
+ @I18NMessage("Explicitly setting file location [{0}] to [{1}]")
+ String CERT_FILE_LOCATION = "AgentConfiguration.cert-file-location";
+
@I18NMessage("The configured server alias [{0}] cannot be resolved - will use localhost address. Cause: {1}")
String SERVER_ALIAS_UNKNOWN = "AgentConfiguration.server-alias-unknown";
commit 7c4577c895a469b5ddce6aa91eb6935eb5cf6cc9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 8 22:23:58 2013 -0400
BZ 535800 - can't use default protocol because it is automatically initialized and cached, not allowing us to use a customized one
add a main() for quick testing
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
index 6097ebe..16a4544 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
@@ -23,7 +23,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.security.KeyStore;
-import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
@@ -62,29 +61,13 @@ public class SecureConnector {
private final String truststoreAlgorithm;
/**
- * The {@link #openSecureConnection(URL) secure connections} built by this object will not
- * authenticate the server endpoint, but they will use the default secure socket protocol to
- * encrypt the connection traffic (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>).
- *
- * @throws NoSuchAlgorithmException if the default secure connection protocol cannot be determined
- */
- public SecureConnector() throws NoSuchAlgorithmException {
- this(null, null, null, null, null);
- }
-
- /**
* The {@link #openSecureConnection(URL) secure connections} built by this object will
* not authenticate the server endpoint, but they will use the given secure socket protocol
* to encrypt the connection traffic.
*
- * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
- * the JVM's default secure socket protocol will be used
- * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
- *
- * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
- * the default secure connection protocol cannot be determined
+ * @param secureSocketProtocol the secure socket protocol to use (e.g. "TLS")
*/
- public SecureConnector(String secureSocketProtocol) throws NoSuchAlgorithmException {
+ public SecureConnector(String secureSocketProtocol) {
this(secureSocketProtocol, null, null, null, null);
}
@@ -97,28 +80,22 @@ public class SecureConnector {
* truststore parameters are ignored and the secure connections built by this object will
* not authenticate the server endpoint.
*
- * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
- * the JVM's default secure socket protocol will be used
- * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ * @param secureSocketProtocol the secure socket protocol to use (e.g. "TLS")
* @param truststoreFile the truststore file containing authorized certificates
- * @param truststorePassword the password to the truststore file
- * @param truststoreType the type of the truststore file; if <code>null</code>, then the JVM's
+ * @param truststorePassword the password to the truststore file (if a file is given, this must not be <code>null</code>)
+ * @param truststoreType the type of the truststore file (e.g. "JKS"); if <code>null</code>, then the JVM's
* default type is used (see <code>java.security.KeyStore.getDefaultType()</code>)
- * @param truststoreAlgorithm the standard name of the trust management algorithm; if <code>null</code>,
- * then the JVM's default algorithm is used (see
+ * @param truststoreAlgorithm the standard name of the trust management algorithm (e.g. "SunX509");
+ * if <code>null</code>, then the JVM's default algorithm is used (see
* <code>javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()</code>)
- *
- * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
- * the default secure connection protocol cannot be determined
*/
public SecureConnector(String secureSocketProtocol, File truststoreFile, String truststorePassword,
- String truststoreType, String truststoreAlgorithm) throws NoSuchAlgorithmException {
+ String truststoreType, String truststoreAlgorithm) {
if (secureSocketProtocol == null) {
- this.secureSocketProtocol = SSLContext.getDefault().getProtocol();
- } else {
- this.secureSocketProtocol = secureSocketProtocol;
+ throw new IllegalArgumentException("secure socket protocol cannot be null");
}
+ this.secureSocketProtocol = secureSocketProtocol;
if (truststoreFile == null) {
// no truststore file was provided, we don't need to know any truststore parameters
@@ -129,17 +106,21 @@ public class SecureConnector {
} else {
// the truststore file is provided, make sure we have non-null truststore parameters, using defaults if need be
this.truststoreFile = truststoreFile;
+
+ if (truststorePassword == null) {
+ throw new IllegalArgumentException("truststorePassword cannot be null");
+ }
this.truststorePassword = truststorePassword;
if (truststoreType == null) {
truststoreType = KeyStore.getDefaultType();
}
- this.truststoreType = (truststoreType != null) ? truststoreType : "JKS";
+ this.truststoreType = truststoreType;
if (truststoreAlgorithm == null) {
truststoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
}
- this.truststoreAlgorithm = (truststoreAlgorithm != null) ? truststoreAlgorithm : "SunX509";
+ this.truststoreAlgorithm = truststoreAlgorithm;
}
return;
@@ -216,4 +197,16 @@ public class SecureConnector {
return true;
}
};
+
+ public static void main(String[] args) throws Exception {
+ HttpsURLConnection conn = new SecureConnector("TLS").openSecureConnection(new URL(args[0]));
+ java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+ java.io.InputStream input = new java.io.BufferedInputStream(conn.getInputStream(), 32768);
+ byte[] buffer = new byte[32768];
+ for (int bytesRead = input.read(buffer); bytesRead != -1; bytesRead = input.read(buffer)) {
+ out.write(buffer, 0, bytesRead);
+ }
+ out.flush();
+ System.out.println(out.toString());
+ }
}
\ No newline at end of file
commit 2c6438cd554b64aa97f2b83d1d5fe7f005d9f68f
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 8 16:43:36 2013 -0400
BZ 535800 - allow the agent to download the agent update binary over the configured SSL channel
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
index 9edad7f..ccd46db 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateDownload.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
+import javax.net.ssl.HttpsURLConnection;
+
import mazz.i18n.Logger;
import org.rhq.core.util.MessageDigestGenerator;
@@ -153,7 +155,13 @@ public class AgentUpdateDownload {
// we only support http/s
url = getDownloadUrl();
LOG.info(AgentI18NResourceKeys.UPDATE_DOWNLOAD_RETRIEVAL, info, url);
- conn = (HttpURLConnection) url.openConnection();
+
+ if (url.getProtocol().equals("https")) {
+ conn = openSecureConnection(url);
+ } else {
+ conn = (HttpURLConnection) url.openConnection(); // we only support http(s), so this cast is OK
+ }
+
inStream = conn.getInputStream();
// put the update content in the local file system
@@ -277,4 +285,24 @@ public class AgentUpdateDownload {
return false;
}
}
+
+ private HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ AgentConfiguration config = this.agent.getConfiguration();
+ String secureSocketProtocol = config.getClientSenderSecuritySocketProtocol();
+ SecureConnector secureConnector;
+ if (config.isClientSenderSecurityServerAuthMode()) {
+ File file = new File(config.getClientSenderSecurityTruststoreFile());
+ if (!file.isAbsolute()) {
+ file = new File(this.agent.getAgentHomeDirectory(), file.getPath());
+ }
+ String password = config.getClientSenderSecurityTruststorePassword();
+ String type = config.getClientSenderSecurityTruststoreType();
+ String algorithm = config.getClientSenderSecurityTruststoreAlgorithm();
+ secureConnector = new SecureConnector(secureSocketProtocol, file, password, type, algorithm);
+ } else {
+ secureConnector = new SecureConnector(secureSocketProtocol);
+ }
+
+ return secureConnector.openSecureConnection(url);
+ }
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
index b429fa8..6ef123a 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentUpdateVersion.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,14 @@
*/
package org.rhq.enterprise.agent;
+import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;
+import javax.net.ssl.HttpsURLConnection;
+
import mazz.i18n.Logger;
import org.rhq.core.util.exception.ThrowableUtil;
@@ -100,7 +103,13 @@ public class AgentUpdateVersion {
// we only support http/s
url = getVersionUrl();
LOG.debug(AgentI18NResourceKeys.UPDATE_VERSION_RETRIEVAL, url);
- conn = (HttpURLConnection) url.openConnection();
+
+ if (url.getProtocol().equals("https")) {
+ conn = openSecureConnection(url);
+ } else {
+ conn = (HttpURLConnection) url.openConnection(); // we only support http(s), so this cast is OK
+ }
+
versionProps = new Properties();
inStream = conn.getInputStream();
versionProps.load(inStream);
@@ -142,4 +151,24 @@ public class AgentUpdateVersion {
return;
}
+
+ private HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ AgentConfiguration config = this.agent.getConfiguration();
+ String secureSocketProtocol = config.getClientSenderSecuritySocketProtocol();
+ SecureConnector secureConnector;
+ if (config.isClientSenderSecurityServerAuthMode()) {
+ File file = new File(config.getClientSenderSecurityTruststoreFile());
+ if (!file.isAbsolute()) {
+ file = new File(this.agent.getAgentHomeDirectory(), file.getPath());
+ }
+ String password = config.getClientSenderSecurityTruststorePassword();
+ String type = config.getClientSenderSecurityTruststoreType();
+ String algorithm = config.getClientSenderSecurityTruststoreAlgorithm();
+ secureConnector = new SecureConnector(secureSocketProtocol, file, password, type, algorithm);
+ } else {
+ secureConnector = new SecureConnector(secureSocketProtocol);
+ }
+
+ return secureConnector.openSecureConnection(url);
+ }
}
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
new file mode 100644
index 0000000..6097ebe
--- /dev/null
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/SecureConnector.java
@@ -0,0 +1,219 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.agent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * If you need to make a connection to an external HTTP server using the https protocol,
+ * use this class to build the connection. You can specify which trusted certificates can be used
+ * to verify and authenticate the remote server via truststore file parameters passed into the constructor.
+ * In other words, you don't have to rely on the global system properties javax.net.ssl.keyStore and
+ * javax.net.ssl.trustStore to make your connection.
+ *
+ * This is useful if some other object running in your JVM requires
+ * javax.net.ssl.keyStore/javax.net.ssl.trustStore set to something other than what you want to use.
+ * Since those system properties can only be set once during the lifetime of the JVM, it is not possible
+ * to change them at runtime and expect the change to take effect. Besides, even if you could change them,
+ * this could then effect the other objects that do need those properties set to particular values.
+ *
+ * This object has the ability to make an encrypted call without requiring a truststore to exist (that is,
+ * you can encrypt the call but you will not have the server endpoint verified and authenticated). This
+ * can be useful if you aren't concerned with authenticating the endpoint but do want to encrypt the
+ * traffic.
+ *
+ * @author John Mazzitelli
+ */
+public class SecureConnector {
+ private final String secureSocketProtocol;
+ private final File truststoreFile;
+ private final String truststorePassword;
+ private final String truststoreType;
+ private final String truststoreAlgorithm;
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will not
+ * authenticate the server endpoint, but they will use the default secure socket protocol to
+ * encrypt the connection traffic (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>).
+ *
+ * @throws NoSuchAlgorithmException if the default secure connection protocol cannot be determined
+ */
+ public SecureConnector() throws NoSuchAlgorithmException {
+ this(null, null, null, null, null);
+ }
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will
+ * not authenticate the server endpoint, but they will use the given secure socket protocol
+ * to encrypt the connection traffic.
+ *
+ * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
+ * the JVM's default secure socket protocol will be used
+ * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ *
+ * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
+ * the default secure connection protocol cannot be determined
+ */
+ public SecureConnector(String secureSocketProtocol) throws NoSuchAlgorithmException {
+ this(secureSocketProtocol, null, null, null, null);
+ }
+
+ /**
+ * The {@link #openSecureConnection(URL) secure connections} built by this object will
+ * authenticate the server endpoint using the given truststore file and its related parameters.
+ * The connection will use the given secure socket protocol to encrypt the connection traffic.
+ *
+ * Note that if the given <code>truststoreFile</code> is <code>null</code>, the other
+ * truststore parameters are ignored and the secure connections built by this object will
+ * not authenticate the server endpoint.
+ *
+ * @param secureSocketProtocol the secure socket protocol to use; if <code>null</code>, then
+ * the JVM's default secure socket protocol will be used
+ * (see <code>javax.net.ssl.SSLContext.getDefault().getProtocol()</code>)
+ * @param truststoreFile the truststore file containing authorized certificates
+ * @param truststorePassword the password to the truststore file
+ * @param truststoreType the type of the truststore file; if <code>null</code>, then the JVM's
+ * default type is used (see <code>java.security.KeyStore.getDefaultType()</code>)
+ * @param truststoreAlgorithm the standard name of the trust management algorithm; if <code>null</code>,
+ * then the JVM's default algorithm is used (see
+ * <code>javax.net.ssl.TrustManagerFactory.getDefaultAlgorithm()</code>)
+ *
+ * @throws NoSuchAlgorithmException if <code>secureSocketProtocol</code> is <code>null</code>, and
+ * the default secure connection protocol cannot be determined
+ */
+ public SecureConnector(String secureSocketProtocol, File truststoreFile, String truststorePassword,
+ String truststoreType, String truststoreAlgorithm) throws NoSuchAlgorithmException {
+
+ if (secureSocketProtocol == null) {
+ this.secureSocketProtocol = SSLContext.getDefault().getProtocol();
+ } else {
+ this.secureSocketProtocol = secureSocketProtocol;
+ }
+
+ if (truststoreFile == null) {
+ // no truststore file was provided, we don't need to know any truststore parameters
+ this.truststoreFile = null;
+ this.truststorePassword = null;
+ this.truststoreType = null;
+ this.truststoreAlgorithm = null;
+ } else {
+ // the truststore file is provided, make sure we have non-null truststore parameters, using defaults if need be
+ this.truststoreFile = truststoreFile;
+ this.truststorePassword = truststorePassword;
+
+ if (truststoreType == null) {
+ truststoreType = KeyStore.getDefaultType();
+ }
+ this.truststoreType = (truststoreType != null) ? truststoreType : "JKS";
+
+ if (truststoreAlgorithm == null) {
+ truststoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ }
+ this.truststoreAlgorithm = (truststoreAlgorithm != null) ? truststoreAlgorithm : "SunX509";
+ }
+
+ return;
+ }
+
+ public HttpsURLConnection openSecureConnection(URL url) throws Exception {
+ // we assume the URL is https - if it is not, its an error so just let the cast throw exception
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+
+ TrustManager[] trustManagers;
+ SSLContext sslContext = SSLContext.getInstance(getSecureSocketProtocol());
+
+ if (getTruststoreFile() == null) {
+ // we are configured to not care about authenticating the server, just encrypt but don't worry about certificates
+ trustManagers = new TrustManager[] { NO_OP_TRUST_MANAGER };
+ connection.setHostnameVerifier(NO_OP_HOSTNAME_VERIFIER);
+ } else {
+ // We need to configure our SSL connection with the agent's truststore so we can authenticate the server.
+ // First, create a KeyStore, but load it with our truststore entries.
+ KeyStore keyStore = KeyStore.getInstance(getTruststoreType());
+ keyStore.load(new FileInputStream(getTruststoreFile()), getTruststorePassword().toCharArray());
+ // now create a truststore manager instance and initialize it with our KeyStore we created with all our truststore entries
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(getTruststoreAlgorithm());
+ tmf.init(keyStore);
+ trustManagers = tmf.getTrustManagers();
+ }
+
+ sslContext.init(null, trustManagers, null);
+ connection.setSSLSocketFactory(sslContext.getSocketFactory());
+
+ return connection;
+ }
+
+ public String getSecureSocketProtocol() {
+ return this.secureSocketProtocol;
+ }
+
+ public File getTruststoreFile() {
+ return this.truststoreFile;
+ }
+
+ public String getTruststorePassword() {
+ return this.truststorePassword;
+ }
+
+ public String getTruststoreType() {
+ return this.truststoreType;
+ }
+
+ public String getTruststoreAlgorithm() {
+ return this.truststoreAlgorithm;
+ }
+
+ private static TrustManager NO_OP_TRUST_MANAGER = new X509TrustManager() {
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ return;
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ return;
+ }
+ };
+
+ private static HostnameVerifier NO_OP_HOSTNAME_VERIFIER = new HostnameVerifier() {
+ @Override
+ public boolean verify(String s, SSLSession sslSession) {
+ return true;
+ }
+ };
+}
\ No newline at end of file
commit 8091c631ae4cebe9a19825f3c107753590bec922
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 10:15:23 2013 -0700
[BZ 960646] - RFE Redesigned Availability Chart - i18n.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index f0db5a2..fbce610 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -124,11 +124,13 @@ public class AvailabilityOverUnderGraphType {
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverEndLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
- global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()()
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartTitleLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartUpLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailChartDownLabel()()
);
@@ -264,7 +266,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-family", "Arial, Verdana, sans-serif;")
.style("font-weight", "bold")
.attr("fill", "#003168")
- .text("Availability");
+ .text(availChartContext.chartTitle);
svg.append("text")
.attr("class", "upLabel")
@@ -274,7 +276,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "9px")
.attr("fill", "#50505a")
.style("text-anchor", "end")
- .text("UP");
+ .text(availChartContext.chartUpLabel);
svg.append("text")
.attr("class", "downLabel")
@@ -284,7 +286,7 @@ public class AvailabilityOverUnderGraphType {
.style("font-size", "9px")
.attr("fill", "#50505a")
.style("text-anchor", "end")
- .text("DOWN");
+ .text(availChartContext.chartDownLabel);
}
@@ -355,8 +357,16 @@ public class AvailabilityOverUnderGraphType {
return MSG.chart_hover_start_label();
}
- public String getChartHoverEndLabel() {
- return MSG.chart_hover_end_label();
+ public String getAvailChartDownLabel() {
+ return MSG.avail_chart_down_label();
+ }
+
+ public String getAvailChartUpLabel() {
+ return MSG.avail_chart_up_label();
+ }
+
+ public String getAvailChartTitleLabel() {
+ return MSG.avail_chart_title_label();
}
public String getChartHoverBarLabel() {
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 0c5af20..00a68ef 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+avail_chart_down_label = DOWN
+avail_chart_title_label = Availability
+avail_chart_up_label = UP
chart_date_label = Date
chart_down_label = Down
chart_hover_availability_label = Availability
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index 42405aa..a27fb3c 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -29,6 +29,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 8185e7f..5415ed0 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -9,6 +9,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index c15e129..8f47413 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -9,6 +9,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 8105460..5d19d06 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -7,6 +7,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index d50a54e..743c4b5 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index fb45e35..772c4e4 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -6,6 +6,9 @@
## http://rhq-project.org/display/RHQ/Working+with+the+Resource+Bundles
##
####################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index e929386..03dfa4e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -6,6 +6,9 @@
# https://docs.jboss.org/author/display/RHQ/Working+with+the+Resource+Bundles
#
###################################
+##avail_chart_down_label = DOWN
+##avail_chart_title_label = Availability
+##avail_chart_up_label = UP
##chart_date_label = Date
##chart_down_label = Down
##chart_time_label = Start
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 081a9a2..3b35252 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -48,7 +48,7 @@ var ChartContext = function (chartId, chartHeight, metricsData, xAxisLabel, char
this.chartSelection = this.chartHandle + " svg";
},
-AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverStartLabel, hoverEndLabel, hoverBarLabel, availabilityLabel, chartHoverTimeFormat, chartHoverDateFormat) {
+AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverStartLabel, hoverBarLabel, availabilityLabel, chartHoverTimeFormat, chartHoverDateFormat, chartTitle, chartUpLabel, chartDownLabel) {
"use strict";
if (!(this instanceof AvailChartContext)) {
throw new Error("AvailChartContext function cannot be called as a function.")
@@ -60,10 +60,12 @@ AvailChartContext = function (chartId, availData, dateLabel, timeLabel, hoverSta
this.dateLabel = dateLabel;
this.timeLabel = timeLabel;
this.hoverStartLabel = hoverStartLabel;
- this.hoverEndLabel = hoverEndLabel;
this.hoverBarLabel = hoverBarLabel;
this.hoverBarAvailabilityLabel = availabilityLabel;
this.chartHoverTimeFormat = chartHoverTimeFormat;
this.chartHoverDateFormat = chartHoverDateFormat;
+ this.chartTitle = chartTitle;
+ this.chartDownLabel = chartDownLabel;
+ this.chartUpLabel = chartUpLabel;
};
commit 59df0f08367521576187063a6bbafaa6ba0be9c2
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 08:45:18 2013 -0700
Make x-axis more readable on Safari, IE. These browsers even though they are using the same SVG fonts, render wider fonts showing up as labels running into one another. Reduced the clutter on the x-axis for increased readability.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index e38df39..f0db5a2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -162,7 +162,7 @@ public class AvailabilityOverUnderGraphType {
xAxis = $wnd.d3.svg.axis()
.scale(timeScale)
- .ticks(12)
+ .ticks(8)
.tickSize(13, 0, 0)
.orient("bottom"),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index bf08615..4d71192 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -129,13 +129,8 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
else {
console.log("Using Large Charts Profile");
// we use the width already defined above
- if(isIEBrowserGreaterThanOrEqualTo(9)){
- xTicks = 8;
- xTickSubDivide = 5;
- }else {
- xTicks = 12;
- xTickSubDivide = 5;
- }
+ xTicks = 8;
+ xTickSubDivide = 5;
chartData = chartContext.data;
}
commit c8bbd8b0c5dcfa51a2d653a95bc83d73d80178be
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 8 08:30:08 2013 -0700
[BZ 960521] Globally uncaught exception on clicking on resource name link on IE9.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 4e6a0ce..e38df39 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -215,7 +215,7 @@ public class AvailabilityOverUnderGraphType {
}
else {
// should not ever happen, but...
- console.warn("AvailabilityType not valid.");
+ console.log("AvailabilityType not valid.");
return "#000"; //black
}
},
@@ -318,13 +318,11 @@ public class AvailabilityOverUnderGraphType {
return {
// Public API
- draw: function (chartContext) {
+ draw: function (availChartContext) {
"use strict";
- console.info("AvailabilityChart");
- //console.time("availabilityChart");
+ console.log("AvailabilityChart");
drawBars(availChartContext);
createHovers();
- //console.timeEnd("availabilityChart");
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index 15f400d..bf08615 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -38,7 +38,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
*/
@Override
public native void drawJsniChart() /*-{
- //console.log("Draw Stacked Bar jsni chart");
+ console.log("Draw Stacked Bar jsni chart");
var global = this,
// create a chartContext object (from rhq.js) with the data required to render to a chart
@@ -120,14 +120,14 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
// if window is too small server up small chart
if (useSmallCharts()) {
- //console.log("Using Small Charts Profile for width: "+getChartWidth());
+ console.log("Using Small Charts Profile for width: "+getChartWidth());
width = 250;
xTicks = 3;
xTickSubDivide = 2;
chartData = chartContext.data.slice(chartContext.data.length - numberOfBarsForSmallGraph, chartContext.data.length - 1);
}
else {
- //console.log("Using Large Charts Profile");
+ console.log("Using Large Charts Profile");
// we use the width already defined above
if(isIEBrowserGreaterThanOrEqualTo(9)){
xTicks = 8;
@@ -613,8 +613,7 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
"use strict";
// Guard condition that can occur when a portlet has not been configured yet
if (chartContext.data.length > 0) {
- //console.info("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
- //console.time("chart");
+ console.log("Creating Chart: "+ chartContext.chartSelection + " --> "+ chartContext.chartTitle);
determineScale();
createHeader(chartContext.chartTitle);
@@ -624,11 +623,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
createXandYAxes();
createAvgLines();
if (oobMax > 0) {
- //console.info("OOB Data Exists!");
+ console.log("OOB Data Exists!");
createOOBLines();
}
createHovers(chartContext);
- //console.timeEnd("chart");
}
}
}; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
index 27c4cc0..081a9a2 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/rhq.js
@@ -2,29 +2,9 @@
* Charting Javascript Functions.
*/
-// Avoid `console` errors in browsers that lack a console.
-(function() {
- var method;
- var noop = function () {};
- var methods = [
- 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
- 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
- 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
- 'timeStamp', 'trace', 'warn'
- ];
- var length = methods.length;
- var console = (window.console = window.console || {});
-
- while (length--) {
- method = methods[length];
-
- // Only stub undefined methods.
- if (!console[method]) {
- console[method] = noop;
- }
- }
-} ());
-
+// Handle browsers not supporting console object
+if (!window.console) window.console = {};
+if (!window.console.log) window.console.log = function () { };
/**
* ChartContext Constructor Object
commit db8f9686b96e2e3c44e61162b1a0d2d388fc59e9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 13:48:42 2013 +0200
BZ 960529 - check for non-existing resources when obtaining availability
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 4e00625..3e1d195 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -338,6 +338,10 @@ public class ResourceHandlerBean extends AbstractRestBean {
@ApiParam(value="Start time", defaultValue = "30 days ago") @QueryParam("start") long start,
@ApiParam(value="End time", defaultValue = "Now") @QueryParam("end") long end,
@Context HttpHeaders headers) {
+
+ // Vaildate it the resource exists
+ fetchResource(resourceId);
+
if (end==0)
end = System.currentTimeMillis();
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
index 1dee0f1..c71bbd8 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/ResourcesTest.java
@@ -499,6 +499,22 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testCreateChildForUnknownParent() throws Exception {
+
+ given()
+ .body("{\"value\":\"CPU\"}") // Type of new resource
+ .header("Content-Type", "application/json")
+ .header("Accept", "application/json")
+ .pathParam("name", "test")
+ .queryParam("plugin", "Platforms")
+ .queryParam("parentId", 321)
+ .expect()
+ .statusCode(404)
+ .log().ifError()
+ .when().post("/resource/{name}");
+ }
+
+ @Test
public void testAlertsForResource() throws Exception {
given()
.header("Accept", "application/json")
@@ -521,6 +537,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testSchedulesForUnknownResource() throws Exception {
+ given()
+ .header("Accept", "application/json")
+ .pathParam("id", 123)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/schedules");
+ }
+
+ @Test
public void testAvailabilityForResourceJson() throws Exception {
given()
.header(acceptJson)
@@ -532,6 +559,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAvailabilityForUnknownResource() throws Exception {
+ given()
+ .header(acceptJson)
+ .pathParam("id", 532)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/availability");
+ }
+
+ @Test
public void testAvailabilityForResourceXml() throws Exception {
given()
.header(acceptXml)
@@ -554,6 +592,17 @@ public class ResourcesTest extends AbstractBase {
}
@Test
+ public void testAvailabilityHistoryForUnknownResource() throws Exception {
+ given()
+ .header(acceptJson)
+ .pathParam("id", -42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/resource/{id}/availability/history");
+ }
+
+ @Test
public void testAvailabilityHistoryForResourceXml() throws Exception {
given()
.header(acceptXml)
commit 17c3db8f19d0b70a6f0d910450523c245cd6f8b9
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 09:17:48 2013 +0200
Code cleanup and improvements for the REST-api
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
index 2746823..7a198bd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AbstractRestBean.java
@@ -81,21 +81,21 @@ import org.rhq.enterprise.server.rest.domain.ResourceWithType;
@SuppressWarnings("unchecked")
public class AbstractRestBean {
- Log log = LogFactory.getLog(getClass().getName());
+ protected Log log = LogFactory.getLog(getClass().getName());
- static private final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
+ private static final CacheKey META_KEY = new CacheKey("rhq.rest.resourceMeta", 0);
@javax.annotation.Resource( name = "ISPN")
- protected CacheContainer container;
+ private CacheContainer container;
protected Cache<CacheKey, Object> cache;
/** Subject of the caller that gets injected via {@link SetCallerInterceptor} */
protected Subject caller;
@EJB
- ResourceManagerLocal resMgr;
+ protected ResourceManagerLocal resMgr;
@EJB
- ResourceGroupManagerLocal resourceGroupManager;
+ protected ResourceGroupManagerLocal resourceGroupManager;
@PostConstruct
public void start() {
@@ -116,15 +116,15 @@ public class AbstractRestBean {
freemarker.template.Configuration config = new freemarker.template.Configuration();
// XXX fall-over to ClassTL after failure in FTL seems not to work
- // FileTemplateLoader ftl = new FileTemplateLoader(new File("src/main/resources"));
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "/rest_templates/");
TemplateLoader[] loaders = new TemplateLoader[] { ctl };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
config.setTemplateLoader(mtl);
- if (!templateName.endsWith(".ftl"))
+ if (!templateName.endsWith(".ftl")) {
templateName = templateName + ".ftl";
+ }
Template template = config.getTemplate(templateName);
StringWriter out = new StringWriter();
@@ -171,8 +171,9 @@ public class AbstractRestBean {
CacheValue value = (CacheValue) cache.get(key);
+ boolean debugEnabled = log.isDebugEnabled();
if (null != value) {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Hit for " + key);
}
@@ -180,12 +181,12 @@ public class AbstractRestBean {
o = value.getValue();
} else {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Hit ignored, caller " + caller.toString() + " not found");
}
}
} else {
- if (log.isDebugEnabled()) {
+ if (debugEnabled) {
log.debug("Cache Miss for " + key);
}
}
@@ -351,8 +352,9 @@ public class AbstractRestBean {
Resource parent = res.getParentResource();
if (parent != null) {
rwt.setParentId(parent.getId());
- } else
+ } else {
rwt.setParentId(0);
+ }
rwt.setAncestry(res.getAncestry());
@@ -429,8 +431,9 @@ public class AbstractRestBean {
protected ResourceGroup fetchGroup(int groupId, boolean requireCompatible) {
ResourceGroup resourceGroup;
resourceGroup = resourceGroupManager.getResourceGroup(caller, groupId);
- if (resourceGroup == null)
+ if (resourceGroup == null) {
throw new StuffNotFoundException("Group with id " + groupId);
+ }
if (requireCompatible) {
if (resourceGroup.getGroupCategory() != GroupCategory.COMPATIBLE) {
throw new BadArgumentException("Group with id " + groupId,"it is no compatible group");
@@ -445,8 +448,9 @@ public class AbstractRestBean {
gr.setId(group.getId());
gr.setCategory(group.getGroupCategory());
gr.setRecursive(group.isRecursive());
- if (group.getGroupDefinition()!=null)
+ if (group.getGroupDefinition()!=null) {
gr.setDynaGroupDefinitionId(group.getGroupDefinition().getId());
+ }
gr.setExplicitCount(group.getExplicitResources().size());
gr.setImplicitCount(group.getImplicitResources().size());
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
@@ -526,16 +530,6 @@ public class AbstractRestBean {
return ms;
}
- Configuration mapToConfiguration(Map<String,Object> in) {
- Configuration config = new Configuration();
- for (Map.Entry<String,Object> entry : in.entrySet()) {
- config.put(new PropertySimple(entry.getKey(),entry.getValue())); // TODO honor more types
- }
-
- return config;
-
- }
-
/**
* Set the caching header on the response
* @param builder Response builder to put the caching header on
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 06bc8ae..d203cd3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -106,22 +106,22 @@ import org.rhq.enterprise.server.rest.domain.Link;
public class AlertDefinitionHandlerBean extends AbstractRestBean {
@EJB
- AlertDefinitionManagerLocal alertDefinitionManager;
+ private AlertDefinitionManagerLocal alertDefinitionManager;
@EJB
- AlertNotificationManagerLocal notificationMgr;
+ private AlertNotificationManagerLocal notificationMgr;
@EJB
- AlertConditionManagerLocal conditionMgr;
+ private AlertConditionManagerLocal conditionMgr;
@EJB
- AlertManagerLocal alertManager;
+ private AlertManagerLocal alertManager;
@EJB
- ResourceGroupManagerLocal resourceGroupMgr;
+ private ResourceGroupManagerLocal resourceGroupMgr;
@EJB
- ResourceTypeManagerLocal resourceTypeMgr;
+ private ResourceTypeManagerLocal resourceTypeMgr;
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
@@ -169,8 +169,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@Context Request request, @Context UriInfo uriInfo) {
AlertDefinition def = alertDefinitionManager.getAlertDefinition(caller, definitionId);
- if (def==null)
+ if (def==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId );
+ }
EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
@@ -285,8 +286,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@Context UriInfo uriInfo) {
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,definitionId);
- if (definition==null)
+ if (definition==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId);
+ }
definition = new AlertDefinition(definition); // detach
@@ -302,10 +304,12 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
// Set the recovery id if such a definition exists at all
if (definitionRest.getRecoveryId()>0) {
AlertDefinition recoveryDef = alertDefinitionManager.getAlertDefinition(caller,definitionRest.getRecoveryId());
- if (recoveryDef!=null)
+ if (recoveryDef!=null) {
definition.setRecoveryId(definitionRest.getRecoveryId());
- else
+ }
+ else {
throw new StuffNotFoundException("Alert to recover with id " + definitionRest.getRecoveryId());
+ }
}
@@ -348,34 +352,24 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < vals.length ; i++) {
builder.append(vals[i].name());
- if (i < vals.length-1)
+ if (i < vals.length-1) {
builder.append(", ");
+ }
}
throw new BadArgumentException("dampening category","Allowed values are: " + builder.toString());
}
AlertDampening dampening = new AlertDampening(dampeningCategory);
- if (adr.getDampeningCount()!=null) {
- if (adr.getDampeningCount().contains(" ")) {
- String tmp = adr.getDampeningCount().trim();
- int num = Integer.parseInt(tmp.substring(0,tmp.indexOf(' ')));
- tmp = tmp.substring(tmp.lastIndexOf(' ')).trim();
- dampening.setValue(num);
- dampening.setValueUnits(AlertDampening.TimeUnits.valueOf(tmp.toUpperCase()));
- }
- else {
- dampening.setValue(Integer.parseInt(adr.getDampeningCount()));
- }
- }
- if (adr.getDampeningPeriod()!=null) {
- if (adr.getDampeningPeriod().contains(" ")) {
- String tmp = adr.getDampeningPeriod().trim();
- int num = Integer.parseInt(tmp.substring(0,tmp.indexOf(' ')));
- tmp = tmp.substring(tmp.lastIndexOf(' ')).trim();
- dampening.setPeriod(num);
- dampening.setPeriodUnits(AlertDampening.TimeUnits.valueOf(tmp.toUpperCase()));
- }
- else {
- dampening.setPeriod(Integer.parseInt(adr.getDampeningPeriod()));
+ if (adr.getDampeningCount()>-1) {
+ dampening.setValue(adr.getDampeningCount());
+ }
+ if (adr.getDampeningPeriod()>0) {
+ dampening.setPeriod(adr.getDampeningPeriod());
+ try {
+ if (adr.getDampeningUnit()!=null) {
+ dampening.setPeriodUnits(AlertDampening.TimeUnits.valueOf(adr.getDampeningUnit().toUpperCase()));
+ }
+ } catch (Exception e) {
+ throw new BadArgumentException("dampenign unit", "Allowed values are MINUTES,HOURS,DAYS, WEEKS");
}
}
@@ -439,8 +433,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
definition2 = entityManager.find(AlertDefinition.class,definitionId);
AlertCondition condition=null;
for (AlertCondition c: definition2.getConditions()) {
- if (c.getId() == conditionId)
+ if (c.getId() == conditionId) {
condition=c;
+ }
}
definition2.getConditions().remove(condition);
@@ -522,8 +517,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The id of the condition to retrieve") @PathParam("cid") int conditionId) {
AlertCondition condition = conditionMgr.getAlertConditionById(conditionId);
- if (condition==null)
+ if (condition==null) {
throw new StuffNotFoundException("No condition with id " + conditionId);
+ }
AlertConditionRest acr = conditionToConditionRest(condition);
return Response.ok(acr).build();
@@ -565,8 +561,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
AlertConditionRest result = conditionToConditionRest(createdCondition);
Response.ResponseBuilder builder;
- if (isCreate)
+ if (isCreate) {
builder = Response.created(uri);
+ }
else {
builder = Response.ok();
builder.location(uri);
@@ -583,8 +580,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The id of the notification definition to retrieve") @PathParam("nid") int notificationId) {
AlertNotification notification = notificationMgr.getAlertNotification(caller,notificationId);
- if (notification==null)
+ if (notification==null) {
throw new StuffNotFoundException("No notification with id " + notificationId);
+ }
AlertNotificationRest anr = notificationToNotificationRest(notification);
return Response.ok(anr).build();
@@ -618,8 +616,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
@ApiParam("The updated notification definition to use") AlertNotificationRest notificationRest) {
AlertNotification notification = notificationMgr.getAlertNotification(caller,notificationId);
- if (notification==null)
+ if (notification==null) {
throw new StuffNotFoundException("No notification with id " + notificationId);
+ }
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,notification.getAlertDefinition().getId());
@@ -634,8 +633,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
List<AlertNotification> notifications = definition.getAlertNotifications();
int newNotifId = 0;
for (AlertNotification n : notifications) {
- if (n.getSenderName().equals(notification.getSenderName()))
+ if (n.getSenderName().equals(notification.getSenderName())) {
newNotifId = n.getId();
+ }
}
AlertNotification result = notificationMgr.getAlertNotification(caller,newNotifId);
@@ -667,8 +667,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
// Now check if the definition exists as well
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(caller,definitionId);
- if (definition==null)
+ if (definition==null) {
throw new StuffNotFoundException("AlertDefinition with id " + definitionId);
+ }
// definition and sender are valid, continue
int existingNotificationCount = definition.getAlertNotifications().size();
@@ -816,10 +817,13 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
adr.setDampeningCategory(dampening.getCategory().name());
AlertDampening.TimeUnits units = dampening.getValueUnits();
String s = units != null ? " " + units.name() : "";
- adr.setDampeningCount(dampening.getValue() + s);
+ adr.setDampeningCount(dampening.getValue());
units = dampening.getPeriodUnits();
s = units != null ? " " + units.name() : "";
- adr.setDampeningPeriod(dampening.getPeriod() + s);
+ adr.setDampeningPeriod(dampening.getPeriod());
+ if (dampening.getPeriodUnits()!=null) {
+ adr.setDampeningUnit(dampening.getPeriodUnits().name());
+ }
if (def.getResource()!=null) {
adr.getLinks().add(createUILink(uriInfo,UILinkTemplate.RESOURCE_ALERT_DEF,def.getResource().getId(),adr.getId()));
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
index 0a37a9d..4c80bd1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertHandlerBean.java
@@ -79,10 +79,8 @@ import org.rhq.enterprise.server.rest.domain.*;
@Interceptors(SetCallerInterceptor.class)
public class AlertHandlerBean extends AbstractRestBean {
-// private final Log log = LogFactory.getLog(AlertHandlerBean.class);
-
@EJB
- AlertManagerLocal alertManager;
+ private AlertManagerLocal alertManager;
@GZIP
@@ -107,10 +105,12 @@ public class AlertHandlerBean extends AbstractRestBean {
if (resourceId!=null && definitionId!=null) {
throw new BadArgumentException("At most one of 'resourceId' and 'definitionId' may be given");
}
- if (size==0)
+ if (size==0) {
throw new BadArgumentException("size","Must not be 0");
- if (page<1)
+ }
+ if (page<1) {
throw new BadArgumentException("page","Must be >=1");
+ }
AlertCriteria criteria = new AlertCriteria();
@@ -119,8 +119,9 @@ public class AlertHandlerBean extends AbstractRestBean {
pageControl.setPageNumber(page);
criteria.setPageControl(pageControl);
}
- else
+ else {
criteria.setPaging(page-1, size); // TODO implement linking to next page
+ }
if (since!=null) {
criteria.addFilterStartTime(since);
@@ -335,8 +336,9 @@ public class AlertHandlerBean extends AbstractRestBean {
AlertCriteria criteria = new AlertCriteria();
criteria.addFilterId(id);
List<Alert> alerts = alertManager.findAlertsByCriteria(caller,criteria);
- if (alerts.isEmpty())
+ if (alerts.isEmpty()) {
throw new StuffNotFoundException("Alert with id " + id);
+ }
return alerts.get(0);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
index 07b2a1c..1099679 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/CustomExceptionMapper.java
@@ -43,9 +43,9 @@ import org.rhq.enterprise.server.rest.domain.RHQErrorWrapper;
public class CustomExceptionMapper implements ExceptionMapper<Exception> {
@Context
- HttpHeaders httpHeaders;
+ private HttpHeaders httpHeaders;
- Log log = LogFactory.getLog(getClass().getName());
+ private Log log = LogFactory.getLog(getClass().getName());
@Override
public Response toResponse(Exception e) {
@@ -53,24 +53,25 @@ public class CustomExceptionMapper implements ExceptionMapper<Exception> {
Response.ResponseBuilder builder;
Response.Status status;
- if (e instanceof StuffNotFoundException)
+ if (e instanceof StuffNotFoundException) {
status =Response.Status.NOT_FOUND;
- else if (e instanceof ResourceNotFoundException)
+ } else if (e instanceof ResourceNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ResourceGroupNotFoundException)
+ } else if (e instanceof ResourceGroupNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ResourceTypeNotFoundException)
+ } else if (e instanceof ResourceTypeNotFoundException) {
status = Response.Status.NOT_FOUND;
- else if (e instanceof ParameterMissingException)
+ } else if (e instanceof ParameterMissingException) {
status = Response.Status.NOT_ACCEPTABLE;
- else if (e instanceof BadArgumentException)
+ } else if (e instanceof BadArgumentException) {
status = Response.Status.NOT_ACCEPTABLE;
- else if (e instanceof PermissionException)
+ } else if (e instanceof PermissionException) {
status = Response.Status.FORBIDDEN;
- else if (e instanceof EJBException && e.getCause()!=null && e.getCause() instanceof IllegalArgumentException)
+ } else if (e instanceof EJBException && e.getCause()!=null && e.getCause() instanceof IllegalArgumentException) {
status = Response.Status.NOT_ACCEPTABLE;
- else
+ } else {
status = Response.Status.SERVICE_UNAVAILABLE;
+ }
builder = Response.status(status);
String message = e.getMessage();
@@ -93,8 +94,9 @@ public class CustomExceptionMapper implements ExceptionMapper<Exception> {
log.debug(e.getMessage());
mediaType = MediaType.TEXT_PLAIN_TYPE;
}
- if (mediaType.getType().equals("text") && mediaType.getSubtype().equals("csv"))
+ if (mediaType.getType().equals("text") && mediaType.getSubtype().equals("csv")) {
mediaType = MediaType.TEXT_PLAIN_TYPE;
+ }
if (mediaType.equals(MediaType.TEXT_PLAIN_TYPE)) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
index ccfed9f..8bc2cb9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/OperationsHandlerBean.java
@@ -47,6 +47,8 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
+import com.wordnik.swagger.annotations.ApiError;
+import com.wordnik.swagger.annotations.ApiErrors;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
@@ -69,13 +71,17 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
+import org.rhq.core.domain.util.StringUtils;
+import org.rhq.enterprise.server.operation.OperationDefinitionNotFoundException;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceNotFoundException;
import org.rhq.enterprise.server.rest.domain.Link;
import org.rhq.enterprise.server.rest.domain.OperationDefinitionRest;
import org.rhq.enterprise.server.rest.domain.OperationHistoryRest;
import org.rhq.enterprise.server.rest.domain.OperationRest;
import org.rhq.enterprise.server.rest.domain.SimplePropDef;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
/**
* Deal with operations
@@ -88,32 +94,31 @@ import org.rhq.enterprise.server.rest.domain.SimplePropDef;
public class OperationsHandlerBean extends AbstractRestBean {
@EJB
- OperationManagerLocal opsManager;
+ private OperationManagerLocal opsManager;
@EJB
- ResourceManagerLocal resourceManager;
+ private ResourceManagerLocal resourceManager;
@GET
@Path("definition/{id}")
@Cache(maxAge = 1200)
@ApiOperation("Retrieve a single operation definition by its id")
public Response getOperationDefinition(
- @ApiParam("Id of the definition to retrieve") @PathParam("id") int definitionId,
- @ApiParam("Id of a resource that supports this operation") @QueryParam("resourceId") Integer resourceId,
- @Context UriInfo uriInfo,
- @Context Request request,
- @Context HttpHeaders httpHeaders) {
-
-
+ @ApiParam("Id of the definition to retrieve") @PathParam("id") int definitionId,
+ @ApiParam("Id of a resource that supports this operation") @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request) {
OperationDefinition def;
def = getFromCache(definitionId, OperationDefinition.class);
if (def==null) {
- def = opsManager.getOperationDefinition(caller,definitionId);
- if (def==null)
- throw new StuffNotFoundException("OperationDefinition with id " + definitionId);
- else
+ try {
+ def = opsManager.getOperationDefinition(caller,definitionId);
putToCache(definitionId,OperationDefinition.class,def);
+ }
+ catch (OperationDefinitionNotFoundException ode) {
+ throw new StuffNotFoundException("Operation definition with id " + definitionId);
+ }
}
EntityTag eTag = new EntityTag(Integer.toHexString(def.hashCode()));
@@ -145,43 +150,27 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
- private void copyParamsForDefinition(OperationDefinition def, OperationDefinitionRest odr) {
- ConfigurationDefinition cd = def.getParametersConfigurationDefinition();
- if (cd==null)
- return;
-
- for (Map.Entry<String,PropertyDefinition> entry : cd.getPropertyDefinitions().entrySet()) {
- PropertyDefinition pd = entry.getValue();
- if (pd instanceof PropertyDefinitionSimple) {
- PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
- SimplePropDef prop = new SimplePropDef();
- prop.setName(pds.getName());
- prop.setRequired(pds.isRequired());
- prop.setType(pds.getType());
- prop.setDefaultValue(pds.getDefaultValue());
- odr.addParam(prop);
- }
- log.debug("copyParams: " + pd.getName() + " not yet supported");
- }
- }
-
@GZIP
@GET
@Path("definitions")
@Cache(maxAge = 1200)
@ApiOperation("List all operation definitions for a resource")
public Response getOperationDefinitions(
- @ApiParam(value = "Id of the resource",required = true) @QueryParam("resourceId") Integer resourceId,
- @Context UriInfo uriInfo,
- @Context Request request,
- @Context HttpHeaders httpHeaders) {
+ @ApiParam(value = "Id of the resource", required = true) @QueryParam("resourceId") Integer resourceId,
+ @Context UriInfo uriInfo,
+ @Context Request request) {
- if (resourceId == null)
+ if (resourceId == null) {
throw new ParameterMissingException("resourceId");
+ }
- Resource res =resourceManager.getResource(caller,resourceId);
- if(res==null)
+ Resource res;
+ try {
+ res = resourceManager.getResource(caller,resourceId);
+ }
+ catch (ResourceNotFoundException rnfe) {
throw new StuffNotFoundException("resource with id " + resourceId);
+ }
ResourceType resourceType = res.getResourceType();
@@ -226,16 +215,24 @@ public class OperationsHandlerBean extends AbstractRestBean {
@ApiParam(value = "Id of the resource", required = true) @QueryParam("resourceId") Integer resourceId,
@Context UriInfo uriInfo) {
- if (resourceId == null)
+ if (resourceId == null) {
throw new ParameterMissingException("resourceId");
+ }
- Resource res =resourceManager.getResource(caller,resourceId);
- if(res==null)
+ try {
+ // Check if the resource exists at all
+ resourceManager.getResource(caller,resourceId);
+ }
+ catch (ResourceNotFoundException rnfe) {
throw new StuffNotFoundException("resource with id " + resourceId);
+ }
- OperationDefinition opDef = opsManager.getOperationDefinition(caller,definitionId);
- if (opDef==null) {
+ OperationDefinition opDef;
+ try {
+ opDef = opsManager.getOperationDefinition(caller,definitionId);
+ }
+ catch (OperationDefinitionNotFoundException odnfe) {
throw new StuffNotFoundException("Operation definition with id " + definitionId);
}
OperationRest operationRest = new OperationRest(resourceId,definitionId);
@@ -266,9 +263,11 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Path("{id}")
@ApiOperation("Return a (draft) operation")
public Response getOperation(@ApiParam("Id of the operation to retrieve") @PathParam("id") int operationId) {
+
OperationRest op = getFromCache(operationId,OperationRest.class);
- if (op==null)
+ if (op==null) {
throw new StuffNotFoundException("Operation with id " + operationId);
+ }
return Response.ok(op).build();
}
@@ -277,20 +276,40 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Path("{id}")
@Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
@ApiOperation("Update a (draft) operation. If the state is set to 'ready', the operation will be scheduled")
+ @ApiErrors({
+ @ApiError(code = 404, reason = "No draft operation with the passed id exists"),
+ @ApiError(code = 406, reason = "Draft was set for scheduling, but parameters failed validation"),
+ @ApiError(code = 200, reason = "Update was successful, operation was scheduled if requested" )
+ }
+ )
public Response updateOperation(@ApiParam("Id of the operation to update") @PathParam("id") int operationId,
OperationRest operation, @Context UriInfo uriInfo) {
- if (!operation.isReadyToSubmit() && operation.getDefinitionId()>0 && !operation.getName().isEmpty()) {
- // TODO check all the required parameters for presence before allowing to submit
- operation.setReadyToSubmit(true);
+ OperationRest op = getFromCache(operationId,OperationRest.class);
+ if (op==null) {
+ throw new StuffNotFoundException("Operation with id " + operationId);
}
+
+ Configuration parameters = ConfigurationHelper.mapToConfiguration(operation.getParams());
+
if (operation.isReadyToSubmit()) {
- // todo check params
- // submit
+ OperationDefinition opDef = opsManager.getOperationDefinition(caller,operation.getDefinitionId());
- Configuration parameters = mapToConfiguration(operation.getParams());
+ // Validate parameters
+ ConfigurationDefinition parameterDefinition = opDef.getParametersConfigurationDefinition();
+ List<String> errorMessages = ConfigurationHelper.checkConfigurationWrtDefinition(parameters, parameterDefinition);
+ if (errorMessages.size()>0) {
+ // Configuration is not ok
+ operation.setReadyToSubmit(false);
+ throw new BadArgumentException("Validation of parameters failed", StringUtils.getListAsString(errorMessages,", "));
+ }
+ }
+
+ if (operation.isReadyToSubmit()) {
+
+ // submit
ResourceOperationSchedule sched = opsManager.scheduleResourceOperation(caller,operation.getResourceId(),operation.getName(),0,0,0,-1,
parameters,"Test");
JobId jobId = new JobId(sched.getJobName(),sched.getJobGroup());
@@ -304,12 +323,12 @@ public class OperationsHandlerBean extends AbstractRestBean {
else {
UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
uriBuilder.path("/operation/{id}");
- URI uri = uriBuilder.build(operation.getId());
+ URI uri = uriBuilder.build(operationId);
Link editLink = new Link("edit",uri.toString());
operation.addLink(editLink);
}
// Update item in cache
- putToCache(operation.getId(),OperationRest.class,operation);
+ putToCache(operationId,OperationRest.class,operation);
Response.ResponseBuilder builder = Response.ok(operation);
return builder.build();
}
@@ -381,8 +400,9 @@ public class OperationsHandlerBean extends AbstractRestBean {
@Context HttpHeaders httpHeaders) {
ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria();
- if (resourceId>0)
+ if (resourceId>0) {
criteria.addFilterResourceIds(resourceId);
+ }
criteria.addSortEndTime(PageOrdering.DESC);
@@ -424,30 +444,41 @@ public class OperationsHandlerBean extends AbstractRestBean {
}
-
+ /**
+ * Create a REST-object from the passed operation history
+ * @param history History object to convert
+ * @param uriInfo URI info of the incoming request, used to create links
+ * @return a populated OperationHistoryRest object
+ */
private OperationHistoryRest historyToHistoryRest(ResourceOperationHistory history, UriInfo uriInfo) {
String status;
- if (history.getStatus()==null)
+ if (history.getStatus()==null) {
status = " - no information yet -";
- else
+ }
+ else {
status = history.getStatus().getDisplayName();
+ }
OperationHistoryRest hist = new OperationHistoryRest();
hist.setStatus(status);
- if (history.getResource()!=null)
+ if (history.getResource()!=null) {
hist.setResourceName(history.getResource().getName());
+ }
hist.setOperationName(history.getOperationDefinition().getName());
hist.lastModified(history.getModifiedTime());
- if (history.getErrorMessage()!=null)
+ if (history.getErrorMessage()!=null) {
hist.setErrorMessage(history.getErrorMessage());
+ }
if (history.getResults()!=null) {
Configuration results = history.getResults();
for (Property p : results.getProperties()) {
String val;
- if (p instanceof PropertySimple)
+ if (p instanceof PropertySimple) {
val = ((PropertySimple)p).getStringValue();
- else
+ }
+ else {
val = p.toString();
+ }
hist.getResult().put(p.getName(),val);
}
}
@@ -465,4 +496,34 @@ public class OperationsHandlerBean extends AbstractRestBean {
return hist;
}
+ /**
+ * Copies the parameters of an OperationDefinition into to an object that can be
+ * returned to a REST-client, so that this knows which fields are to be filled in,
+ * of which type they are and which ones are required
+ * @param def OperationsDefinition to "copy"
+ * @param definitionRest The definition to fill in
+ */
+ private void copyParamsForDefinition(OperationDefinition def, OperationDefinitionRest definitionRest) {
+ ConfigurationDefinition cd = def.getParametersConfigurationDefinition();
+ if (cd==null) {
+ return;
+ }
+
+ for (Map.Entry<String,PropertyDefinition> entry : cd.getPropertyDefinitions().entrySet()) {
+ PropertyDefinition pd = entry.getValue();
+ if (pd instanceof PropertyDefinitionSimple) {
+ PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd;
+ SimplePropDef prop = new SimplePropDef();
+ prop.setName(pds.getName());
+ prop.setRequired(pds.isRequired());
+ prop.setType(pds.getType());
+ prop.setDefaultValue(pds.getDefaultValue());
+ definitionRest.addParam(prop);
+ }
+ log.debug("copyParams: " + pd.getName() + " not yet supported");
+ }
+ }
+
+
+
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
index 16fd62f..d3f3f50 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ParameterMissingException.java
@@ -1,9 +1,12 @@
package org.rhq.enterprise.server.rest;
+import javax.ejb.ApplicationException;
+
/**
* Exception thrown if (Query) Parameters are missing
* @author Heiko W. Rupp
*/
+@ApplicationException(rollback = false, inherited = true)
public class ParameterMissingException extends RuntimeException {
public ParameterMissingException(String what) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
index 1377be4..1b563da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ReportsHandlerBean.java
@@ -76,25 +76,25 @@ import org.rhq.enterprise.server.rest.reporting.SuspectMetricLocal;
public class ReportsHandlerBean extends AbstractRestBean {
@EJB
- AlertDefinitionLocal alertDefinitionLocal;
+ private AlertDefinitionLocal alertDefinitionLocal;
@EJB
- ConfigurationHistoryLocal configurationHistoryLocal;
+ private ConfigurationHistoryLocal configurationHistoryLocal;
@EJB
- DriftComplianceLocal driftComplianceLocal;
+ private DriftComplianceLocal driftComplianceLocal;
@EJB
- InventorySummaryLocal inventorySummaryLocal;
+ private InventorySummaryLocal inventorySummaryLocal;
@EJB
- PlatformUtilizationLocal platformUtilizationLocal;
+ private PlatformUtilizationLocal platformUtilizationLocal;
@EJB
- RecentAlertLocal recentAlertLocal;
+ private RecentAlertLocal recentAlertLocal;
@EJB
- RecentDriftLocal recentDriftLocal;
+ private RecentDriftLocal recentDriftLocal;
@EJB
- RecentOperationsLocal recentOperationsLocal;
+ private RecentOperationsLocal recentOperationsLocal;
@EJB
- SuspectMetricLocal suspectMetricLocal;
+ private SuspectMetricLocal suspectMetricLocal;
- String[] reports = {
+ private String[] reports = {
"alertDefinitions",
"configurationHistory",
"driftCompliance",
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
index 1c2b516..4e00625 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/ResourceHandlerBean.java
@@ -108,6 +108,7 @@ import org.rhq.enterprise.server.rest.domain.MetricSchedule;
import org.rhq.enterprise.server.rest.domain.ResourceWithChildren;
import org.rhq.enterprise.server.rest.domain.ResourceWithType;
import org.rhq.enterprise.server.rest.domain.StringValue;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
/**
* Class that deals with getting data about resources
@@ -755,8 +756,8 @@ public class ResourceHandlerBean extends AbstractRestBean {
if (resType==null)
throw new StuffNotFoundException("ResourceType with name [" + typeName + "] and plugin [" + plugin + "]");
- Configuration pluginConfig = mapToConfiguration(request.getPluginConfig());
- Configuration deployConfig = mapToConfiguration(request.getResourceConfig());
+ Configuration pluginConfig = ConfigurationHelper.mapToConfiguration(request.getPluginConfig());
+ Configuration deployConfig = ConfigurationHelper.mapToConfiguration(request.getResourceConfig());
String packageName = DEFAULT_PACKAGE;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
index 3aded78..612b3f7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/RootHandlerBean.java
@@ -51,7 +51,7 @@ import org.rhq.enterprise.server.rest.domain.Link;
@Stateless
public class RootHandlerBean extends AbstractRestBean {
- String[] roots = { // rel, target
+ private String[] roots = { // rel, target
"platforms","resource/platforms",
"groups","group",
"dynaGroups","group/definitions",
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
index 3db8dc5..1da5411 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/SetCallerInterceptor.java
@@ -52,10 +52,10 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
public class SetCallerInterceptor {
@Resource
- EJBContext ejbContext;
+ private EJBContext ejbContext;
@EJB
- SubjectManagerLocal subjectManager;
+ private SubjectManagerLocal subjectManager;
private SessionManager sessionManager = SessionManager.getInstance();
@@ -76,8 +76,9 @@ public class SetCallerInterceptor {
caller = subjectManager.getSubjectByName(p.getName());
}
- if (caller==null)
+ if (caller==null) {
throw new IllegalAccessException("No calling principal provided");
+ }
// Get Subject with a session
caller = sessionManager.put(caller);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
index 23bbd4b..a6c81b3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/StatusHandlerBean.java
@@ -55,9 +55,9 @@ public class StatusHandlerBean extends AbstractRestBean {
@EJB
- SystemInfoManagerLocal infoMgr;
+ private SystemInfoManagerLocal infoMgr;
@EJB
- ServerManagerLocal serverManager;
+ private ServerManagerLocal serverManager;
@GZIP
@ApiOperation(value="Retrieve the current configured state of the server along with some runtime information." +
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
index 9851425..cd57b67 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/UserHandlerBean.java
@@ -74,8 +74,6 @@ import org.rhq.enterprise.server.rest.domain.UserRest;
@Stateless
public class UserHandlerBean extends AbstractRestBean {
- // private final Log log = LogFactory.getLog(UserHandlerBean.class);
-
/**
* List of favorite {@link org.rhq.core.domain.resource.Resource} id's, delimited by '|' characters. Default is "".
*/
@@ -88,10 +86,10 @@ public class UserHandlerBean extends AbstractRestBean {
public static final String GROUP_HEALTH_GROUPS = ".dashContent.grouphealth.groups";
@EJB
- SubjectManagerLocal subjectManager;
+ private SubjectManagerLocal subjectManager;
@EJB
- ResourceManagerLocal resourceManager;
+ private ResourceManagerLocal resourceManager;
@GZIP
@GET
@@ -112,10 +110,12 @@ public class UserHandlerBean extends AbstractRestBean {
ResourceWithType rwt = fillRWT(res, uriInfo);
ret.add(rwt);
} catch (Exception e) {
- if (e instanceof ResourceNotFoundException)
+ if (e instanceof ResourceNotFoundException) {
log.debug("Favorite resource with id " + id + " not found - not returning to the user");
- else
+ }
+ else {
log.warn("Retrieving resource with id " + id + " failed: " + e.getLocalizedMessage());
+ }
}
}
Response.ResponseBuilder builder;
@@ -151,11 +151,12 @@ public class UserHandlerBean extends AbstractRestBean {
ResourceGroup res = resourceGroupManager.getResourceGroup(caller, id);
GroupRest rwt = fillGroup(res, uriInfo);
ret.add(rwt);
- } catch (Exception e) {
- if (e instanceof ResourceGroupNotFoundException)
- log.debug("Favorite group with id " + id + " not found - not returning to the user");
- else
- log.warn("Retrieving group with id " + id + " failed: " + e.getLocalizedMessage());
+ }
+ catch (ResourceGroupNotFoundException e) {
+ log.debug("Favorite group with id " + id + " not found - not returning to the user");
+ }
+ catch (Exception e) {
+ log.warn("Retrieving group with id " + id + " failed: " + e.getLocalizedMessage());
}
}
Response.ResponseBuilder builder;
@@ -222,8 +223,8 @@ public class UserHandlerBean extends AbstractRestBean {
@Path("favorites/group/{id}")
@ApiOperation(value = "Remove a group from favorites")
public void removeResourceGroupFromFavorites(@ApiParam(name = "id", value = "Id of the group")
- @PathParam("id")
- int id) {
+ @PathParam("id") int id) {
+
Set<Integer> favIds = getGroupIdsForFavorites();
if (favIds.contains(id)) {
favIds.remove(id);
@@ -242,8 +243,9 @@ public class UserHandlerBean extends AbstractRestBean {
HttpHeaders headers) {
Subject subject = subjectManager.getSubjectByName(loginName);
- if (subject == null)
+ if (subject == null) {
throw new StuffNotFoundException("User with login " + loginName);
+ }
EntityTag eTag = new EntityTag(Long.toOctalString(subject.hashCode()));
Response.ResponseBuilder builder = request.evaluatePreconditions(eTag);
@@ -273,7 +275,8 @@ public class UserHandlerBean extends AbstractRestBean {
PropertySimple prop = conf.getSimple(RESOURCE_HEALTH_RESOURCES);
if (prop == null) {
conf.put(new PropertySimple(RESOURCE_HEALTH_RESOURCES, builder.toString()));
- } else {
+ }
+ else {
prop.setStringValue(builder.toString());
}
caller.setUserConfiguration(conf);
@@ -290,7 +293,8 @@ public class UserHandlerBean extends AbstractRestBean {
PropertySimple prop = conf.getSimple(GROUP_HEALTH_GROUPS);
if (prop == null) {
conf.put(new PropertySimple(GROUP_HEALTH_GROUPS, builder.toString()));
- } else {
+ }
+ else {
prop.setStringValue(builder.toString());
}
caller.setUserConfiguration(conf);
@@ -308,13 +312,22 @@ public class UserHandlerBean extends AbstractRestBean {
private Set<Integer> getGroupIdsForFavorites() {
Configuration conf = caller.getUserConfiguration();
- if (conf==null)
+ if (conf==null) {
return new HashSet<Integer>();
+ }
String favsString = conf.getSimpleValue(GROUP_HEALTH_GROUPS, "");
Set<Integer> favIds = getIdsFromFavString(favsString);
return favIds;
}
+ /**
+ * Parse the String with favorites.
+ * The list of favorites is stored in the server as a list
+ * of ids separated by a pipe '|' character.
+ *
+ * @param favsString String as stored in for the user
+ * @return Set of ids of the favorites
+ */
private Set<Integer> getIdsFromFavString(String favsString) {
Set<Integer> favIds = new TreeSet<Integer>();
if (!favsString.isEmpty()) {
@@ -326,13 +339,21 @@ public class UserHandlerBean extends AbstractRestBean {
return favIds;
}
+ /**
+ * Create the String with favorites to store for the user
+ * The list of favorites is stored in the server as a list
+ * of ids separated by a pipe '|' character
+ * @param favIds Set of favorite ids
+ * @return String representation
+ */
private StringBuilder buildFavStringFromSet(Set<Integer> favIds) {
StringBuilder builder = new StringBuilder();
Iterator<Integer> iter = favIds.iterator();
while (iter.hasNext()) {
builder.append(iter.next());
- if (iter.hasNext())
+ if (iter.hasNext()) {
builder.append('|');
+ }
}
return builder;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
index 2224732..f40d92c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/domain/AlertDefinitionRest.java
@@ -43,8 +43,9 @@ public class AlertDefinitionRest {
List<AlertConditionRest> conditions = new ArrayList<AlertConditionRest>();
List<AlertNotificationRest> notifications = new ArrayList<AlertNotificationRest>();
String dampeningCategory;
- String dampeningCount;
- String dampeningPeriod;
+ int dampeningCount;
+ int dampeningPeriod;
+ String dampeningUnit;
List<Link> links = new ArrayList<Link>();
@SuppressWarnings("unused")
@@ -138,24 +139,33 @@ public class AlertDefinitionRest {
this.dampeningCategory = dampeningCategory;
}
- @ApiProperty(value = "Number of occurrences of an alert (in a given period)")
- public String getDampeningCount() {
+ @ApiProperty(value = "Number of occurrences of an alert (in a given period). Valid values are > -1")
+ public int getDampeningCount() {
return dampeningCount;
}
- public void setDampeningCount(String dampeningCount) {
+ public void setDampeningCount(int dampeningCount) {
this.dampeningCount = dampeningCount;
}
@ApiProperty( value = "Period to check events. Only applicable for PARTIAL_COUNT, DURATION_COUNT, INVERSE_COUNT")
- public String getDampeningPeriod() {
+ public int getDampeningPeriod() {
return dampeningPeriod;
}
- public void setDampeningPeriod(String dampeningPeriod) {
+ public void setDampeningPeriod(int dampeningPeriod) {
this.dampeningPeriod = dampeningPeriod;
}
+ @ApiProperty( value = "Unit of the dampening period.",allowableValues = "MINUTES, HOURS, DAYS, WEEKS" )
+ public String getDampeningUnit() {
+ return dampeningUnit;
+ }
+
+ public void setDampeningUnit(String dampeningUnit) {
+ this.dampeningUnit = dampeningUnit;
+ }
+
public List<Link> getLinks() {
return links;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java
new file mode 100644
index 0000000..073966d
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/helper/ConfigurationHelper.java
@@ -0,0 +1,432 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.rest.helper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+
+/**
+ * Helper class to deal with configuration objects
+ * @author Heiko W. Rupp
+ */
+public class ConfigurationHelper {
+
+ /**
+ * Convert the passed map into a RHQ configuration object
+ * @param in Map with items to convert. Map.Entry.Key is the name of the property and Map.Entry.Value the value
+ * @return a new Configuration object
+ */
+ public static Configuration mapToConfiguration(Map<String, Object> in) {
+ Configuration config = new Configuration();
+ Set<String> mapKeys = in.keySet();
+ for (String mapKey : mapKeys) {
+ Object mapValue = in.get(mapKey);
+
+ if (mapValue instanceof Map) {
+ Map<String,Object> map = (Map<String, Object>) mapValue;
+ PropertyMap propertyMap = getPropertyMap(mapKey, map);
+ config.put(propertyMap);
+ }
+ else if (mapValue instanceof List) {
+ List<Object> objects = (List<Object>) mapValue;
+ PropertyList propertyList = getPropertyList(mapKey, objects);
+ config.put(propertyList);
+ }
+ else {
+ config.put(new PropertySimple(mapKey,mapValue));
+ }
+ }
+
+ return config;
+
+ }
+
+ public static Map<String,Object> configurationToMap(Configuration configuration, ConfigurationDefinition definition,
+ boolean strict) {
+
+ Map<String,Object> result = new HashMap<String, Object>();
+
+ if (configuration==null) {
+ return result;
+ }
+
+ if (configuration.getProperties().isEmpty()) {
+ return result;
+ }
+
+ for (Property property : configuration.getProperties()) {
+
+ String propertyName = property.getName();
+ PropertyDefinition propertyDefinition = definition.get(propertyName);
+ if (propertyDefinition==null) {
+ if (strict) {
+ throw new IllegalArgumentException("No definition for property " + propertyName + "found");
+ } else {
+ // no definition found and not strict, so skip the property
+ continue;
+ }
+ }
+
+ Object target = convertProperty(property, propertyDefinition, strict);
+ result.put(propertyName,target);
+ }
+
+ return result;
+ }
+
+ private static Object convertProperty(Property property, PropertyDefinition propertyDefinition, boolean strict) {
+ Object target;
+
+ if (property instanceof PropertyMap) {
+ PropertyMap propertyMap = (PropertyMap) property;
+ target = getInnerMap(propertyMap,(PropertyDefinitionMap) propertyDefinition, strict);
+ } else if (property instanceof PropertyList) {
+ PropertyList propertyList = (PropertyList) property;
+ target = getInnerList(propertyList, (PropertyDefinitionList)propertyDefinition, strict);
+ } else {
+ target= convertSimplePropertyValue((PropertySimple) property,
+ ((PropertyDefinitionSimple)propertyDefinition));
+ }
+ return target;
+ }
+
+ private static Map<String, Object> getInnerMap(PropertyMap propertyMap, PropertyDefinitionMap propertyDefinition,
+ boolean strict) {
+
+ Map<String, Property> map = propertyMap.getMap();
+ Map<String,Object> result = new HashMap<String, Object>(map.size());
+
+ Set<String> names = map.keySet();
+ for (String name : names ) {
+ Property property = map.get(name);
+ PropertyDefinition definition = propertyDefinition.get(name);
+
+ Object target = convertProperty(property,definition, strict);
+ result.put(name,target);
+ }
+
+ return result;
+ }
+
+ private static List<Object> getInnerList(PropertyList propertyList, PropertyDefinitionList definition,
+ boolean strict) {
+
+ List<Object> result = new ArrayList<Object>(propertyList.getList().size());
+
+ if (definition==null) {
+ if (strict) {
+ throw new IllegalArgumentException("No Definition exists for " + propertyList.getName());
+ } else {
+ return result;
+ }
+ }
+
+
+ PropertyDefinition memberDefinition = definition.getMemberDefinition();
+ for (Property property : propertyList.getList()) {
+ Object target = convertProperty(property,memberDefinition, strict);
+ result.add(target);
+ }
+
+ return result;
+ }
+
+ private static PropertyList getPropertyList(String propertyName, List<Object> objects) {
+ PropertyList propertyList = new PropertyList(propertyName);
+
+ Property target;
+ for (Object o : objects) {
+ if (o instanceof List) {
+ // Not sure if we actually support that at all inside RHQ
+ List list = (List) o;
+ target = getPropertyList(propertyName,list); // TODO propertyName?
+ } else if (o instanceof Map) {
+ Map map = (Map) o;
+ target = getPropertyMap(propertyName,map); // TODO propertyName?
+ } else {
+ target = new PropertySimple(propertyName,o);
+ }
+ propertyList.add(target);
+ }
+ return propertyList;
+ }
+
+ private static PropertyMap getPropertyMap(String propertyName, Map<String, Object> map) {
+ PropertyMap propertyMap = new PropertyMap(propertyName);
+ Set<String> keys = map.keySet();
+ for (String key : keys) {
+ Object value = map.get(key);
+ Property target;
+ if (value instanceof Map) {
+ target = getPropertyMap(key, (Map)value);
+ } else if (value instanceof List) {
+ target = getPropertyList(key, (List)value);
+ } else {
+ target = new PropertySimple(key,value);
+ }
+ propertyMap.put(target);
+ }
+ return propertyMap;
+ }
+
+ /**
+ * Convert the passed simple property into an object of a matching type. The
+ * type is determined with the help of the passed definition
+ * @param property Property to convert
+ * @param definition Definition of the Property
+ * @return Object with the correct type
+ */
+ public static Object convertSimplePropertyValue(PropertySimple property, PropertyDefinitionSimple definition) {
+
+ if (definition==null) {
+ throw new IllegalArgumentException("No definition provided");
+ }
+
+ if (property==null) {
+ return null;
+ }
+
+ PropertySimpleType type = definition.getType();
+ String val = property.getStringValue();
+
+ Object ret;
+
+ switch (type) {
+ case STRING:
+ ret= val;
+ break;
+ case INTEGER:
+ ret= Integer.valueOf(val);
+ break;
+ case BOOLEAN:
+ ret= Boolean.valueOf(val);
+ break;
+ case LONG:
+ ret= Long.valueOf(val);
+ break;
+ case FLOAT:
+ ret= Float.valueOf(val);
+ break;
+ case DOUBLE:
+ ret= Double.valueOf(val);
+ break;
+ default:
+ ret= val;
+ }
+ return ret;
+ }
+
+
+ /**
+ * Check that the passed configuration is valid wrt the passed definition
+ * @param configuration A Configuration to check
+ * @param definition A Definition to check the Configuration against
+ * @return List of validation failure messages. List is empty if no errors were found.
+ */
+ public static List<String> checkConfigurationWrtDefinition(Configuration configuration,
+ ConfigurationDefinition definition) {
+
+ List<String> messages = new ArrayList<String>();
+
+ if (configuration==null) {
+ messages.add("Configuration is null");
+
+ }
+
+ if (definition==null) {
+ messages.add("Definition is null");
+ }
+
+ if (configuration==null || definition==null) {
+ return messages;
+ }
+
+ // Basic validation is done, now have a look at the properties
+
+ for (PropertyDefinition propDef : definition.getPropertyDefinitions().values()) {
+ String name = propDef.getName();
+ Property property = configuration.get(name);
+
+ checkProperty(messages, propDef, property);
+ }
+
+
+ return messages;
+ }
+
+ /**
+ * Recursively check the passed property against the passed property definition
+ * @param messages Validation error messages are added here
+ * @param propertyDefinition The definition to check against
+ * @param property The property to check
+ */
+ private static void checkProperty(List<String> messages, PropertyDefinition propertyDefinition,
+ Property property) {
+
+ String name = propertyDefinition.getName();
+
+ // If a property is required and not present we can bail out early
+ if (propertyDefinition.isRequired() && property ==null) {
+ messages.add("Required property [" + name + "] not found");
+ return;
+ }
+
+ // If a property is not required and is null, it is fine either
+ if (!propertyDefinition.isRequired() && property==null) {
+ return;
+ }
+
+ // Check if the property and definition are of the same kind (simple, map, list)
+ boolean good = checkIfCompatible(propertyDefinition, property,messages);
+ // We only need to do this dance if the kinds are matching
+ if (good) {
+ if (property instanceof PropertySimple) {
+ checkDataTypeOfSimpleProperty((PropertyDefinitionSimple) propertyDefinition, (PropertySimple) property,
+ messages);
+ } else if (property instanceof PropertyList) {
+ PropertyList propertyList = (PropertyList) property;
+ PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition;
+ for (Property prop : propertyList.getList()) {
+ checkProperty(messages, propertyDefinitionList.getMemberDefinition(), prop);
+ }
+ } else if (property instanceof PropertyMap) {
+ PropertyMap propertyMap = (PropertyMap) property;
+ PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition;
+ for (Map.Entry<String,Property> entry : propertyMap.getMap().entrySet()) {
+ Property prop = entry.getValue();
+ PropertyDefinition definition = propertyDefinitionMap.get(name);
+ checkProperty(messages,definition,prop);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that for a Property that is defined with one of the non-string data types, the
+ * stored value is actually valid according to this data type.
+ * This also checks if a property is required, but its value is actually null.
+ *
+ * @param propDef Definition of the property, that contains the data type
+ * @param property The property to check
+ * @param messages Validation issues are added to this list.
+ */
+ private static void checkDataTypeOfSimpleProperty(PropertyDefinitionSimple propDef, PropertySimple property,
+ List<String> messages) {
+
+ String prefix = "Property [" + property.getName() + "] is ";
+ String val = property.getStringValue();
+
+ // If a property is not required and its value is null, we can just return
+ if (!propDef.isRequired() && property.getStringValue()==null) {
+ return;
+ }
+
+ // If a property is required and its value is null, we can just return
+ if (propDef.isRequired() && property.getStringValue()==null) {
+ messages.add(prefix + "required but was 'null'");
+ return;
+ }
+
+
+ switch (propDef.getType()) {
+ case DOUBLE:
+ try {
+ Double.parseDouble(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no double : " + val);
+ }
+ break;
+ case FLOAT:
+ float f;
+ try {
+ f = Float.parseFloat(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no float : " + val);
+ break;
+ }
+ if (f < Float.MIN_VALUE || f > Float.MAX_VALUE) {
+ messages.add(prefix + "no valid float : " + val);
+ }
+ break;
+ case INTEGER:
+ try {
+ Integer.parseInt(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no integer : " + val);
+ }
+ break;
+ case LONG:
+ try {
+ Long.parseLong(property.getStringValue());
+ } catch (NumberFormatException nfe ) {
+ messages.add(prefix + "no long : " + val);
+ }
+ break;
+ case BOOLEAN:
+ String s = val.toLowerCase();
+ if (!(s.equals("true") || s.equals("false"))) {
+ messages.add(prefix + "no boolean : " + val);
+ }
+ break;
+ default:
+ // Strings and long strings and directories and files
+ }
+ }
+
+ /**
+ * Check if the Kind of Definition and Property match. I.e. if a PropertyMap corresponds to a PropertyDefinitionMap
+ * @param propDef PropertyDefinition to match
+ * @param property Property to match with the definition
+ * @param messages List of messages to add validation errors to.
+ * @return true if the kinds are matching
+ */
+ private static boolean checkIfCompatible(final PropertyDefinition propDef, final Property property,
+ final List<String> messages) {
+
+ boolean good = false ;
+ if (propDef instanceof PropertyDefinitionSimple && property instanceof PropertySimple) {
+ good = true;
+ } else if (propDef instanceof PropertyDefinitionMap && property instanceof PropertyMap) {
+ good = true;
+ } else if (propDef instanceof PropertyDefinitionList && property instanceof PropertyList) {
+ good = true;
+ }
+ if (!good) {
+ String name = propDef.getName();
+ messages.add("The type of property for [" + name + "] does not match the definition");
+ }
+ return good;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
new file mode 100644
index 0000000..7e20630
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationHelperTest.java
@@ -0,0 +1,756 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.rhq.enterprise.server.configuration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.Property;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.configuration.definition.PropertySimpleType;
+import org.rhq.core.domain.util.StringUtils;
+import org.rhq.enterprise.server.rest.helper.ConfigurationHelper;
+
+/**
+ * Test the ConfigurationHelper class
+ * @author Heiko W. Rupp
+ */
+public class ConfigurationHelperTest {
+
+ @Test
+ public void testConvertSimpleMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2;
+
+ PropertySimple hello = config.getSimple("Hello");
+ assert hello !=null;
+ assert hello.getStringValue().equals("World");
+
+ PropertySimple qu = config.getSimple("Answer");
+ assert qu!=null;
+ Integer value = qu.getIntegerValue();
+ assert value !=null;
+ assert value ==42;
+ }
+
+ @Test
+ public void testConvertWithNestedMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(3);
+ map.put("Hello","World");
+ map.put("Answer",42);
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ map.put("Inner",inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop!=null;
+ assert prop instanceof PropertyMap : "Inner is no map";
+
+ PropertyMap pm = (PropertyMap) prop;
+ Map<String, Property> innerMap = pm.getMap();
+ assert innerMap.size()==1;
+
+ assert inner.containsKey("Foo");
+
+ }
+
+ @Test
+ public void testConvertListOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.add(inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop==null;
+
+ prop = config.get("list");
+ assert prop instanceof PropertyList : "list is no list";
+
+ PropertyList pl = (PropertyList) prop;
+ List<Property> propertyList = pl.getList();
+ assert propertyList.size()==1;
+ PropertyMap innerMapProperty = (PropertyMap) propertyList.get(0);
+
+ Map<String, Property> propertyMap = innerMapProperty.getMap();
+ assert propertyMap.size()==1;
+ Map<String,Property> innerMap = propertyMap;
+
+ assert innerMap.containsKey("Foo");
+ Property property = innerMapProperty.get("Foo");
+ assert property != null;
+ assert property instanceof PropertySimple;
+ PropertySimple ps = (PropertySimple) property;
+ assert ps.getStringValue().equals("Bar");
+
+ }
+
+ @Test
+ public void testConvertWithListOfSimple() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+ List<String> inner = new ArrayList<String>(2);
+ inner.add("Foo");
+ inner.add("Bar");
+ map.put("Inner", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props, got " + properties.size();
+
+ Property prop = config.get("Inner");
+ assert prop!=null;
+ assert prop instanceof PropertyList : "Inner is no list";
+
+ PropertyList plist = (PropertyList) prop;
+ List<Property> propertyList = plist.getList();
+ assert propertyList.size()==2;
+ for (Property innerProp : propertyList) {
+ assert innerProp instanceof PropertySimple;
+ PropertySimple ps = (PropertySimple) innerProp;
+ assert ps.getName().equals("Inner");
+ assert ps.getStringValue().equals("Foo") || ps.getStringValue().equals("Bar");
+ }
+
+ }
+
+ @Test
+ public void testConvertAndValidateBoolean() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>();
+ map.put("bool1","true");
+ map.put("bool2","TruE");
+ map.put("bool3","fAlSe");
+ map.put("bool4", "false");
+ map.put("bool5", 42);
+ map.put("bool6", "Hugo");
+ map.put("bool7",null);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==7 : "Expected 7 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool2","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool3","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool4","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool5","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool6","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool7","A boolean",true, PropertySimpleType.BOOLEAN));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==3 : "Expected 3 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMissingRequired() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ // required 2nd entry is missing
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==1 : "Expected 1 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("bool2","A boolean",true, PropertySimpleType.BOOLEAN));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateNotRequiredButNull() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMismatchingKind() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ map.put("Inner",inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+ // We define Inner as a simple property, but the user supplied a map
+ definition.put(new PropertyDefinitionSimple("Inner","null string",false, PropertySimpleType.STRING));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMismatchingKind2() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(1);
+ map.put("bool1","true");
+ map.put("optional",null);
+ map.put("Inner","Frobnitz");
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==3 : "Expected 3 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("bool1","A boolean",true, PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("optional","null string",false, PropertySimpleType.STRING));
+ // We define Inner as a list property, but the user supplied a simple one
+ definition.put(new PropertyDefinitionList("Inner","Bla",true,
+ new PropertyDefinitionSimple("Inner","fasel",true,PropertySimpleType.STRING)));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==1 : "Expected 1 error, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n ");
+
+ }
+
+ @Test
+ public void testConvertAndValidateNumeric() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("float1",1.1f);
+ map.put("float2",Double.MAX_VALUE);
+ map.put("float3",null);
+ map.put("float4","abc");
+
+ map.put("double1",1.1d);
+ map.put("double2",null);
+ map.put("double3","hugo");
+
+ map.put("int1",42);
+ map.put("int2",Long.MAX_VALUE);
+ map.put("int3",null);
+ map.put("int4","abc");
+
+ map.put("long1",-5);
+ map.put("long2",null);
+ map.put("long3","Frobnitz");
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==14 : "Expected 14 props but got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla","For testing");
+ definition.put(new PropertyDefinitionSimple("float1","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float2","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float3","A float",true, PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("float4","A float",true, PropertySimpleType.FLOAT));
+
+ definition.put(new PropertyDefinitionSimple("double1","A double",true, PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("double2","A double",true, PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("double3","A double",true, PropertySimpleType.DOUBLE));
+
+ definition.put(new PropertyDefinitionSimple("int1","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int2","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int3","An int",true, PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("int4","An int",true, PropertySimpleType.INTEGER));
+
+ definition.put(new PropertyDefinitionSimple("long1","A long",true, PropertySimpleType.LONG));
+ definition.put(new PropertyDefinitionSimple("long2","A long",true, PropertySimpleType.LONG));
+ definition.put(new PropertyDefinitionSimple("long3","A long",true, PropertySimpleType.LONG));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==10 : "Expected 10 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testValidateNullConfiguration() throws Exception {
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(null,new ConfigurationDefinition("bla",null));
+ assert errors != null;
+ assert errors.size()==1;
+
+ }
+
+ @Test
+ public void testValidateNullDefinition() throws Exception {
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(new Configuration(),null);
+ assert errors != null;
+ assert errors.size()==1;
+
+ }
+
+ @Test
+ public void testConvertAndValidateSimpleMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ map.put("Answer",42);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("Answer",null,true,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("Optional",null,false,PropertySimpleType.INTEGER));
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2;
+
+ PropertySimple hello = config.getSimple("Hello");
+ assert hello !=null;
+ assert hello.getStringValue().equals("World");
+
+ PropertySimple qu = config.getSimple("Answer");
+ assert qu!=null;
+ Integer integerValue = qu.getIntegerValue();
+ assert integerValue !=null;
+ assert integerValue ==42;
+ }
+
+ @Test
+ public void testConvertValidateNonRequiredNotPresent() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==0 : "Expected 0 props, got " + properties.size();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Answer",null,false,PropertySimpleType.INTEGER));
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateListOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.add(inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("Answer",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionList("list",null,true,
+ new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+ definition.put(new PropertyDefinitionSimple("aString",null,false,PropertySimpleType.INTEGER));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMapOfMap() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+ Map<String,Map<String,Object>> list = new HashMap<String, Map<String, Object>>();
+ map.put("list",list);
+
+ Map<String,Object> inner = new HashMap<String, Object>(1);
+ inner.put("Foo","Bar");
+ list.put("outer", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConvertAndValidateMapWithListOfSimple() throws Exception {
+
+ Map<String,Object> map = new HashMap<String, Object>(2);
+ map.put("Hello","World");
+
+ Map<String,List<String>> list = new HashMap<String, List<String>>();
+ map.put("list",list);
+
+ List<String> inner = new ArrayList<String>();
+ inner.add("Foo");
+ inner.add("Bar");
+ list.put("outer", inner);
+
+ Configuration config = ConfigurationHelper.mapToConfiguration(map);
+
+ assert config!=null;
+ Collection<Property> properties = config.getProperties();
+ assert properties.size()==2 : "Expected 2 props, got " + properties.size();
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("Hello",null,true,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionMap("list",null,true,
+ new PropertyDefinitionList("list",null,true,
+ new PropertyDefinitionSimple("list",null,true,PropertySimpleType.STRING))));
+
+
+ List<String> errors = ConfigurationHelper.checkConfigurationWrtDefinition(config,definition);
+
+ assert errors!=null;
+ assert errors.size()==0 : "Expected 0 errors, but got " + errors.size() + "\n" + StringUtils.getListAsString(errors,",\n");
+
+ }
+
+ @Test
+ public void testConfigToMapSimple() throws Exception {
+
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("number",42));
+ config.put(new PropertySimple("string","Hello"));
+ config.put(new PropertySimple("bool",true));
+ config.put(new PropertySimple("float",1.1f));
+ config.put(new PropertySimple("double",2.3d));
+ config.put(new PropertySimple("long",Long.MAX_VALUE));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+ definition.put(new PropertyDefinitionSimple("bool",null,false,PropertySimpleType.BOOLEAN));
+ definition.put(new PropertyDefinitionSimple("float",null,false,PropertySimpleType.FLOAT));
+ definition.put(new PropertyDefinitionSimple("double",null,false,PropertySimpleType.DOUBLE));
+ definition.put(new PropertyDefinitionSimple("long",null,false,PropertySimpleType.LONG));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==6;
+
+ assert map.containsKey("number");
+ assert map.containsKey("string");
+
+ assert map.get("number") != null;
+ assert (Integer)map.get("number") == 42;
+
+ assert map.get("string") != null;
+ assert map.get("string").equals("Hello");
+
+ assert (Boolean)map.get("bool") == true;
+
+ assert map.get("float") != null;
+ assert (Float)map.get("float") ==1.1f;
+
+ assert map.get("double") != null;
+ assert (Double) map.get("double") ==2.3d;
+
+ assert map.get("long") != null;
+ assert (Long)map.get("long") == Long.MAX_VALUE;
+
+ }
+
+ @Test
+ public void testEmptyConfigToMap() throws Exception {
+
+ Configuration config = new Configuration();
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==0;
+
+
+ }
+
+ @Test
+ public void testNullConfigToMap() throws Exception {
+
+ Configuration config = null;
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionSimple("number",null,false,PropertySimpleType.INTEGER));
+ definition.put(new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==0;
+
+ }
+
+ @Test
+ public void testConfigToMapComplexList() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ config.put(propertyList);
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionList("aList",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aList");
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMap() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aList",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aString",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, true);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aMap");
+ assert map.get("aMap") instanceof Map;
+ Map<String,Object> innerMap = (Map<String, Object>) map.get("aMap");
+
+ assert innerMap.containsKey("aString");
+ assert innerMap.containsKey("aList");
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMapWithBadSetupStrict() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aBla",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aFoo",null,false,PropertySimpleType.STRING)));
+
+ try {
+ ConfigurationHelper.configurationToMap(config,definition, true);
+ assert false;
+ } catch (IllegalArgumentException iae ) {
+ System.out.println("Yep, caught the error");
+ }
+
+
+ }
+
+ @Test
+ public void testConfigToMapComplexMapWithBadSetupLenient() throws Exception {
+
+ Configuration config = new Configuration();
+ PropertyMap propertyMap = new PropertyMap("aMap");
+ config.put(propertyMap);
+ PropertyList propertyList = new PropertyList("aList");
+ propertyList.add(new PropertySimple("string", "Hello"));
+ propertyList.add(new PropertySimple("string", "World"));
+ propertyMap.put(propertyList);
+
+ propertyMap.put(new PropertySimple("aString","Frobnitz"));
+
+
+ ConfigurationDefinition definition = new ConfigurationDefinition("bla",null);
+ definition.put(new PropertyDefinitionMap("aMap",null,false,
+ new PropertyDefinitionList("aBla",null,false,
+ new PropertyDefinitionSimple("string",null,false,PropertySimpleType.STRING)),
+ new PropertyDefinitionSimple("aFoo",null,false,PropertySimpleType.STRING)));
+
+ Map<String,Object> map = ConfigurationHelper.configurationToMap(config,definition, false);
+
+ assert map != null;
+ assert map.entrySet().size()==1;
+
+ assert map.containsKey("aMap");
+
+ }
+
+ @Test
+ public void testConvertSingleValueNoProperty() throws Exception {
+
+ Object o = ConfigurationHelper.convertSimplePropertyValue(null,new PropertyDefinitionSimple("dummy",null,false,PropertySimpleType.STRING));
+
+ assert o == null;
+
+ }
+
+ @Test
+ public void testConvertSingleValueNoDefinition() throws Exception {
+
+ try {
+ ConfigurationHelper.convertSimplePropertyValue(new PropertySimple("foo","bar"),null);
+ assert false;
+ }
+ catch (IllegalArgumentException iae) {
+ System.out.println("Yep, good");
+ }
+
+ }
+}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
index 3d9f735..fca0f50 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/AlertTest.java
@@ -266,8 +266,8 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("NONE"))
- .body("dampeningCount",is("0"))
- .body("dampeningPeriod",is("0"))
+ .body("dampeningCount",is(0))
+ .body("dampeningPeriod",is(0))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
@@ -369,8 +369,8 @@ public class AlertTest extends AbstractBase {
alertDefinition.setEnabled(false);
alertDefinition.setPriority("LOW");
alertDefinition.setDampeningCategory("PARTIAL_COUNT");
- alertDefinition.setDampeningCount("3");
- alertDefinition.setDampeningPeriod("5");
+ alertDefinition.setDampeningCount(3);
+ alertDefinition.setDampeningPeriod(5);
AlertDefinition result =
given()
@@ -381,8 +381,8 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("PARTIAL_COUNT"))
- .body("dampeningCount",is("3"))
- .body("dampeningPeriod",is("5"))
+ .body("dampeningCount",is(3))
+ .body("dampeningPeriod",is(5))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
@@ -404,8 +404,9 @@ public class AlertTest extends AbstractBase {
alertDefinition.setEnabled(false);
alertDefinition.setPriority("LOW");
alertDefinition.setDampeningCategory("DURATION_COUNT");
- alertDefinition.setDampeningCount("1");
- alertDefinition.setDampeningPeriod("3 minutes");
+ alertDefinition.setDampeningCount(1);
+ alertDefinition.setDampeningPeriod(3);
+ alertDefinition.setDampeningUnit("minutes");
AlertDefinition result =
given()
@@ -416,8 +417,9 @@ public class AlertTest extends AbstractBase {
.expect()
.statusCode(201)
.body("dampeningCategory",is("DURATION_COUNT"))
- .body("dampeningCount", is("1"))
- .body("dampeningPeriod", is("3 MINUTES"))
+ .body("dampeningCount", is(1))
+ .body("dampeningPeriod", is(3))
+ .body("dampeningUnit", is("MINUTES"))
.when()
.post("/alert/definitions")
.as(AlertDefinition.class);
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
index 713a755..e6aea1f 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/OperationsTest.java
@@ -61,8 +61,9 @@ public class OperationsTest extends AbstractBase {
definitionId = -1;
List<Map<String,Object>> list = r.as(List.class);
for (Map<String,Object> map : list) {
- if (map.get("name").equals("discovery"))
+ if (map.get("name").equals("discovery")) {
definitionId = (Integer) map.get("id");
+ }
}
assert definitionId !=-1 : "No discovery operation found";
@@ -85,6 +86,92 @@ public class OperationsTest extends AbstractBase {
}
@Test
+ public void testGetDefinitionByUnknownId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("did",-42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/operation/definition/{did}");
+
+ }
+
+ @Test
+ public void testGetDefinitionsForUnknownResource() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .queryParam("resourceId",42)
+ .expect()
+ .statusCode(404)
+ .when()
+ .get("/operation/definitions");
+ }
+
+ @Test
+ public void testGetDefinitionsForMissingResourceId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .expect()
+ .statusCode(406)
+ .when()
+ .get("/operation/definitions");
+ }
+
+ @Test
+ public void testCreateScheduleByUnknownDefinitionId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("did",-42)
+ .expect()
+ .statusCode(406)
+ .when()
+ .post("/operation/definition/{did}");
+
+ }
+
+ @Test
+ public void testCreateScheduleForUnknownResource() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .queryParam("resourceId", 42)
+ .pathParam("definitionId", definitionId)
+ .expect()
+ .statusCode(404)
+ .when()
+ .post("/operation/definition/{definitionId}");
+ }
+
+ @Test
+ public void testCreateScheduleForMissingResourceId() throws Exception {
+
+ // Now retrieve that definition by id
+
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId", definitionId)
+ .expect()
+ .statusCode(406)
+ .when()
+ .post("/operation/definition/{definitionId}");
+ }
+
+ @Test
public void testCreateDraftOperation() throws Exception {
Operation draft =
@@ -196,8 +283,9 @@ public class OperationsTest extends AbstractBase {
String history = null;
List<Link> links = scheduled.getLinks();
for (Link link : links) {
- if (link.getRel().equals("history"))
- history = (String) link.getHref();
+ if (link.getRel().equals("history")) {
+ history = link.getHref();
+ }
}
assert history != null;
@@ -272,4 +360,98 @@ public class OperationsTest extends AbstractBase {
}
}
+ @Test
+ public void testOpsScheduleMissingRequiredParam() throws Exception {
+
+ int platformId = findIdOfARealPlatform();
+
+ Operation draft =
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId",definitionId)
+ .queryParam("resourceId",platformId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/operation/definition/{definitionId}")
+ .as(Operation.class);
+
+ assert draft != null;
+ assert draft.getDefinitionId() == definitionId;
+
+ int draftId = draft.getId();
+
+ // explicitly remove the param from the draft for
+ // the test
+ Map<String, Object> params = draft.getParams();
+ if (params.containsKey("detailedDiscovery")) {
+ params.remove("detailedDiscovery");
+ }
+
+ // Update to put the new version in the server
+ // We don't want to submit, so the server does not
+ // validate and we should get a 200 back
+ draft.setReadyToSubmit(false);
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+
+
+ // update to schedule, lacking the required param
+ draft.setReadyToSubmit(true);
+
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(406)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+ }
+
+ @Test
+ public void testOpsScheduleRequiredParamWrongDataType() throws Exception {
+
+ int platformId = findIdOfARealPlatform();
+
+ Operation draft =
+ given()
+ .header(acceptJson)
+ .pathParam("definitionId",definitionId)
+ .queryParam("resourceId",platformId)
+ .expect()
+ .statusCode(200)
+ .log().ifError()
+ .when()
+ .post("/operation/definition/{definitionId}")
+ .as(Operation.class);
+
+ assert draft != null;
+ assert draft.getDefinitionId() == definitionId;
+
+ int draftId = draft.getId();
+
+ draft.getParams().put("detailedDiscovery", 42);
+ draft.setReadyToSubmit(true);
+
+ // update to schedule
+ given()
+ .contentType(ContentType.JSON)
+ .pathParam("id",draftId)
+ .body(draft)
+ .expect()
+ .statusCode(406)
+ .log().ifError()
+ .when()
+ .put("/operation/{id}");
+ }
}
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
index 5922770..d6da534 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/RootURITest.java
@@ -50,7 +50,7 @@ public class RootURITest extends AbstractBase {
.expect().statusCode(200)
.when().get("/");
- given().header("Accept","application/json")
+ given().header("Accept","application/xml")
.expect().statusCode(200)
.when().get("/index");
diff --git a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
index 5049a98..b870443 100644
--- a/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
+++ b/modules/integration-tests/rest-api/src/test/java/org/rhq/modules/integrationTests/restApi/d/AlertDefinition.java
@@ -41,8 +41,9 @@ public class AlertDefinition {
List<AlertCondition> conditions = new ArrayList<AlertCondition>();
List<AlertNotification> notifications = new ArrayList<AlertNotification>();
String dampeningCategory = "NONE";
- String dampeningCount;
- String dampeningPeriod;
+ int dampeningCount;
+ int dampeningPeriod;
+ String dampeningUnit;
List<Link> links;
@@ -121,22 +122,30 @@ public class AlertDefinition {
this.dampeningCategory = dampeningCategory;
}
- public String getDampeningCount() {
+ public int getDampeningCount() {
return dampeningCount;
}
- public void setDampeningCount(String dampeningCount) {
+ public void setDampeningCount(int dampeningCount) {
this.dampeningCount = dampeningCount;
}
- public String getDampeningPeriod() {
+ public int getDampeningPeriod() {
return dampeningPeriod;
}
- public void setDampeningPeriod(String dampeningPeriod) {
+ public void setDampeningPeriod(int dampeningPeriod) {
this.dampeningPeriod = dampeningPeriod;
}
+ public String getDampeningUnit() {
+ return dampeningUnit;
+ }
+
+ public void setDampeningUnit(String dampeningUnit) {
+ this.dampeningUnit = dampeningUnit;
+ }
+
public List<Link> getLinks() {
return links;
}
commit d72ac1e6bba8cbeb054a7cbfc8d7df026a09a5fc
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Wed May 8 09:17:22 2013 +0200
Add another email for Thomas
diff --git a/.mailmap b/.mailmap
index 384ec04..ac0fdc9 100644
--- a/.mailmap
+++ b/.mailmap
@@ -75,5 +75,6 @@ Test JON User <test_jon(a)jon01.qa.atl2.redhat.com>
Todd B Sanders <tsanders(a)dhcp231-67.rdu.redhat.com>
Torben Jäger <torben(a)jit-central.com>
Thomas Segismont <tsegismo(a)redhat.com> Thomas SEGISMONT <tsegismo(a)redhat.com>
+Thomas Segismont <tsegismo(a)redhat.com> Thomas Segismont <tsegismont(a)gmail.com>
Thomas Segismont <tsegismo(a)redhat.com>
hudson auto <wnstb(a)yahoo.com>
commit bbe5654f0755eac835b78351a8ef71a7e3398037
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 7 16:58:43 2013 -0700
[BZ 960646] - RFE Redesigned Availability Chart - Add disabled state cross hatch SVG pattern. Pixel tweeks.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
index 76c8f69..4e6a0ce 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -18,6 +18,9 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+import java.util.Date;
+import java.util.List;
+
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.measurement.MeasurementUnits;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
@@ -27,9 +30,6 @@ import org.rhq.enterprise.gui.coregui.client.Messages;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import java.util.Date;
-import java.util.List;
-
/**
* Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
* just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
@@ -66,7 +66,7 @@ public class AvailabilityOverUnderGraphType {
// loop through the avail intervals
for (Availability availability : availabilityList) {
sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
- sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType() + "\", ");
sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
// last record will be null
long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
@@ -84,8 +84,9 @@ public class AvailabilityOverUnderGraphType {
// loop through the group avail down intervals
for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
// allows substitution for situations like WARN=MIXED for easier terminology
- String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
- ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType()
+ .equals(ResourceGroupComposite.GroupAvailabilityType.WARN)) ? MSG
+ .chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
@@ -139,7 +140,6 @@ public class AvailabilityOverUnderGraphType {
barOffset = 10,
width = 750 - margin.left - margin.right + barOffset,
height = 40 - margin.top - margin.bottom,
- pixelsOffHeight = 0,
svg;
@@ -161,65 +161,65 @@ public class AvailabilityOverUnderGraphType {
.domain([0, 4]),
xAxis = $wnd.d3.svg.axis()
- .scale(timeScale)
- .ticks(12)
- .tickSize(10, 0, 0)
- .orient("bottom"),
-
- calcBarY = function(d) {
- var ABOVE = -10,
- BELOW = 0,
- STRADDLE = -5,
- offset;
-
- if (d.availType === 'DOWN') {
- offset = BELOW;
- }
- else if (d.availType === 'DISABLED') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UNKNOWN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'UP') {
- offset = ABOVE;
- }
- else if (d.availType === 'WARN') {
- offset = STRADDLE;
- }
- else if (d.availType === 'EMPTY') {
- offset = STRADDLE;
- }
- return yScale(0) + offset;
-
- },
-
- calcBarFill = function(d) {
- if (d.availType === 'DOWN') {
- return "#FF1919"; // red
- }
- else if (d.availType === 'DISABLED') {
- return "#FF9933"; // orange
- }
- else if (d.availType === 'UNKNOWN') {
- return "#CCC"; // gray
- }
- else if (d.availType === 'UP') {
- return "#198C19"; // green
- }
- else if (d.availType === 'WARN') {
- return "#FFA500"; // yellow
- }
- else if (d.availType === 'EMPTY') {
- return "#CCC"; // gray
- }
- else {
- // should not ever happen, but...
- console.warn("AvailabilityType not valid.");
- return "#000"; //black
- }
- },
- svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .scale(timeScale)
+ .ticks(12)
+ .tickSize(13, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function (d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function (d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "url(#diagonalHatchFill)"; // grey diagonal hatches
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // orange
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.warn("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
@@ -234,11 +234,9 @@ public class AvailabilityOverUnderGraphType {
})
.attr("y", function (d) {
return calcBarY(d);
-
})
.attr("height", function (d) {
return 10;
-
})
.attr("width", function (d) {
return timeScale(+d.availEnd) - timeScale(+d.availStart);
@@ -250,43 +248,43 @@ public class AvailabilityOverUnderGraphType {
// create x-axis
svg.append("g")
- .attr("class", "x axis")
- .attr("stroke", "#50505a")
- .attr("stroke-width", "0.5")
- .attr("transform", "translate(0," + height + ")")
- .attr("letter-spacing", "3")
- .style("text-anchor", "end")
- .call(xAxis);
+ .attr("class", "x axis")
+ .attr("fill", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
svg.append("text")
- .attr("class", "availabilityLabel")
- .attr("x", -40)
- .attr("y", 10)
- .style("font-size", "12px")
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-weight", "bold")
- .attr("fill", "#003168")
- .text("Availability");
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text("Availability");
svg.append("text")
- .attr("class", "upLabel")
- .attr("x", -5)
- .attr("y", 28)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text("UP");
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("UP");
svg.append("text")
- .attr("class", "downLabel")
- .attr("x", -5)
- .attr("y", 39)
- .style("font-family", "Arial, Verdana, sans-serif;")
- .style("font-size", "9px")
- .attr("fill", "#50505a")
- .style("text-anchor", "end")
- .text("DOWN");
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("DOWN");
}
@@ -306,19 +304,15 @@ public class AvailabilityOverUnderGraphType {
}
function formatHovers(d) {
- var hoverString,
- timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
- availStart = new Date(+d.availStart),
- availEnd = new Date(+d.availEnd);
+ availStart = new Date(+d.availStart);
- hoverString =
- '<div class="chartHoverEnclosingDiv">' +
+ return '<div class="chartHoverEnclosingDiv">' +
'<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
- '<div class="chartHoverAlignLeft"><span>'+ dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
'<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
'</div>';
- return hoverString;
}
@@ -341,7 +335,7 @@ public class AvailabilityOverUnderGraphType {
availabilityGraph.draw(availChartContext);
}
- }-*/;
+ }-*/;
public String getChartId() {
return String.valueOf(entityId);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
index 7df45d1..b876c74 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/summary/AbstractActivityView.java
@@ -634,7 +634,7 @@ public abstract class AbstractActivityView extends EnhancedVLayout implements Re
setIsModal(true);
setShowModalMask(true);
setWidth(950);
- setHeight(350);
+ setHeight(370);
setShowResizer(true);
setCanDragResize(true);
centerInPage();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
index b590e86..f8887bf 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3GraphView.java
@@ -67,6 +67,31 @@ public class MetricD3GraphView extends EnhancedVLayout {
+ " width=\"6\" height=\"3\">"
+ " <path d=\"M 0 0 6 0\" style=\"stroke:#2E9EC2; fill:none;\"/>"
+ " </pattern>"
+ + "<pattern id=\"diagonalHatchFill\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">"
+ + "<circle cx=\"0\" cy=\"0\" r=\"1000\" fill=\"grey\"/>"
+ + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>"
+ + "<path d=\"M0 60 l45,45\"/>"
+ + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>"
+ + "<path d=\"M0 15 l90,90\"/>"
+ + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>"
+ + "<path d=\"M30 0 l75,75\"/>"
+ + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>"
+ + "<path d=\"M75 0 l30,30\"/>"
+ + "<path d=\"M90 0 l15,15\"/>"
+ + "</g>"
+ + "</pattern>"
+ + "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\" width=\"105\" height=\"105\">"
+ + "<g style=\"fill:none; stroke:black; stroke-width:1\">" + "<path d=\"M0 90 l15,15\"/>"
+ + "<path d=\"M0 75 l30,30\"/>" + "<path d=\"M0 60 l45,45\"/>" + "<path d=\"M0 45 l60,60\"/>"
+ + "<path d=\"M0 30 l75,75\"/>" + "<path d=\"M0 15 l90,90\"/>" + "<path d=\"M0 0 l105,105\"/>"
+ + "<path d=\"M15 0 l90,90\"/>" + "<path d=\"M30 0 l75,75\"/>" + "<path d=\"M45 0 l60,60\"/>"
+ + "<path d=\"M60 0 l45,45\"/>" + "<path d=\"M75 0 l30,30\"/>" + "<path d=\"M90 0 l15,15\"/>" + "</g>"
+ + "</pattern>"
+ " <pattern id=\"downStripes\" patternUnits=\"userSpaceOnUse\" x=\"0\" y=\"0\""
+ " width=\"6\" height=\"3\">"
+ " <path d=\"M 0 0 6 0\" style=\"stroke:#ff8a9a; fill:none;\"/>"
@@ -101,9 +126,9 @@ public class MetricD3GraphView extends EnhancedVLayout {
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs
.append("<div id=\""
- + getFullChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
- + getChartHeight() + "px;\">");
+ + getFullChartId()
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"height:"
+ + getChartHeight() + "px;\">");
divAndSvgDefs.append(getSvgDefs());
divAndSvgDefs.append("</svg></div>");
@@ -133,14 +158,11 @@ public class MetricD3GraphView extends EnhancedVLayout {
graph.drawJsniChart();
}
-
public String getFullChartId() {
return "rChart-" + graph.getMetricGraphData().getChartId();
}
-
-
public Integer getChartHeight() {
return graph.getMetricGraphData().getChartHeight();
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
index d06bab2..ca8b117 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
@@ -25,7 +25,6 @@ import com.smartgwt.client.widgets.HTMLFlow;
import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraph;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -43,7 +42,7 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
public AvailabilityD3Graph(AvailabilityOverUnderGraphType graphType) {
super();
this.availabilityGraphType = graphType;
- setHeight(70);
+ setHeight(65);
setWidth100();
}
@@ -83,15 +82,26 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:110px;\">");
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:65px;\">");
+ divAndSvgDefs.append(getSvgDefs());
divAndSvgDefs.append("</svg></div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
- graph.setHeight(25);
+ graph.setHeight(65);
addMember(graph);
}
+ /**
+ * Svg definitions for patterns and gradients to use on SVG shapes.
+ * @return xml String
+ */
+ private static String getSvgDefs() {
+ return " <defs>"+
+ "<pattern id=\"diagonalHatch\" patternUnits=\"userSpaceOnUse\" width=\"4\" height=\"4\"> <path d=\"M-1,1 l2,-2 M0,4 l4,-4 M3,5 l2,-2\" /> </pattern>"
+ + "</defs>";
+ }
+
@Override
public void destroy() {
super.destroy();
commit ee5255b684d733fa01989930676f5d0e7e17d51e
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Mon May 6 14:23:28 2013 -0700
[BZ 960646] - RFE Redesigned Availability Charts.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
new file mode 100644
index 0000000..76c8f69
--- /dev/null
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/AvailabilityOverUnderGraphType.java
@@ -0,0 +1,381 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2012 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
+
+import org.rhq.core.domain.measurement.Availability;
+import org.rhq.core.domain.measurement.MeasurementUnits;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
+import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
+import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.Messages;
+import org.rhq.enterprise.gui.coregui.client.util.Log;
+import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Contains the javascript chart definition for an implementation of the d3 availability chart. This implementation is
+ * just a line that changes color based on availability type: up=green, down=red, orange=disabled, unknown=grey,
+ * empty=grey, warn=yellow. This version of the availability graph shows continuous intervals.
+ *
+ * @author Mike Thompson
+ */
+public class AvailabilityOverUnderGraphType {
+
+ private static Messages MSG = CoreGUI.getMessages();
+ private List<Availability> availabilityList;
+ private List<ResourceGroupAvailability> groupAvailabilityList;
+ private Integer entityId;
+
+ /**
+ * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
+ * for all cases but the dashboard portlet).
+ */
+ public AvailabilityOverUnderGraphType(Integer entityId) {
+ this.entityId = entityId;
+ }
+
+ public void setAvailabilityList(List<Availability> availabilityList) {
+ this.availabilityList = availabilityList;
+ }
+
+ public void setGroupAvailabilityList(List<ResourceGroupAvailability> groupAvailabilityList) {
+ this.groupAvailabilityList = groupAvailabilityList;
+ }
+
+ public String getAvailabilityJson() {
+ StringBuilder sb = new StringBuilder("[");
+ if (null != availabilityList) {
+ // loop through the avail intervals
+ for (Availability availability : availabilityList) {
+ sb.append("{ \"availType\":\"" + availability.getAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availability.getAvailabilityType()+ "\", ");
+ sb.append(" \"availStart\":" + availability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = availability.getEndTime() != null ? availability.getEndTime() : (new Date()).getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - availability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+
+ } else if (null != groupAvailabilityList) {
+ // loop through the group avail down intervals
+ for (ResourceGroupAvailability groupAvailability : groupAvailabilityList) {
+ // allows substitution for situations like WARN=MIXED for easier terminology
+ String availabilityTypeMessage = (groupAvailability.getGroupAvailabilityType().equals(ResourceGroupComposite.GroupAvailabilityType.WARN))
+ ? MSG.chart_hover_availability_type_warn() : groupAvailability.getGroupAvailabilityType().name();
+
+ sb.append("{ \"availType\":\"" + groupAvailability.getGroupAvailabilityType() + "\", ");
+ sb.append(" \"availTypeMessage\":\"" + availabilityTypeMessage + "\", ");
+ sb.append(" \"availStart\":" + groupAvailability.getStartTime() + ", ");
+ // last record will be null
+ long endTime = groupAvailability.getEndTime() != null ? groupAvailability.getEndTime() : (new Date())
+ .getTime();
+ sb.append(" \"availEnd\":" + endTime + ", ");
+
+ long availDuration = endTime - groupAvailability.getStartTime();
+ String availDurationString = MeasurementConverterClient.format((double) availDuration,
+ MeasurementUnits.MILLISECONDS, true);
+ sb.append(" \"availDuration\": \"" + availDurationString + "\" },");
+
+ }
+ sb.setLength(sb.length() - 1);
+ }
+
+ sb.append("]");
+ Log.debug(sb.toString());
+ return sb.toString();
+ }
+
+ /**
+ * The magic JSNI to draw the charts with d3.
+ */
+ public native void drawJsniChart() /*-{
+ console.log("Draw Enhanced Availability chart");
+
+ var global = this,
+ // tidy up all of our interactions with java (via JSNI) thru AvailChartContext class
+ // NOTE: rhq.js has the javascript object constructors in it.
+ availChartContext = new $wnd.AvailChartContext(global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartId()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getAvailabilityJson()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartDateLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartTimeLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverStartLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverEndLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverBarLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverAvailabilityLabel()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverTimeFormat()(),
+ global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType::getChartHoverDateFormat()()
+ );
+
+
+ var availabilityGraph = function () {
+ "use strict";
+ // privates
+
+ var margin = {top: 5, right: 5, bottom: 5, left: 40},
+ barOffset = 10,
+ width = 750 - margin.left - margin.right + barOffset,
+ height = 40 - margin.top - margin.bottom,
+ pixelsOffHeight = 0,
+ svg;
+
+
+ function drawBars(availChartContext) {
+ var xAxisMin = $wnd.d3.min(availChartContext.data, function (d) {
+ return +d.availStart;
+ }),
+ xAxisMax = $wnd.d3.max(availChartContext.data, function (d) {
+ return +d.availEnd;
+ }),
+
+ timeScale = $wnd.d3.time.scale()
+ .range([0, width])
+ .domain([xAxisMin, xAxisMax]),
+
+ yScale = $wnd.d3.scale.linear()
+ .clamp(true)
+ .rangeRound([height, 0])
+ .domain([0, 4]),
+
+ xAxis = $wnd.d3.svg.axis()
+ .scale(timeScale)
+ .ticks(12)
+ .tickSize(10, 0, 0)
+ .orient("bottom"),
+
+ calcBarY = function(d) {
+ var ABOVE = -10,
+ BELOW = 0,
+ STRADDLE = -5,
+ offset;
+
+ if (d.availType === 'DOWN') {
+ offset = BELOW;
+ }
+ else if (d.availType === 'DISABLED') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UNKNOWN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'UP') {
+ offset = ABOVE;
+ }
+ else if (d.availType === 'WARN') {
+ offset = STRADDLE;
+ }
+ else if (d.availType === 'EMPTY') {
+ offset = STRADDLE;
+ }
+ return yScale(0) + offset;
+
+ },
+
+ calcBarFill = function(d) {
+ if (d.availType === 'DOWN') {
+ return "#FF1919"; // red
+ }
+ else if (d.availType === 'DISABLED') {
+ return "#FF9933"; // orange
+ }
+ else if (d.availType === 'UNKNOWN') {
+ return "#CCC"; // gray
+ }
+ else if (d.availType === 'UP') {
+ return "#198C19"; // green
+ }
+ else if (d.availType === 'WARN') {
+ return "#FFA500"; // yellow
+ }
+ else if (d.availType === 'EMPTY') {
+ return "#CCC"; // gray
+ }
+ else {
+ // should not ever happen, but...
+ console.warn("AvailabilityType not valid.");
+ return "#000"; //black
+ }
+ },
+ svg = $wnd.d3.select(availChartContext.chartSelection).append("g")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+
+ svg.selectAll("rect.availBars")
+ .data(availChartContext.data)
+ .enter().append("rect")
+ .attr("class", "availBars")
+ .attr("x", function (d) {
+ return timeScale(+d.availStart);
+ })
+ .attr("y", function (d) {
+ return calcBarY(d);
+
+ })
+ .attr("height", function (d) {
+ return 10;
+
+ })
+ .attr("width", function (d) {
+ return timeScale(+d.availEnd) - timeScale(+d.availStart);
+ })
+ .attr("opacity", ".9")
+ .attr("fill", function (d) {
+ return calcBarFill(d);
+ });
+
+ // create x-axis
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("stroke", "#50505a")
+ .attr("stroke-width", "0.5")
+ .attr("transform", "translate(0," + height + ")")
+ .attr("letter-spacing", "3")
+ .style("text-anchor", "end")
+ .call(xAxis);
+
+ svg.append("text")
+ .attr("class", "availabilityLabel")
+ .attr("x", -40)
+ .attr("y", 10)
+ .style("font-size", "12px")
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-weight", "bold")
+ .attr("fill", "#003168")
+ .text("Availability");
+
+ svg.append("text")
+ .attr("class", "upLabel")
+ .attr("x", -5)
+ .attr("y", 28)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("UP");
+
+ svg.append("text")
+ .attr("class", "downLabel")
+ .attr("x", -5)
+ .attr("y", 39)
+ .style("font-family", "Arial, Verdana, sans-serif;")
+ .style("font-size", "9px")
+ .attr("fill", "#50505a")
+ .style("text-anchor", "end")
+ .text("DOWN");
+
+ }
+
+ function createHovers() {
+ $wnd.jQuery('svg rect.availBars').tipsy({
+ gravity: 's',
+ html: true,
+ trigger: 'hover',
+ title: function () {
+ var d = this.__data__;
+ return formatHovers(d);
+ },
+ show: function (e, el) {
+ el.css({ 'z-index': '990000'})
+ }
+ });
+ }
+
+ function formatHovers(d) {
+ var hoverString,
+ timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat),
+ dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat),
+ availStart = new Date(+d.availStart),
+ availEnd = new Date(+d.availEnd);
+
+ hoverString =
+ '<div class="chartHoverEnclosingDiv">' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span>'+ dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' +
+ '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' +
+ '</div>';
+ return hoverString;
+
+ }
+
+ return {
+ // Public API
+ draw: function (chartContext) {
+ "use strict";
+ console.info("AvailabilityChart");
+ //console.time("availabilityChart");
+ drawBars(availChartContext);
+ createHovers();
+ //console.timeEnd("availabilityChart");
+ }
+ }; // end public closure
+
+
+ }();
+
+ if (availChartContext.data !== undefined && availChartContext.data.length > 0) {
+ availabilityGraph.draw(availChartContext);
+ }
+
+ }-*/;
+
+ public String getChartId() {
+ return String.valueOf(entityId);
+ }
+
+ public String getChartTimeLabel() {
+ return MSG.chart_time_label();
+ }
+
+ public String getChartDateLabel() {
+ return MSG.chart_date_label();
+ }
+
+ public String getChartHoverAvailabilityLabel() {
+ return MSG.chart_hover_availability_label();
+ }
+
+ public String getChartHoverStartLabel() {
+ return MSG.chart_hover_start_label();
+ }
+
+ public String getChartHoverEndLabel() {
+ return MSG.chart_hover_end_label();
+ }
+
+ public String getChartHoverBarLabel() {
+ return MSG.chart_hover_bar_label();
+ }
+
+ public String getChartHoverTimeFormat() {
+ return MSG.chart_hover_time_format();
+ }
+
+ public String getChartHoverDateFormat() {
+ return MSG.chart_hover_date_format();
+ }
+}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index d9a4205..15f400d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -234,8 +234,10 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
chart.append("g").append("rect")
.attr("class", "rightSidePanel")
.attr("x", xLabel - 10)
- .attr("y", margin.top + 60)
- .attr("height", 100)
+ .attr("y", margin.top + 70)
+ .attr("rx", 10)
+ .attr("ry", 10)
+ .attr("height", 80)
.attr("width", 135)
.attr("opacity", "0.3")
.attr("fill", "#E8E8E8");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
index 786701b..7691c5f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/D3GroupGraphListView.java
@@ -42,6 +42,7 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.AutoRefresh;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.MetricD3GraphView;
@@ -74,7 +75,7 @@ public final class D3GroupGraphListView extends AbstractD3GraphListView implemen
addMember(measurementRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityLineGraphType(resourceGroup.getId()));
+ availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resourceGroup.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
index 26f3626..58d3050 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/D3GraphListView.java
@@ -47,6 +47,7 @@ import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferen
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3Graph;
@@ -130,7 +131,7 @@ public class D3GraphListView extends AbstractD3GraphListView {
addMember(measurementRangeEditor);
if (showAvailabilityGraph) {
- availabilityGraph = new AvailabilityD3Graph(new AvailabilityLineGraphType(resource.getId()));
+ availabilityGraph = new AvailabilityD3Graph(new AvailabilityOverUnderGraphType(resource.getId()));
// first step in 2 step to create d3 chart
// create a placeholder for avail graph
availabilityGraph.createGraphMarker();
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
index d03fefe..d06bab2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3Graph.java
@@ -26,6 +26,7 @@ import org.rhq.core.domain.measurement.Availability;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityGraph;
import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityLineGraphType;
+import org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.AvailabilityOverUnderGraphType;
import org.rhq.enterprise.gui.coregui.client.util.Log;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
@@ -37,12 +38,12 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
*/
public class AvailabilityD3Graph extends EnhancedVLayout implements AvailabilityGraph {
- protected AvailabilityLineGraphType availabilityGraphType;
+ protected AvailabilityOverUnderGraphType availabilityGraphType;
- public AvailabilityD3Graph(AvailabilityLineGraphType graphType) {
+ public AvailabilityD3Graph(AvailabilityOverUnderGraphType graphType) {
super();
this.availabilityGraphType = graphType;
- setHeight(25);
+ setHeight(70);
setWidth100();
}
@@ -82,7 +83,7 @@ public class AvailabilityD3Graph extends EnhancedVLayout implements Availability
StringBuilder divAndSvgDefs = new StringBuilder();
divAndSvgDefs.append("<div id=\"availChart-" + availabilityGraphType.getChartId()
- + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:20px;\">");
+ + "\" ><svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style=\"height:110px;\">");
divAndSvgDefs.append("</svg></div>");
HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString());
graph.setWidth100();
commit 85215f76e7ec578a7cad3a13e983c6cbffa0650f
Author: mtho11 <mikecthompson(a)gmail.com>
Date: Wed Apr 24 16:16:15 2013 -0700
Trivial: add *.DS_Store files to .gitignore
diff --git a/.gitignore b/.gitignore
index 92b2176..3bd9232 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,6 @@ modules/enterprise/gui/coregui/build/classes/
modules/enterprise/gui/content_http-war/build/classes/
#created by rhq-enterprise-server's unit tests
modules/enterprise/server/jar/transaction.log
-
.idea/
.metadata/
*cache.html
@@ -27,6 +26,7 @@ modules/enterprise/server/jar/transaction.log
.*.jsfdia
.wtpmodules
*~
+*.DS_Store
#these are created by the python script engine during the tests
cachedir/
commit f875212be4a8cfaf0905e2fd376a579197b83148
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue May 7 14:25:34 2013 +0200
Bug 865629 - (PRODMGT-245) Add more metrics to AS7 plugin
Added missing metrics
Added integration test
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index cfe756d..5f538b7 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -615,6 +615,7 @@
<include>org/rhq/modules/plugins/jbossas7/itest/**/*Test.java</include>
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 45f4e05..742c4d5 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -8864,6 +8864,22 @@
<metric property="responseTime"
dataType="calltime" defaultOn="false" units="milliseconds" destinationType="URL"
description="the minimum, maximum, and average response times for requests serviced by this webapp"/>
+ <metric property="active-sessions" displayName="Currently Active Sessions"
+ description="The number of sessions that are currently active"/>
+ <metric property="duplicated-session-ids" displayName="Duplicated Session Ids"
+ description="The number of duplicated session identifiers"/>
+ <metric property="expired-sessions" measurementType="trendsup" displayName="Expired Sessions"
+ description="The number of expired sessions"/>
+ <metric property="max-active-sessions" displayName="Maximum Active Sessions"
+ description="The maximum number of sessions that have been active"/>
+ <metric property="rejected-sessions" measurementType="trendsup" displayName="Rejected Sessions"
+ description="The number of sessions rejected"/>
+ <metric property="session-avg-alive-time" units="milliseconds" displayName="Average Session Alive Time"
+ description="The average alive time of sessions"/>
+ <metric property="session-max-alive-time" units="milliseconds" displayName="Max Session Alive Time"
+ description="The maximum alive time of sessions"/>
+ <metric property="sessions-created" measurementType="trendsup" displayName="Created Sessions"
+ description="The number of sessions created"/>
</service>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
index 6f84e34..5b552bc 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/DeploymentTest.java
@@ -19,6 +19,11 @@
package org.rhq.modules.plugins.jbossas7.itest.standalone;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.rhq.core.domain.util.ResourceTypeUtility.getMeasurementDefinitions;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -27,6 +32,8 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
import java.util.Set;
import org.mockito.Mockito;
@@ -47,8 +54,18 @@ import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.content.PackageDetailsKey;
import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
+import org.rhq.core.domain.measurement.DataType;
+import org.rhq.core.domain.measurement.MeasurementDataNumeric;
+import org.rhq.core.domain.measurement.MeasurementDataTrait;
+import org.rhq.core.domain.measurement.MeasurementDefinition;
+import org.rhq.core.domain.measurement.MeasurementReport;
+import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.domain.resource.CreateResourceStatus;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.util.MeasurementDefinitionFilter;
+import org.rhq.core.pc.inventory.ResourceContainer;
+import org.rhq.core.pc.util.FacetLockType;
+import org.rhq.core.pluginapi.measurement.MeasurementFacet;
import org.rhq.modules.plugins.jbossas7.StandaloneASComponent;
import org.rhq.modules.plugins.jbossas7.itest.AbstractJBossAS7PluginTest;
import org.rhq.test.arquillian.DiscoveredResources;
@@ -101,6 +118,9 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
@DiscoveredResources(plugin = PLUGIN_NAME, resourceType = "Deployment")
private Set<Resource> deploymentResources;
+ @DiscoveredResources(plugin = PLUGIN_NAME, resourceType = "Web Runtime")
+ private Set<Resource> webRuntimeResources;
+
private static TestDeployments DEPLOYMENT_TO_SERVE = TestDeployments.DEPLOYMENT_1;
private static long copyStreamAndReturnCount(InputStream in, OutputStream out) throws IOException {
@@ -242,6 +262,60 @@ public class DeploymentTest extends AbstractJBossAS7PluginTest {
}
@Test(priority = 15)
+ @RunDiscovery
+ public void testWebRuntimeMetricsHaveNonNullValues() throws Exception {
+ assertTrue(webRuntimeResources != null && !webRuntimeResources.isEmpty(),
+ "Web Runtime resource should have been discovered");
+ assertEquals(webRuntimeResources.size(), 1, "Found more than one Web Runtime resource: " + webRuntimeResources);
+
+ Resource webRuntimeResource = webRuntimeResources.iterator().next();
+ ResourceContainer webRuntimeResourceContainer = pluginContainer.getInventoryManager().getResourceContainer(
+ webRuntimeResource);
+ MeasurementFacet measurementFacet = webRuntimeResourceContainer.createResourceComponentProxy(
+ MeasurementFacet.class, FacetLockType.READ, SECONDS.toMillis(5), false, false);
+ MeasurementReport report = new MeasurementReport();
+ Set<MeasurementScheduleRequest> measurementScheduleRequests = getMeasurementScheduleRequests(webRuntimeResource);
+ measurementFacet.getValues(report, measurementScheduleRequests);
+ assertEquals(report.getCallTimeData().size(), 0, "No calltime data was requested");
+ assertTrue(
+ report.getNumericData().size() + report.getTraitData().size() == measurementScheduleRequests.size(),
+ "Some requested measurements are missing: "
+ + getMissingMeasurements(measurementScheduleRequests, report.getNumericData(), report.getTraitData()));
+ }
+
+ private Set<String> getMissingMeasurements(Set<MeasurementScheduleRequest> measurementScheduleRequests,
+ Set<MeasurementDataNumeric> numericData, Set<MeasurementDataTrait> traitData) {
+ Set<String> missingMeasurements = new HashSet<String>();
+ for (MeasurementScheduleRequest measurementScheduleRequest : measurementScheduleRequests) {
+ missingMeasurements.add(measurementScheduleRequest.getName());
+ }
+ for (MeasurementDataNumeric measurementDataNumeric : numericData) {
+ missingMeasurements.remove(measurementDataNumeric.getName());
+ }
+ for (MeasurementDataTrait measurementDataTrait : traitData) {
+ missingMeasurements.remove(measurementDataTrait.getName());
+ }
+ return missingMeasurements;
+ }
+
+ private Set<MeasurementScheduleRequest> getMeasurementScheduleRequests(Resource webRuntimeResource) {
+ Set<MeasurementDefinition> measurementDefinitions = getMeasurementDefinitions(
+ webRuntimeResource.getResourceType(), new MeasurementDefinitionFilter() {
+ private final Set<DataType> acceptableDataTypes = EnumSet.of(DataType.MEASUREMENT, DataType.TRAIT);
+
+ public boolean accept(MeasurementDefinition measurementDefinition) {
+ return acceptableDataTypes.contains(measurementDefinition.getDataType());
+ }
+ });
+ Set<MeasurementScheduleRequest> measurementScheduleRequests = new HashSet<MeasurementScheduleRequest>();
+ for (MeasurementDefinition measurementDefinition : measurementDefinitions) {
+ measurementScheduleRequests.add(new MeasurementScheduleRequest(-1, measurementDefinition.getName(), -1,
+ true, measurementDefinition.getDataType(), measurementDefinition.getRawNumericType()));
+ }
+ return measurementScheduleRequests;
+ }
+
+ @Test(priority = 16)
public void testUndeploy() throws Exception {
Resource deployment = deploymentResources.iterator().next();
DeleteResourceRequest request = new DeleteResourceRequest(0, deployment.getId());
commit e589245b50710f5487ce3efcd527f73c02df8ea3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon May 6 19:02:55 2013 -0400
BZ 817825 don't show "Loading..." for leaf nodes in resource type drop down menus
this still doesn't fix the Platform plugin's platform type submenus.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
index e2650e4..90511d7 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/selection/ResourceSelector.java
@@ -77,8 +77,6 @@ public class ResourceSelector extends AbstractSelector<Resource, ResourceCriteri
typeSelectItem.setValueField("id");
typeSelectItem.setCanSelectParentItems(true);
typeSelectItem.setLoadDataOnDemand(false);
- typeSelectItem.setEmptyMenuMessage(MSG.common_msg_loading());
- typeSelectItem.setShowIcons(false);
if (this.forceResourceTypeFilter) {
typeSelectItem.setDisabled(true);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
index 136db95..c1c9e66 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/type/ResourceTypePluginTreeDataSource.java
@@ -19,8 +19,6 @@
package org.rhq.enterprise.gui.coregui.client.inventory.resource.type;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.HashMap;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -144,12 +142,6 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
}
}
- Collections.sort(nodes, new Comparator<TreeNode>() {
- public int compare(TreeNode o1, TreeNode o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
-
TreeNode[] treeNodes = nodes.toArray(new TreeNode[nodes.size()]);
return treeNodes;
}
@@ -198,9 +190,8 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
setParentID(null);
setAttribute("name", pluginName + " " + pluginStr);
- // setAttribute("plugin",pluginName);
- setIcon("types/plugin_16.png"); // todo doesn't work
setEnabled(true);
+ // setIcon(IconEnum.PLUGIN.getIcon16x16Path()); // IPickTreeItem doesn't appear to want to use this
}
@Override
@@ -245,10 +236,7 @@ public class ResourceTypePluginTreeDataSource extends DataSource {
setAttribute("name", resourceType.getName());
setAttribute("plugin", resourceType.getPlugin());
setAttribute("category", resourceType.getCategory().getDisplayName());
-
- setIcon("types/" + resourceType.getCategory().getDisplayName() + "_up_16.png");
-
- setIsFolder(true);
+ // setIcon(ImageManager.getResourceIcon(resourceType.getCategory())); // IPickTreeItem doesn't appear to want to use this
}
public ResourceType getResourceType() {
commit 82a86c90fcc05ec19b1b9b63771fe12905cb2f09
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon May 6 16:03:20 2013 -0400
BZ 960265 bring back the GWT calltime page
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index a68170a..91db630 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -28,6 +28,7 @@ import com.smartgwt.client.widgets.Canvas;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.DataType;
@@ -55,7 +56,6 @@ import org.rhq.enterprise.gui.coregui.client.drift.ResourceDriftDefinitionsView;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.AbstractTwoLevelTabSetView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.monitoring.IFrameWithMeasurementRangeEditorView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.event.EventCompositeHistoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.ResourceGroupListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceCompositeSearchView;
@@ -64,6 +64,7 @@ import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configura
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationEditView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.PluginConfigurationHistoryListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory.ResourceAgentView;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.CalltimeView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.D3GraphListView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.ResourceAvailabilityView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.schedules.ResourceSchedulesView;
@@ -437,8 +438,7 @@ public class ResourceDetailView extends
viewFactory = (!visible) ? null : new ViewFactory() {
@Override
public Canvas createView() {
- return new IFrameWithMeasurementRangeEditorView("/rhq/resource/monitor/response-plain.xhtml?id="
- + resource.getId());
+ return new CalltimeView(EntityContext.forResource(resource.getId()));
}
};
updateSubTab(this.monitoringTab, this.monitorCallTime, visible, true, viewFactory);
commit 98f5814fe4acb2dd5a9305170460638e3cd984e1
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:05:04 2013 -0500
Update development version to 4.8.0-SNAPSHOT.
diff --git a/code-coverage/pom.xml b/code-coverage/pom.xml
index f1f8cec..dbb487d 100644
--- a/code-coverage/pom.xml
+++ b/code-coverage/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-code-coverage</artifactId>
diff --git a/modules/cli-tests/pom.xml b/modules/cli-tests/pom.xml
index c4dadc9..efe6d1f 100644
--- a/modules/cli-tests/pom.xml
+++ b/modules/cli-tests/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/common/ant-bundle/pom.xml b/modules/common/ant-bundle/pom.xml
index 4cf6703..138e9ca 100644
--- a/modules/common/ant-bundle/pom.xml
+++ b/modules/common/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml
index 9d7a132..5afdead 100644
--- a/modules/common/drift/pom.xml
+++ b/modules/common/drift/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-common-drift</artifactId>
diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml
index 32692b5..0beb20b 100644
--- a/modules/common/filetemplate-bundle/pom.xml
+++ b/modules/common/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-filetemplate-bundle-common</artifactId>
diff --git a/modules/common/jboss-as-dmr-client/pom.xml b/modules/common/jboss-as-dmr-client/pom.xml
index 4f43692..b8c1682 100644
--- a/modules/common/jboss-as-dmr-client/pom.xml
+++ b/modules/common/jboss-as-dmr-client/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-dmr-client</artifactId>
diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml
index b9ee5be..6dac77b 100644
--- a/modules/common/jboss-as/pom.xml
+++ b/modules/common/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-common-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-jboss-as-common</artifactId>
diff --git a/modules/common/pom.xml b/modules/common/pom.xml
index 4ed6d92..088e268 100644
--- a/modules/common/pom.xml
+++ b/modules/common/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/arquillian-integration/archive/pom.xml b/modules/core/arquillian-integration/archive/pom.xml
index 7c7e949..fe5f377 100644
--- a/modules/core/arquillian-integration/archive/pom.xml
+++ b/modules/core/arquillian-integration/archive/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/container/pom.xml b/modules/core/arquillian-integration/container/pom.xml
index 75a7a05..258d050 100644
--- a/modules/core/arquillian-integration/container/pom.xml
+++ b/modules/core/arquillian-integration/container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 9637dfc..67b02a8 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/arquillian-integration/suite-extension/pom.xml b/modules/core/arquillian-integration/suite-extension/pom.xml
index 5d80c3f..231ab67 100644
--- a/modules/core/arquillian-integration/suite-extension/pom.xml
+++ b/modules/core/arquillian-integration/suite-extension/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<!-- Model Version -->
diff --git a/modules/core/arquillian-integration/test-agent-plugin/pom.xml b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
index f086ca3..4ed7bca 100644
--- a/modules/core/arquillian-integration/test-agent-plugin/pom.xml
+++ b/modules/core/arquillian-integration/test-agent-plugin/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-arquillian-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/client-api/pom.xml b/modules/core/client-api/pom.xml
index acd19c9..7adcd3b 100644
--- a/modules/core/client-api/pom.xml
+++ b/modules/core/client-api/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/comm-api/pom.xml b/modules/core/comm-api/pom.xml
index 9fd9f98..1fb2161 100644
--- a/modules/core/comm-api/pom.xml
+++ b/modules/core/comm-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index d77ee51..cc040f8 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/domain/pom.xml b/modules/core/domain/pom.xml
index d572d9d..776459d 100644
--- a/modules/core/domain/pom.xml
+++ b/modules/core/domain/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-domain</artifactId>
diff --git a/modules/core/gui/pom.xml b/modules/core/gui/pom.xml
index b3b7706..dc21aad 100644
--- a/modules/core/gui/pom.xml
+++ b/modules/core/gui/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/native-system/pom.xml b/modules/core/native-system/pom.xml
index 04be12b..46fe305 100644
--- a/modules/core/native-system/pom.xml
+++ b/modules/core/native-system/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/plugin-api/pom.xml b/modules/core/plugin-api/pom.xml
index a24c330..8060a89 100644
--- a/modules/core/plugin-api/pom.xml
+++ b/modules/core/plugin-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-container-itest/pom.xml b/modules/core/plugin-container-itest/pom.xml
index 900eb72..9c801de 100644
--- a/modules/core/plugin-container-itest/pom.xml
+++ b/modules/core/plugin-container-itest/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container-itest</artifactId>
diff --git a/modules/core/plugin-container/pom.xml b/modules/core/plugin-container/pom.xml
index 06395a2..3c070a9 100644
--- a/modules/core/plugin-container/pom.xml
+++ b/modules/core/plugin-container/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-container</artifactId>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index fc49cf3..18fa318 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-plugin-test-api</artifactId>
diff --git a/modules/core/plugin-test-util/pom.xml b/modules/core/plugin-test-util/pom.xml
index c75dcbc..0374729 100644
--- a/modules/core/plugin-test-util/pom.xml
+++ b/modules/core/plugin-test-util/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugin-validator/pom.xml b/modules/core/plugin-validator/pom.xml
index d05b721..99c875d 100644
--- a/modules/core/plugin-validator/pom.xml
+++ b/modules/core/plugin-validator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/plugindoc/pom.xml b/modules/core/plugindoc/pom.xml
index c3c7175..426d298 100644
--- a/modules/core/plugindoc/pom.xml
+++ b/modules/core/plugindoc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c4992af..c41a8f4 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/core/util/pom.xml b/modules/core/util/pom.xml
index b799891..cdc3b9b 100644
--- a/modules/core/util/pom.xml
+++ b/modules/core/util/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-core-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-core-util</artifactId>
diff --git a/modules/enterprise/agent/pom.xml b/modules/enterprise/agent/pom.xml
index cb1fad0..2d7093d 100644
--- a/modules/enterprise/agent/pom.xml
+++ b/modules/enterprise/agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index 3b66b92..67ed9a8 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/binding/pom.xml b/modules/enterprise/binding/pom.xml
index a41fb6c..d5b7643 100644
--- a/modules/enterprise/binding/pom.xml
+++ b/modules/enterprise/binding/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-script-bindings</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Script Bindings</name>
<description>Abstraction of different facilities and default configurations for script bindings</description>
diff --git a/modules/enterprise/comm/pom.xml b/modules/enterprise/comm/pom.xml
index c312dc1..8148262 100644
--- a/modules/enterprise/comm/pom.xml
+++ b/modules/enterprise/comm/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/content_http-war/pom.xml b/modules/enterprise/gui/content_http-war/pom.xml
index 333aa5d..a140a9c 100644
--- a/modules/enterprise/gui/content_http-war/pom.xml
+++ b/modules/enterprise/gui/content_http-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-gui-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/gui/coregui/pom.xml b/modules/enterprise/gui/coregui/pom.xml
index 035ade8..cb7dd3a 100644
--- a/modules/enterprise/gui/coregui/pom.xml
+++ b/modules/enterprise/gui/coregui/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 1fa9ec1..018a802 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -8,7 +8,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/portal-war/pom.xml b/modules/enterprise/gui/portal-war/pom.xml
index a827c3c..d2998cc 100644
--- a/modules/enterprise/gui/portal-war/pom.xml
+++ b/modules/enterprise/gui/portal-war/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/remoting-war/pom.xml b/modules/enterprise/gui/remoting-war/pom.xml
index 70ece03..638bccd 100644
--- a/modules/enterprise/gui/remoting-war/pom.xml
+++ b/modules/enterprise/gui/remoting-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-examples-war/pom.xml b/modules/enterprise/gui/rest-examples-war/pom.xml
index 2a5091c..c9aa075 100644
--- a/modules/enterprise/gui/rest-examples-war/pom.xml
+++ b/modules/enterprise/gui/rest-examples-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/gui/rest-war/pom.xml b/modules/enterprise/gui/rest-war/pom.xml
index 5d3dbfc..33e330e 100644
--- a/modules/enterprise/gui/rest-war/pom.xml
+++ b/modules/enterprise/gui/rest-war/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/pom.xml b/modules/enterprise/pom.xml
index 489d603..3fad441 100644
--- a/modules/enterprise/pom.xml
+++ b/modules/enterprise/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index e371826..dec19d0 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-api/pom.xml b/modules/enterprise/remoting/client-api/pom.xml
index 2c7b6f9..cba50db 100644
--- a/modules/enterprise/remoting/client-api/pom.xml
+++ b/modules/enterprise/remoting/client-api/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/client-deps/pom.xml b/modules/enterprise/remoting/client-deps/pom.xml
index b411a87..6db40f2 100644
--- a/modules/enterprise/remoting/client-deps/pom.xml
+++ b/modules/enterprise/remoting/client-deps/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/remoting/pom.xml b/modules/enterprise/remoting/pom.xml
index 3ab9e66..7bf574e 100644
--- a/modules/enterprise/remoting/pom.xml
+++ b/modules/enterprise/remoting/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/scripting/api/pom.xml b/modules/enterprise/scripting/api/pom.xml
index 07768cd..268af3a 100644
--- a/modules/enterprise/scripting/api/pom.xml
+++ b/modules/enterprise/scripting/api/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-api</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting API</name>
<description>Provides API for adding scripting support to RHQ using different javax.scripting - based interpreters</description>
diff --git a/modules/enterprise/scripting/javascript/pom.xml b/modules/enterprise/scripting/javascript/pom.xml
index 32eb12d..acc09aa 100644
--- a/modules/enterprise/scripting/javascript/pom.xml
+++ b/modules/enterprise/scripting/javascript/pom.xml
@@ -4,10 +4,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-javascript</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Javascript support</name>
<description>Provides RHQ scripting in Javascript using Rhino</description>
diff --git a/modules/enterprise/scripting/pom.xml b/modules/enterprise/scripting/pom.xml
index 5c82958..a58f1ca 100644
--- a/modules/enterprise/scripting/pom.xml
+++ b/modules/enterprise/scripting/pom.xml
@@ -3,12 +3,12 @@
<parent>
<artifactId>rhq-enterprise-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-parent</artifactId>
<packaging>pom</packaging>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Scripting Parent Module</name>
<modules>
diff --git a/modules/enterprise/scripting/python/pom.xml b/modules/enterprise/scripting/python/pom.xml
index f6a1149c..dc69d9e 100644
--- a/modules/enterprise/scripting/python/pom.xml
+++ b/modules/enterprise/scripting/python/pom.xml
@@ -3,10 +3,10 @@
<parent>
<artifactId>rhq-scripting-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>rhq-scripting-python</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Python support</name>
<description>Provides RHQ scripting in Python using Jython</description>
diff --git a/modules/enterprise/server/appserver/pom.xml b/modules/enterprise/server/appserver/pom.xml
index 0e46986..f186d70 100644
--- a/modules/enterprise/server/appserver/pom.xml
+++ b/modules/enterprise/server/appserver/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/client-api/pom.xml b/modules/enterprise/server/client-api/pom.xml
index 6bb6ea2..3e69ded 100644
--- a/modules/enterprise/server/client-api/pom.xml
+++ b/modules/enterprise/server/client-api/pom.xml
@@ -5,13 +5,13 @@
<parent>
<artifactId>rhq-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-server-client-api</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Client API</name>
<description>The implementation of the client API when accessing the server locally</description>
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 939f107..867ebe1 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/installer/pom.xml b/modules/enterprise/server/installer/pom.xml
index 150daf2..23d8e94 100644
--- a/modules/enterprise/server/installer/pom.xml
+++ b/modules/enterprise/server/installer/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/itests-2/pom.xml b/modules/enterprise/server/itests-2/pom.xml
index 9f9ba81..5e4e076 100644
--- a/modules/enterprise/server/itests-2/pom.xml
+++ b/modules/enterprise/server/itests-2/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/jar/pom.xml b/modules/enterprise/server/jar/pom.xml
index acb8931..84e34c4 100644
--- a/modules/enterprise/server/jar/pom.xml
+++ b/modules/enterprise/server/jar/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/alert-cli/pom.xml b/modules/enterprise/server/plugins/alert-cli/pom.xml
index 68ea87a..ea9bd42 100644
--- a/modules/enterprise/server/plugins/alert-cli/pom.xml
+++ b/modules/enterprise/server/plugins/alert-cli/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>alert-cli</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Script Alert Plugin</name>
<description>An alert sender able to execute an arbitrary CLI script as a response to an alert</description>
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
index ec91baf..a2102a3 100644
--- a/modules/enterprise/server/plugins/alert-email/pom.xml
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.server</groupId>
<artifactId>alert-email</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Email Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-irc/pom.xml b/modules/enterprise/server/plugins/alert-irc/pom.xml
index ea7bd90..bd5f656 100644
--- a/modules/enterprise/server/plugins/alert-irc/pom.xml
+++ b/modules/enterprise/server/plugins/alert-irc/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-irc</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server IRC Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-log4j/pom.xml b/modules/enterprise/server/plugins/alert-log4j/pom.xml
index c50b5cb..934cb7e 100644
--- a/modules/enterprise/server/plugins/alert-log4j/pom.xml
+++ b/modules/enterprise/server/plugins/alert-log4j/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-log4j</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Log4J Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-microblog/pom.xml b/modules/enterprise/server/plugins/alert-microblog/pom.xml
index c576b41..28d1d56 100644
--- a/modules/enterprise/server/plugins/alert-microblog/pom.xml
+++ b/modules/enterprise/server/plugins/alert-microblog/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-microblog</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Microblog Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-mobicents/pom.xml b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
index 5d9fb43..4338526 100644
--- a/modules/enterprise/server/plugins/alert-mobicents/pom.xml
+++ b/modules/enterprise/server/plugins/alert-mobicents/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-mobicents</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Mobicents Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-operations/pom.xml b/modules/enterprise/server/plugins/alert-operations/pom.xml
index 24813ad..21ec5f7 100644
--- a/modules/enterprise/server/plugins/alert-operations/pom.xml
+++ b/modules/enterprise/server/plugins/alert-operations/pom.xml
@@ -2,14 +2,14 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-operations</artifactId>
<packaging>jar</packaging>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Opertions Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-roles/pom.xml b/modules/enterprise/server/plugins/alert-roles/pom.xml
index 31acb49..a6c054a 100644
--- a/modules/enterprise/server/plugins/alert-roles/pom.xml
+++ b/modules/enterprise/server/plugins/alert-roles/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-roles</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Roles Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index b09ed2a..f84398b 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-snmp</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/alert-subject/pom.xml b/modules/enterprise/server/plugins/alert-subject/pom.xml
index cd0263b..d4d2564 100644
--- a/modules/enterprise/server/plugins/alert-subject/pom.xml
+++ b/modules/enterprise/server/plugins/alert-subject/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>alert-subject</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Subject Alert Plugin</name>
diff --git a/modules/enterprise/server/plugins/ant-bundle/pom.xml b/modules/enterprise/server/plugins/ant-bundle/pom.xml
index 489b37b..648b451 100644
--- a/modules/enterprise/server/plugins/ant-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/cobbler/pom.xml b/modules/enterprise/server/plugins/cobbler/pom.xml
index 94cbe7d..6f56e82 100644
--- a/modules/enterprise/server/plugins/cobbler/pom.xml
+++ b/modules/enterprise/server/plugins/cobbler/pom.xml
@@ -4,14 +4,14 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>rhq-serverplugin-cobbler</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server Cobbler Plugin</name>
diff --git a/modules/enterprise/server/plugins/disk/pom.xml b/modules/enterprise/server/plugins/disk/pom.xml
index c111bcc..21bb689 100644
--- a/modules/enterprise/server/plugins/disk/pom.xml
+++ b/modules/enterprise/server/plugins/disk/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/drift-rhq/pom.xml b/modules/enterprise/server/plugins/drift-rhq/pom.xml
index 52b3a7c..7111543 100644
--- a/modules/enterprise/server/plugins/drift-rhq/pom.xml
+++ b/modules/enterprise/server/plugins/drift-rhq/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
index b43da47..6ab0964 100644
--- a/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
+++ b/modules/enterprise/server/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/jboss-software/pom.xml b/modules/enterprise/server/plugins/jboss-software/pom.xml
index 33a11a1..32ffc76 100644
--- a/modules/enterprise/server/plugins/jboss-software/pom.xml
+++ b/modules/enterprise/server/plugins/jboss-software/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/packagetype-cli/pom.xml b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
index 80799ab..2a75e07 100644
--- a/modules/enterprise/server/plugins/packagetype-cli/pom.xml
+++ b/modules/enterprise/server/plugins/packagetype-cli/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq</groupId>
<artifactId>packagetype-cli</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>RHQ Enterprise Server CLI Package Type Plugin</name>
diff --git a/modules/enterprise/server/plugins/pom.xml b/modules/enterprise/server/plugins/pom.xml
index 827bc41..dc862db 100644
--- a/modules/enterprise/server/plugins/pom.xml
+++ b/modules/enterprise/server/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/plugins/url/pom.xml b/modules/enterprise/server/plugins/url/pom.xml
index 5660473..bb1740d 100644
--- a/modules/enterprise/server/plugins/url/pom.xml
+++ b/modules/enterprise/server/plugins/url/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
index 0d80df3..06da613 100644
--- a/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
+++ b/modules/enterprise/server/plugins/validate-all-serverplugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml
index 75b3cdc..6f8ac10 100644
--- a/modules/enterprise/server/plugins/yum/pom.xml
+++ b/modules/enterprise/server/plugins/yum/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/pom.xml b/modules/enterprise/server/pom.xml
index 494e98e..9c60e30 100644
--- a/modules/enterprise/server/pom.xml
+++ b/modules/enterprise/server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/safe-invoker/pom.xml b/modules/enterprise/server/safe-invoker/pom.xml
index 8c509f4..b2b741e 100644
--- a/modules/enterprise/server/safe-invoker/pom.xml
+++ b/modules/enterprise/server/safe-invoker/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/pom.xml b/modules/enterprise/server/sars/pom.xml
index 2b00e67..d4f7715 100644
--- a/modules/enterprise/server/sars/pom.xml
+++ b/modules/enterprise/server/sars/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/sars/services-sar/pom.xml b/modules/enterprise/server/sars/services-sar/pom.xml
index 4586a8b..014420b 100644
--- a/modules/enterprise/server/sars/services-sar/pom.xml
+++ b/modules/enterprise/server/sars/services-sar/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-sars-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/startup-subsystem/pom.xml b/modules/enterprise/server/startup-subsystem/pom.xml
index 3359f33..7152fc3 100644
--- a/modules/enterprise/server/startup-subsystem/pom.xml
+++ b/modules/enterprise/server/startup-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index 98783f1..00e558b 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/bundleGen/pom.xml b/modules/helpers/bundleGen/pom.xml
index 82fabfc..f2f2455 100644
--- a/modules/helpers/bundleGen/pom.xml
+++ b/modules/helpers/bundleGen/pom.xml
@@ -3,13 +3,13 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.rhq.helpers</groupId>
<artifactId>bundleGen</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<build>
<plugins>
diff --git a/modules/helpers/jeeGen/pom.xml b/modules/helpers/jeeGen/pom.xml
index 348b780..6f36514 100644
--- a/modules/helpers/jeeGen/pom.xml
+++ b/modules/helpers/jeeGen/pom.xml
@@ -9,7 +9,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/perftest-support/pom.xml b/modules/helpers/perftest-support/pom.xml
index ed71426..8772058 100644
--- a/modules/helpers/perftest-support/pom.xml
+++ b/modules/helpers/perftest-support/pom.xml
@@ -3,11 +3,11 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>perftest-support</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<name>Performance Testing Support</name>
<description>To support performance testing, this is a basic tool to support extracting and later reimporting of
data from/to a database.
diff --git a/modules/helpers/pom.xml b/modules/helpers/pom.xml
index bd47d23..ecebf6c 100644
--- a/modules/helpers/pom.xml
+++ b/modules/helpers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/helpers/rest-docs-generator/pom.xml b/modules/helpers/rest-docs-generator/pom.xml
index e72aab4..c5a4a41 100644
--- a/modules/helpers/rest-docs-generator/pom.xml
+++ b/modules/helpers/rest-docs-generator/pom.xml
@@ -24,7 +24,7 @@
<parent>
<artifactId>rhq-helpers</artifactId>
<groupId>org.rhq.helpers</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/helpers/rtfilter-subsystem/pom.xml b/modules/helpers/rtfilter-subsystem/pom.xml
index f3cbb2e..baf0801 100644
--- a/modules/helpers/rtfilter-subsystem/pom.xml
+++ b/modules/helpers/rtfilter-subsystem/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/helpers/rtfilter/pom.xml b/modules/helpers/rtfilter/pom.xml
index da9cf66..bf4ca3d 100644
--- a/modules/helpers/rtfilter/pom.xml
+++ b/modules/helpers/rtfilter/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq.helpers</groupId>
<artifactId>rhq-helpers</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq.helpers</groupId>
diff --git a/modules/integration-tests/apache-plugin-test/pom.xml b/modules/integration-tests/apache-plugin-test/pom.xml
index ce66fd5..a9d7296 100644
--- a/modules/integration-tests/apache-plugin-test/pom.xml
+++ b/modules/integration-tests/apache-plugin-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index f83573d..48808ac 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-test</artifactId>
diff --git a/modules/integration-tests/jndi-access/pom.xml b/modules/integration-tests/jndi-access/pom.xml
index caef075..6ded494 100644
--- a/modules/integration-tests/jndi-access/pom.xml
+++ b/modules/integration-tests/jndi-access/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>rhq-integration-tests</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/integration-tests/jndi-access/remote-server/pom.xml b/modules/integration-tests/jndi-access/remote-server/pom.xml
index b28b9bf..d11992a 100644
--- a/modules/integration-tests/jndi-access/remote-server/pom.xml
+++ b/modules/integration-tests/jndi-access/remote-server/pom.xml
@@ -4,7 +4,7 @@
<parent>
<artifactId>jndi-access-test-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>jndi-access-remote-server</artifactId>
diff --git a/modules/integration-tests/pom.xml b/modules/integration-tests/pom.xml
index f110387..7e5f521 100644
--- a/modules/integration-tests/pom.xml
+++ b/modules/integration-tests/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/integration-tests/rest-api/pom.xml b/modules/integration-tests/rest-api/pom.xml
index 6061752..bca2fe4 100644
--- a/modules/integration-tests/rest-api/pom.xml
+++ b/modules/integration-tests/rest-api/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-integration-tests</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index 14874eb..2809e95 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/ant-bundle/pom.xml b/modules/plugins/ant-bundle/pom.xml
index 9c3e48d..75a98a4 100644
--- a/modules/plugins/ant-bundle/pom.xml
+++ b/modules/plugins/ant-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/apache/pom.xml b/modules/plugins/apache/pom.xml
index 3f6bca5..380f6e6 100644
--- a/modules/plugins/apache/pom.xml
+++ b/modules/plugins/apache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 4e663e6..ada89b3 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/byteman/pom.xml b/modules/plugins/byteman/pom.xml
index 6a85842..37ffe0e 100644
--- a/modules/plugins/byteman/pom.xml
+++ b/modules/plugins/byteman/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index d576083..a17a3d8 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cobbler/pom.xml b/modules/plugins/cobbler/pom.xml
index c01634b..9424397 100644
--- a/modules/plugins/cobbler/pom.xml
+++ b/modules/plugins/cobbler/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
index 27f290b..3aa5463 100644
--- a/modules/plugins/cron/pom.xml
+++ b/modules/plugins/cron/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/database/pom.xml b/modules/plugins/database/pom.xml
index 7959a32..03349f8 100644
--- a/modules/plugins/database/pom.xml
+++ b/modules/plugins/database/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/filetemplate-bundle/pom.xml b/modules/plugins/filetemplate-bundle/pom.xml
index c67fc10..8a5f0e6 100644
--- a/modules/plugins/filetemplate-bundle/pom.xml
+++ b/modules/plugins/filetemplate-bundle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/grub/pom.xml b/modules/plugins/grub/pom.xml
index 4a3ad1d..a1c3353 100644
--- a/modules/plugins/grub/pom.xml
+++ b/modules/plugins/grub/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hadoop/pom.xml b/modules/plugins/hadoop/pom.xml
index dd99a37..d8325e4 100644
--- a/modules/plugins/hadoop/pom.xml
+++ b/modules/plugins/hadoop/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hibernate/pom.xml b/modules/plugins/hibernate/pom.xml
index 0303046..adee980 100644
--- a/modules/plugins/hibernate/pom.xml
+++ b/modules/plugins/hibernate/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<!-- Bypass the jopr-plugins-parent which can not have children. It must build after the plugins in order to execute integration tests on them. -->
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 9ca39d3..f587112 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/hudson/pom.xml b/modules/plugins/hudson/pom.xml
index 1a8d193..d1f3e43 100644
--- a/modules/plugins/hudson/pom.xml
+++ b/modules/plugins/hudson/pom.xml
@@ -6,12 +6,12 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-hudson-plugin</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>RHQ Hudson Plugin</name>
diff --git a/modules/plugins/iis/pom.xml b/modules/plugins/iis/pom.xml
index 69f1dbb..93a915f 100644
--- a/modules/plugins/iis/pom.xml
+++ b/modules/plugins/iis/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/irc/pom.xml b/modules/plugins/irc/pom.xml
index 875e82f..b043e7b 100644
--- a/modules/plugins/irc/pom.xml
+++ b/modules/plugins/irc/pom.xml
@@ -5,7 +5,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index 221d4cc..f2e6f8a 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -9,7 +9,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 81b2322..cfe756d 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/jboss-as/pom.xml b/modules/plugins/jboss-as/pom.xml
index bd58a06..b792d26 100644
--- a/modules/plugins/jboss-as/pom.xml
+++ b/modules/plugins/jboss-as/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache-v3/pom.xml b/modules/plugins/jboss-cache-v3/pom.xml
index c83611c..837852d 100644
--- a/modules/plugins/jboss-cache-v3/pom.xml
+++ b/modules/plugins/jboss-cache-v3/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jboss-cache/pom.xml b/modules/plugins/jboss-cache/pom.xml
index 421f24d..3828a6a 100644
--- a/modules/plugins/jboss-cache/pom.xml
+++ b/modules/plugins/jboss-cache/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/jmx/pom.xml b/modules/plugins/jmx/pom.xml
index 48e3f93..864f675 100644
--- a/modules/plugins/jmx/pom.xml
+++ b/modules/plugins/jmx/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/kickstart/pom.xml b/modules/plugins/kickstart/pom.xml
index 9255d09..094f451 100644
--- a/modules/plugins/kickstart/pom.xml
+++ b/modules/plugins/kickstart/pom.xml
@@ -7,7 +7,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mod-cluster/pom.xml b/modules/plugins/mod-cluster/pom.xml
index 62ffc81..54b9f53 100644
--- a/modules/plugins/mod-cluster/pom.xml
+++ b/modules/plugins/mod-cluster/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/mysql/pom.xml b/modules/plugins/mysql/pom.xml
index 14e39a3..572851e 100644
--- a/modules/plugins/mysql/pom.xml
+++ b/modules/plugins/mysql/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml
index 22db736..6b663ff 100644
--- a/modules/plugins/netservices/pom.xml
+++ b/modules/plugins/netservices/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/noop/pom.xml b/modules/plugins/noop/pom.xml
index 1f43ea4..68af26a 100644
--- a/modules/plugins/noop/pom.xml
+++ b/modules/plugins/noop/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/oracle/pom.xml b/modules/plugins/oracle/pom.xml
index dc4f4aa..ed93d10 100644
--- a/modules/plugins/oracle/pom.xml
+++ b/modules/plugins/oracle/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pattern-generator/pom.xml b/modules/plugins/pattern-generator/pom.xml
index 1d40834..5653d69 100644
--- a/modules/plugins/pattern-generator/pom.xml
+++ b/modules/plugins/pattern-generator/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/perftest/pom.xml b/modules/plugins/perftest/pom.xml
index 593a70b..f852e8a 100644
--- a/modules/plugins/perftest/pom.xml
+++ b/modules/plugins/perftest/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/platform/pom.xml b/modules/plugins/platform/pom.xml
index ef210b6..e28148c 100644
--- a/modules/plugins/platform/pom.xml
+++ b/modules/plugins/platform/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 9d6a147..0e27179 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 6ee7474..12ae83c 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/postgres/pom.xml b/modules/plugins/postgres/pom.xml
index 1e323fb..26d37b3 100644
--- a/modules/plugins/postgres/pom.xml
+++ b/modules/plugins/postgres/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-agent/pom.xml b/modules/plugins/rhq-agent/pom.xml
index e187c17..6bf549f 100644
--- a/modules/plugins/rhq-agent/pom.xml
+++ b/modules/plugins/rhq-agent/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/rhq-server/pom.xml b/modules/plugins/rhq-server/pom.xml
index 5327977..968a154 100644
--- a/modules/plugins/rhq-server/pom.xml
+++ b/modules/plugins/rhq-server/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index 23dadb6..20e41c4 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script/pom.xml b/modules/plugins/script/pom.xml
index 3772829..d31500b 100644
--- a/modules/plugins/script/pom.xml
+++ b/modules/plugins/script/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/script2/pom.xml b/modules/plugins/script2/pom.xml
index 3bec031..36ab8be 100644
--- a/modules/plugins/script2/pom.xml
+++ b/modules/plugins/script2/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/snmptrapd/pom.xml b/modules/plugins/snmptrapd/pom.xml
index ae92638..74d740b 100644
--- a/modules/plugins/snmptrapd/pom.xml
+++ b/modules/plugins/snmptrapd/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>rhq-plugins-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/modules/plugins/sshd/pom.xml b/modules/plugins/sshd/pom.xml
index 93856c9..e0a216e 100644
--- a/modules/plugins/sshd/pom.xml
+++ b/modules/plugins/sshd/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index d10ef73..3891b84 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/tomcat/pom.xml b/modules/plugins/tomcat/pom.xml
index 8cdd836..eb97008 100644
--- a/modules/plugins/tomcat/pom.xml
+++ b/modules/plugins/tomcat/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.jboss.on</groupId>
diff --git a/modules/plugins/twitter/pom.xml b/modules/plugins/twitter/pom.xml
index 52e155c..45c2544 100644
--- a/modules/plugins/twitter/pom.xml
+++ b/modules/plugins/twitter/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/validate-all-plugins/pom.xml b/modules/plugins/validate-all-plugins/pom.xml
index 1e8c6fc..63eb6ae 100644
--- a/modules/plugins/validate-all-plugins/pom.xml
+++ b/modules/plugins/validate-all-plugins/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/plugins/virt/pom.xml b/modules/plugins/virt/pom.xml
index 1c2bbca..de510c5 100644
--- a/modules/plugins/virt/pom.xml
+++ b/modules/plugins/virt/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-plugins-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/pom.xml b/modules/pom.xml
index 82d911d..8f4cf31 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -6,7 +6,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<groupId>org.rhq</groupId>
diff --git a/modules/test-utils/pom.xml b/modules/test-utils/pom.xml
index f536119..c343deb 100644
--- a/modules/test-utils/pom.xml
+++ b/modules/test-utils/pom.xml
@@ -7,7 +7,7 @@
<parent>
<artifactId>rhq-modules-parent</artifactId>
<groupId>org.rhq</groupId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
</parent>
<artifactId>test-utils</artifactId>
diff --git a/pom.xml b/pom.xml
index da1506f..b46ee9e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<groupId>org.rhq</groupId>
<artifactId>rhq-parent</artifactId>
- <version>4.7.0-SNAPSHOT</version>
+ <version>4.8.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>RHQ</name>
commit 0989c0c6cad40b787e4148d40b95418d1dd7a4cf
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:02:05 2013 -0500
Disable all the arquillian-integration submodules from building when maven.test.skip is true. Also, fix modules that depended on these modules to include them only if they are built.
(cherry picked from commit 7e9678418a8ee2683aafb395c1cc25415ab375e3)
diff --git a/modules/core/arquillian-integration/pom.xml b/modules/core/arquillian-integration/pom.xml
index 7e215a3..9637dfc 100644
--- a/modules/core/arquillian-integration/pom.xml
+++ b/modules/core/arquillian-integration/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -19,11 +19,30 @@
<name>RHQ Arquillian Integration Modules</name>
<description>parent POM for integration modules with Arquillian</description>
- <modules>
- <module>test-agent-plugin</module>
- <module>container</module>
- <module>archive</module>
- <module>suite-extension</module>
- </modules>
+
+ <profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <modules>
+ <module>test-agent-plugin</module>
+ <module>container</module>
+ <module>archive</module>
+ <module>suite-extension</module>
+ </modules>
+ </profile>
+ </profiles>
</project>
diff --git a/modules/core/plugin-test-api/pom.xml b/modules/core/plugin-test-api/pom.xml
index 9c91bc0..fc49cf3 100644
--- a/modules/core/plugin-test-api/pom.xml
+++ b/modules/core/plugin-test-api/pom.xml
@@ -1,5 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -24,59 +24,80 @@
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>test-utils</artifactId>
- <version>${project.version}</version>
- </dependency>
+ </dependencies>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-arquillian-agent-plugin-container-embedded</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-module-testng</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.powermock</groupId>
- <artifactId>powermock-api-mockito</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.container</groupId>
- <artifactId>arquillian-container-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.core</groupId>
- <artifactId>arquillian-core-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.container</groupId>
- <artifactId>arquillian-container-test-api</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.test</groupId>
- <artifactId>arquillian-test-spi</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.arquillian.testng</groupId>
- <artifactId>arquillian-testng-container</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.jboss.shrinkwrap.resolver</groupId>
- <artifactId>shrinkwrap-resolver-depchain</artifactId>
- <type>pom</type>
- </dependency>
- </dependencies>
+ <profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-arquillian-agent-plugin-container-embedded</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.core</groupId>
+ <artifactId>arquillian-core-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.container</groupId>
+ <artifactId>arquillian-container-test-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.test</groupId>
+ <artifactId>arquillian-test-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian.testng</groupId>
+ <artifactId>arquillian-testng-container</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.resolver</groupId>
+ <artifactId>shrinkwrap-resolver-depchain</artifactId>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
</project>
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index c51fb51..c4992af 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -1,5 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -23,9 +23,7 @@
<profile>
<id>default</id>
<activation>
- <property>
- <name>java.home</name>
- </property>
+ <activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>util</module>
@@ -47,6 +45,38 @@
</modules>
</profile>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>avoid.test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <modules>
+ <module>util</module>
+ <module>native-system</module>
+ <module>comm-api</module>
+ <module>dbutils</module>
+ <module>domain</module>
+ <module>plugin-api</module>
+ <module>client-api</module>
+ <module>plugin-container</module>
+ <module>gui</module>
+ <module>plugin-validator</module>
+ <module>arquillian-integration</module>
+ <module>plugin-test-api</module>
+ <module>plugin-container-itest</module>
+ </modules>
+ </profile>
+
+
<profile>
<id>plugindoc</id>
<modules>
diff --git a/modules/plugins/cassandra/pom.xml b/modules/plugins/cassandra/pom.xml
index 9888aa0..d576083 100644
--- a/modules/plugins/cassandra/pom.xml
+++ b/modules/plugins/cassandra/pom.xml
@@ -63,20 +63,6 @@
<artifactId>snakeyaml</artifactId>
<version>1.10</version>
</dependency>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
@@ -231,6 +217,39 @@
</build>
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>dev</id>
diff --git a/modules/plugins/jboss-as-5/pom.xml b/modules/plugins/jboss-as-5/pom.xml
index d9838cf..221d4cc 100644
--- a/modules/plugins/jboss-as-5/pom.xml
+++ b/modules/plugins/jboss-as-5/pom.xml
@@ -119,21 +119,6 @@
<!-- Test Deps -->
<dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
<groupId>org.jboss.spec.javax.jms</groupId>
<artifactId>jboss-jms-api_1.1_spec</artifactId>
<version>1.0.0.Final</version>
@@ -218,6 +203,39 @@
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>integration-tests</id>
<!--
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 33b2bd7..81b2322 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -99,21 +99,6 @@
<!-- === Test Deps === -->
<dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-api</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>test</scope>
- </dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-core-plugin-test-util</artifactId>
- <version>${project.version}</version>
- <scope>test</scope>
- </dependency>
-
- <dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
@@ -250,6 +235,39 @@
<profiles>
+ <profile>
+ <!--
+ This profile has been created to avoid unnecessary resolution of test dependencies during a build that
+ does not run, compile or need tests.
+ More test dependencies are to be moved here if the set of sub-dependencies is complex, references project
+ test jars, or conflicts with changing the container version.
+ -->
+ <id>test.dependencies</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-api</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-test-util</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+
<profile>
<id>java7</id>
<activation>
commit cad0a43803d781bf2ba28eab71b80f822bf2d07d
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Mon May 6 11:01:37 2013 -0500
Update test to avoid disabled managers. This is especially important for the TagManager that can be disabled via build properties.
(cherry picked from commit c9ccdbf61842dd115ce0d3067752e85dbb1db730)
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
index aa0ebd4..024e4f6 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
@@ -87,6 +87,10 @@ public class ScriptingAPIServerTest extends ScriptableAbstractEJB3Test {
//Simplification itself is unit tested separately.
for (RhqManager m : RhqManager.values()) {
+ if (!m.enabled()) {
+ continue;
+ }
+
String name = m.name();
// Only check for the TagManager if it is enabled at all
if (name.contains("TagManager") && !RhqManager.TagManager.enabled()) {
commit 5fecc675d08aa9220a163f0e35530dc6c07447b6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Mon May 6 16:20:24 2013 +0200
Add test case for Bug 911321 - [EAP 6.1] Reload operation fails in standalone mode
diff --git a/modules/plugins/jboss-as-7/pom.xml b/modules/plugins/jboss-as-7/pom.xml
index 23a02c4..33b2bd7 100644
--- a/modules/plugins/jboss-as-7/pom.xml
+++ b/modules/plugins/jboss-as-7/pom.xml
@@ -30,6 +30,7 @@
<java.tieredCompilation>-Dxxx</java.tieredCompilation>
<java.useCompressedOOPS>-Dxxx</java.useCompressedOOPS>
<rhq.internal>false</rhq.internal>
+ <as7.itest.mock.http.management.server.port>32259</as7.itest.mock.http.management.server.port>
</properties>
@@ -118,6 +119,13 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.aggregate</groupId>
+ <artifactId>jetty-all</artifactId>
+ <version>8.1.8.v20121106</version>
+ <scope>test</scope>
+ </dependency>
+
<!-- For native subsystem -->
<dependency>
<groupId>org.hyperic</groupId>
@@ -588,6 +596,7 @@
<!-- only include integration tests; normal unit tests are handled above by surefire plugin -->
<include>org/rhq/modules/plugins/jbossas7/itest/**/*Test.java</include>
<!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/StandaloneServerComponentTest.java</include>-->
+ <!--<include>org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/DomainServerComponentTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/domain/SecurityModuleOptionsTest.java</include>-->
<!--<include>org/rhq/modules/plugins/jbossas7/itest/nonpc/ManagementConnectionPersistenceTest.java</include>-->
@@ -609,6 +618,7 @@
<jboss.domain.portOffset>${jboss.domain.portOffset}</jboss.domain.portOffset>
<jboss.domain.httpManagementPort>${jboss.domain.httpManagementPort}</jboss.domain.httpManagementPort>
<settings.localRepository>${settings.localRepository}</settings.localRepository>
+ <as7.itest.mock.http.management.server.port>${as7.itest.mock.http.management.server.port}</as7.itest.mock.http.management.server.port>
</systemPropertyVariables>
</configuration>
<executions>
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java
new file mode 100644
index 0000000..9597d47
--- /dev/null
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/standalone/InterruptibleOperationsTest.java
@@ -0,0 +1,239 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.modules.plugins.jbossas7.itest.standalone;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.mockito.Mockito.when;
+import static org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper.LOG_EVENT_SOURCES_CONFIG_PROP;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.HOSTNAME;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.MANAGEMENT_CONNECTION_TIMEOUT;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.PASSWORD;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.PORT;
+import static org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration.Property.USER;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyList;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.availability.AvailabilityContext;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.operation.OperationResult;
+import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.StringUtil;
+import org.rhq.modules.plugins.jbossas7.StandaloneASComponent;
+import org.rhq.modules.plugins.jbossas7.json.Operation;
+import org.rhq.modules.plugins.jbossas7.json.Result;
+
+/**
+ * Check that management operations that might be interrupted by AS server (connection closed before the http response
+ * is sent) don't make RHQ operations fail.
+ *
+ * See https://bugzilla.redhat.com/show_bug.cgi?id=911321
+ *
+ * @author Thomas Segismont
+ */
+public class InterruptibleOperationsTest {
+
+ private static final Log LOG = LogFactory.getLog(InterruptibleOperationsTest.class);
+
+ private static final String HTTP_HOST = "localhost";
+
+ private static final int HTTP_PORT = 31159;
+
+ private static final String HTTP_PORT_VARIABLE = "as7.itest.mock.http.management.server.port";
+
+ @Mock
+ private ResourceContext resourceContext;
+
+ private StandaloneASComponent serverComponent;
+
+ private Server jettyServer;
+
+ private ExecutorService executorService;
+
+ @BeforeMethod
+ private void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ serverComponent = new TestStandaloneASComponent();
+ int httpPort = getJettyPort();
+ setupResourceContext(httpPort);
+ setupJettyServer(httpPort);
+ jettyServer.start();
+ executorService = Executors.newSingleThreadExecutor();
+ serverComponent.start(resourceContext);
+ }
+
+ private void setupJettyServer(int httpPort) {
+ jettyServer = new Server(new InetSocketAddress(HTTP_HOST, httpPort));
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath("/");
+ jettyServer.setHandler(context);
+ HttpServlet testServlet = new TestServlet();
+ context.addServlet(new ServletHolder(testServlet), "/*");
+ }
+
+ private static int getJettyPort() {
+ String httpPortVariable = System.getProperty(HTTP_PORT_VARIABLE);
+ if (StringUtil.isNotBlank(httpPortVariable)) {
+ try {
+ int port = Integer.parseInt(httpPortVariable);
+ LOG.info("Using port " + httpPortVariable + " for http server");
+ return port;
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid port variable: " + httpPortVariable);
+ }
+ }
+ LOG.info("Using default port " + String.valueOf(HTTP_PORT) + " for http server");
+ return HTTP_PORT;
+ }
+
+ private void setupResourceContext(int httpPort) {
+ when(resourceContext.getPluginConfiguration()).thenReturn(pluginConfig(httpPort));
+ when(resourceContext.getResourceKey()).thenReturn("/TestServer");
+ when(resourceContext.getSystemInformation()).thenReturn(SystemInfoFactory.createJavaSystemInfo());
+ when(resourceContext.getAvailabilityContext()).thenReturn(Mockito.mock(AvailabilityContext.class));
+ }
+
+ private Configuration pluginConfig(int httpPort) {
+ Configuration pluginConfig = new Configuration();
+ pluginConfig.setSimpleValue(HOSTNAME, "localhost");
+ pluginConfig.setSimpleValue(PORT, String.valueOf(httpPort));
+ pluginConfig.setSimpleValue(USER, "pipo");
+ pluginConfig.setSimpleValue(PASSWORD, "molo");
+ pluginConfig.setSimpleValue(MANAGEMENT_CONNECTION_TIMEOUT, "-1");
+ pluginConfig.getMap().put(LOG_EVENT_SOURCES_CONFIG_PROP, new PropertyList());
+ return pluginConfig;
+ }
+
+ @AfterMethod
+ private void tearDown() throws Exception {
+ LOG.info("Shutting down Jetty test server");
+ try {
+ if (jettyServer != null) {
+ jettyServer.stop();
+ }
+ } catch (Exception ignore) {
+ }
+ if (executorService != null) {
+ executorService.shutdownNow();
+ }
+ }
+
+ @Test(timeOut = 60 * 1000)
+ public void testReloadOperation() throws Exception {
+ OperationResult operationResult = serverComponent.invokeOperation("reload", new Configuration());
+ assertEquals(operationResult.getSimpleResult(), "Success");
+ }
+
+ @Test(timeOut = 60 * 1000)
+ public void testShutdown() throws Exception {
+ OperationResult operationResult = serverComponent.invokeOperation("shutdown", new Configuration());
+ assertEquals(operationResult.getSimpleResult(), "Success");
+ }
+
+ private class RestartJetty implements Runnable {
+ @Override
+ public void run() {
+ try {
+ jettyServer.stop();
+ } catch (Exception ignore) {
+ }
+ try {
+ Thread.sleep(SECONDS.toMillis(2));
+ } catch (Exception ignore) {
+ }
+ try {
+ jettyServer.start();
+ } catch (Exception ignore) {
+ }
+ }
+ }
+
+ private class TestServlet extends HttpServlet {
+
+ private ObjectMapper objectMapper = new ObjectMapper();
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ Operation operation = objectMapper.readValue(req.getInputStream(), Operation.class);
+ // Check if we recevied an operation which a real http management interface might interrupt
+ if (operation.getOperation().equals("reload") || operation.getOperation().equals("shutdown")) {
+ // Schedule a Jetty restart
+ executorService.submit(new RestartJetty());
+ // Then wait until Jetty is shutdown
+ try {
+ Thread.sleep(Long.MAX_VALUE);
+ } catch (InterruptedException ignore) {
+ }
+ return;
+ }
+ // Standard operation. Return simple success
+ Result result = new Result();
+ result.setOutcome("success");
+ objectMapper.writeValue(resp.getOutputStream(), result);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ doPost(req, resp);
+ }
+
+ }
+
+ // Tweak StandaloneASComponent implementation for this test case
+ private class TestStandaloneASComponent extends StandaloneASComponent {
+
+ @Override
+ public AvailabilityType getAvailability() {
+ // Avoid various management requests when component is started
+ return AvailabilityType.DOWN;
+ }
+
+ @Override
+ protected boolean waitUntilDown() throws InterruptedException {
+ // Standard implementation relies on discovery of some resource properties
+ return true;
+ }
+ }
+
+}
commit 1dba477c3fc0034a5a21960db8447fa9b43f5a56
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Fri May 3 17:10:53 2013 -0500
[BZ 959591] Add back specific ant version based on local pom variables to force the download of the dependency even if not directly used in the pom. Without this, the pom would assume that the version referred here is the version from parent poms. This can cause the submodule artifact to miss ant binaries if not already in the local maven repository.
(cherry picked from commit 2bb45d3c4c9d5edc71acf4380ce7a10a93937aae)
diff --git a/modules/enterprise/agentupdate/pom.xml b/modules/enterprise/agentupdate/pom.xml
index ddec938..3b66b92 100644
--- a/modules/enterprise/agentupdate/pom.xml
+++ b/modules/enterprise/agentupdate/pom.xml
@@ -37,12 +37,14 @@
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
+ <version>${ant.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId>
+ <version>${ant.version}</version>
<scope>provided</scope>
</dependency>
commit 17865107e38aa503c35f5a608cc1972c09bf5a73
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 3 15:01:26 2013 -0700
[BZ 958754] - d3 multi-line chart: time units should have minutes when appropriate. Added the appropriate d3 time format string and updated the nvd3 chart library neither of which fixed the issue. It appears to be an error in nvd3 chart library.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
index 1fec750..a2de9c6 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/MetricNvd3BarChartGraph.java
@@ -19,7 +19,7 @@
package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
/**
- * Contains the chart definition for a Bar Chart Graph.
+ * Contains the chart definition for a MultiLine Graph.
*
* @author Mike Thompson
*/
@@ -39,7 +39,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
*/
public native void drawJsniChart() /*-{
console.log("Draw NVD3 Bar jsni chart");
- console.time("multiChart")
+ console.time("multiChart");
var global = this,
chartId = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getChartId()(),
chartHandle = "#rChart-"+chartId,
@@ -49,7 +49,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
yAxisUnits = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getYAxisUnits()(),
xAxisLabel = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::getXAxisTitle()(),
displayDayOfWeek = global.@org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.MetricGraphData::shouldDisplayDayOfWeekInXAxisLabel()(),
- xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I %p",
+ xAxisTimeFormat = (displayDayOfWeek) ? "%a %I %p" : "%I : %M %p",
// nvd3 defines their json models a standard way (same model for other graphs)
data = function() {
@@ -63,7 +63,7 @@ public final class MetricNvd3BarChartGraph extends AbstractGraph
};
$wnd.nv.addGraph(function() {
var chart = $wnd.nv.models.multiBarChart()
- .showControls(false)
+ .showControls(true)
.tooltips(true);
chart.xAxis.axisLabel(xAxisLabel)
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css b/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
index cc40dfb..163b9a8 100755
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/nv.d3.css
@@ -18,8 +18,8 @@
.nvtooltip {
position: absolute;
background-color: rgba(255,255,255,1);
- padding: 10px;
- border: 1px solid #ddd;
+ padding: 1px;
+ border: 1px solid rgba(0,0,0,.2);
z-index: 10000;
font-family: Arial;
@@ -33,12 +33,13 @@
-moz-transition-delay: 500ms;
-webkit-transition-delay: 500ms;
- -moz-box-shadow: 4px 4px 8px rgba(0,0,0,.5);
- -webkit-box-shadow: 4px 4px 8px rgba(0,0,0,.5);
- box-shadow: 4px 4px 8px rgba(0,0,0,.5);
+ -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
+ box-shadow: 0 5px 10px rgba(0,0,0,.2);
- -moz-border-radius: 10px;
- border-radius: 10px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
pointer-events: none;
@@ -50,15 +51,29 @@
user-select: none;
}
+.nvtooltip.x-nvtooltip,
+.nvtooltip.y-nvtooltip {
+ padding: 8px;
+}
+
.nvtooltip h3 {
margin: 0;
- padding: 0;
+ padding: 4px 14px;
+ line-height: 18px;
+ font-weight: normal;
+ background-color: #f7f7f7;
text-align: center;
+
+ border-bottom: 1px solid #ebebeb;
+
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
}
.nvtooltip p {
margin: 0;
- padding: 0;
+ padding: 5px 14px;
text-align: center;
}
@@ -93,7 +108,7 @@ svg {
svg text {
- font: normal 12px sans-serif;
+ font: normal 12px Arial;
}
svg .title {
@@ -101,7 +116,8 @@ svg .title {
}
.nvd3 .nv-background {
- fill: none;
+ fill: white;
+ fill-opacity: 0;
/*
pointer-events: none;
*/
@@ -109,7 +125,7 @@ svg .title {
.nvd3.nv-noData {
font-size: 18px;
- font-weight: bolf;
+ font-weight: bold;
}
@@ -197,12 +213,10 @@ svg .title {
.nvd3 .nv-bars .negative rect {
zfill: brown;
- cursor: pointer;
}
.nvd3 .nv-bars rect {
zfill: steelblue;
- cursor: pointer;
fill-opacity: .75;
transition: fill-opacity 250ms linear;
@@ -226,10 +240,6 @@ svg .title {
fill: rgba(0,0,0,1);
}
-.nvd3 .nv-x.nv-axis text {
- transform: rotate(90);
-}
-
/**********
* Bars
@@ -302,10 +312,10 @@ svg .title {
.nvd3 .nv-groups path.nv-line {
fill: none;
stroke-width: 2.5px;
+ /*
stroke-linecap: round;
shape-rendering: geometricPrecision;
- /*
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
-webkit-transition: stroke-width 250ms linear;
@@ -318,10 +328,10 @@ svg .title {
.nvd3 .nv-groups path.nv-area {
stroke: none;
+ /*
stroke-linecap: round;
shape-rendering: geometricPrecision;
- /*
stroke-width: 2.5px;
transition: stroke-width 250ms linear;
-moz-transition: stroke-width 250ms linear;
@@ -350,8 +360,8 @@ svg .title {
}
.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point {
- fill-opacity: .5;
- stroke-opacity: .5;
+ fill-opacity: .5 !important;
+ stroke-opacity: .5 !important;
}
@@ -397,9 +407,11 @@ svg .title {
* Scatter
*/
+/* **Attempting to remove this for useVoronoi(false), need to see if it's required anywhere
.nvd3 .nv-groups .nv-point {
pointer-events: none;
}
+*/
.nvd3 .nv-groups .nv-point.hover {
stroke-width: 20px;
@@ -485,21 +497,27 @@ svg .title {
* Bullet
*/
-.nvd3.nv-bullet { font: 10px sans-serif; cursor: pointer; }
-.nvd3.nv-bullet rect { fill-opacity: .6; }
-.nvd3.nv-bullet rect:hover { fill-opacity: 1; }
+.nvd3.nv-bullet { font: 10px sans-serif; }
+.nvd3.nv-bullet .nv-measure { fill-opacity: .8; }
+.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; }
.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; }
.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; }
.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; }
.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; }
.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; }
.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; }
-.nvd3.nv-bullet .nv-measure.nv-s0 { fill: steelblue; }
-.nvd3.nv-bullet .nv-measure.nv-s1 { fill: darkblue; }
.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; }
.nvd3.nv-bullet .nv-subtitle { fill: #999; }
+.nvd3.nv-bullet .nv-range {
+ fill: #999;
+ fill-opacity: .4;
+}
+.nvd3.nv-bullet .nv-range:hover {
+ fill-opacity: .7;
+}
+
/**********
@@ -515,7 +533,7 @@ svg .title {
}
.nvd3.nv-sparklineplus .nv-hoverValue line {
- stroke: #f44;
+ stroke: #333;
stroke-width: 1.5px;
}
@@ -531,8 +549,11 @@ svg .title {
.nvd3.nv-sparklineplus .nv-xValue,
.nvd3.nv-sparklineplus .nv-yValue {
+ /*
stroke: #666;
- font-size: .5em;
+ */
+ stroke-width: 0;
+ font-size: .9em;
font-weight: normal;
}
@@ -540,6 +561,24 @@ svg .title {
stroke: #f66;
}
+.nvd3.nv-sparklineplus .nv-maxValue {
+ stroke: #2ca02c;
+ fill: #2ca02c;
+}
+
+.nvd3.nv-sparklineplus .nv-minValue {
+ stroke: #d62728;
+ fill: #d62728;
+}
+
+.nvd3.nv-sparklineplus .nv-currentValue {
+ /*
+ stroke: #444;
+ fill: #000;
+ */
+ font-weight: bold;
+ font-size: 1.1em;
+}
/**********
* historical stock
@@ -629,4 +668,35 @@ svg .title {
*/
}
+/**********
+* Parallel Coordinates
+*/
+
+.nvd3 .background path {
+ fill: none;
+ stroke: #ccc;
+ stroke-opacity: .4;
+ shape-rendering: crispEdges;
+}
+
+.nvd3 .foreground path {
+ fill: none;
+ stroke: steelblue;
+ stroke-opacity: .7;
+}
+
+.nvd3 .brush .extent {
+ fill-opacity: .3;
+ stroke: #fff;
+ shape-rendering: crispEdges;
+}
+
+.nvd3 .axis line, .axis path {
+ fill: none;
+ stroke: #000;
+ shape-rendering: crispEdges;
+}
+.nvd3 .axis text {
+ text-shadow: 0 1px 0 #fff;
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
index 2fe2c64..e405d2e 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
+++ b/modules/enterprise/gui/coregui/src/main/webapp/js/nv.d3.js
@@ -36,29 +36,34 @@ if (nv.dev) {
// Logs all arguments, and returns the last so you can test things in place
nv.log = function() {
- if (nv.dev && console.log && console.log.apply) console.log.apply(console, arguments);
+ if (nv.dev && console.log && console.log.apply)
+ console.log.apply(console, arguments)
+ else if (nv.dev && console.log && Function.prototype.bind) {
+ var log = Function.prototype.bind.call(console.log, console);
+ log.apply(console, arguments);
+ }
return arguments[arguments.length - 1];
};
nv.render = function render(step) {
- step = step || 1; // number of graphs to generate in each timout loop
+ step = step || 1; // number of graphs to generate in each timeout loop
- render.active = true;
+ nv.render.active = true;
nv.dispatch.render_start();
setTimeout(function() {
- var chart;
+ var chart, graph;
- for (var i = 0; i < step && (graph = render.queue[i]); i++) {
+ for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {
chart = graph.generate();
if (typeof graph.callback == typeof(Function)) graph.callback(chart);
nv.graphs.push(chart);
}
- render.queue.splice(0, i);
+ nv.render.queue.splice(0, i);
- if (render.queue.length) setTimeout(arguments.callee, 0);
+ if (nv.render.queue.length) setTimeout(arguments.callee, 0);
else { nv.render.active = false; nv.dispatch.render_end(); }
}, 0);
};
@@ -114,7 +119,7 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
/*****
- * A no frills tooltip implementation.
+ * A no-frills tooltip implementation.
*****/
@@ -143,39 +148,67 @@ d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {
width = parseInt(container.offsetWidth),
windowWidth = nv.utils.windowSize().width,
windowHeight = nv.utils.windowSize().height,
- scrollTop = body.scrollTop,
- scrollLeft = body.scrollLeft,
+ scrollTop = window.scrollY,
+ scrollLeft = window.scrollX,
left, top;
+ windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16;
+ windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16;
+
+ var tooltipTop = function ( Elem ) {
+ var offsetTop = top;
+ do {
+ if( !isNaN( Elem.offsetTop ) ) {
+ offsetTop += (Elem.offsetTop);
+ }
+ } while( Elem = Elem.offsetParent );
+ return offsetTop;
+ }
+
+ var tooltipLeft = function ( Elem ) {
+ var offsetLeft = left;
+ do {
+ if( !isNaN( Elem.offsetLeft ) ) {
+ offsetLeft += (Elem.offsetLeft);
+ }
+ } while( Elem = Elem.offsetParent );
+ return offsetLeft;
+ }
switch (gravity) {
case 'e':
left = pos[0] - width - dist;
top = pos[1] - (height / 2);
- if (left < scrollLeft) left = pos[0] + dist;
- if (top < scrollTop) top = scrollTop + 5;
- if (top + height > scrollTop + windowHeight) top = scrollTop - height - 5;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left;
+ if (tTop < scrollTop) top = scrollTop - tTop + top;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
break;
case 'w':
left = pos[0] + dist;
top = pos[1] - (height / 2);
- if (left + width > windowWidth) left = pos[0] - width - dist;
- if (top < scrollTop) top = scrollTop + 5;
- if (top + height > scrollTop + windowHeight) top = scrollTop - height - 5;
+ if (tLeft + width > windowWidth) left = pos[0] - width - dist;
+ if (tTop < scrollTop) top = scrollTop + 5;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop - height - 5;
break;
case 'n':
- left = pos[0] - (width / 2);
+ left = pos[0] - (width / 2) - 5;
top = pos[1] + dist;
- if (left < scrollLeft) left = scrollLeft + 5;
- if (left + width > windowWidth) left = windowWidth - width - 5;
- if (top + height > scrollTop + windowHeight) top = pos[1] - height - dist;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = scrollLeft + 5;
+ if (tLeft + width > windowWidth) left = left - width/2 + 5;
+ if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;
break;
case 's':
left = pos[0] - (width / 2);
top = pos[1] - height - dist;
- if (left < scrollLeft) left = scrollLeft + 5;
- if (left + width > windowWidth) left = windowWidth - width - 5;
- if (scrollTop > top) top = pos[1] + 20;
+ var tLeft = tooltipLeft(container);
+ var tTop = tooltipTop(container);
+ if (tLeft < scrollLeft) left = scrollLeft + 5;
+ if (tLeft + width > windowWidth) left = left - width/2 + 5;
+ if (scrollTop > tTop) top = scrollTop;
break;
}
@@ -243,7 +276,7 @@ nv.utils.windowSize = function() {
// Easy way to bind multiple functions to window.onresize
-// TODO: give a way to remove a function after its bound, other than removing alkl of them
+// TODO: give a way to remove a function after its bound, other than removing all of them
nv.utils.windowResize = function(fun){
var oldresize = window.onresize;
@@ -255,7 +288,7 @@ nv.utils.windowResize = function(fun){
// Backwards compatible way to implement more d3-like coloring of graphs.
// If passed an array, wrap it in a function which implements the old default
-// behaviour
+// behavior
nv.utils.getColor = function(color) {
if (!arguments.length) return nv.utils.defaultColor(); //if you pass in nothing, get default colors back
@@ -263,7 +296,7 @@ nv.utils.getColor = function(color) {
return function(d, i) { return d.color || color[i % color.length]; };
else
return color;
- //can't really help it if someone passes rubish as color
+ //can't really help it if someone passes rubbish as color
}
// Default color chooser uses the index of an object as before.
@@ -328,7 +361,7 @@ nv.models.axis = function() {
;
var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 60 //only used for tickLabel currently
+ , width = 75 //only used for tickLabel currently
, height = 60 //only used for tickLabel currently
, scale = d3.scale.linear()
, axisLabelText = null
@@ -337,6 +370,7 @@ nv.models.axis = function() {
, rotateLabels = 0
, rotateYLabel = true
, staggerLabels = false
+ , isOrdinal = false
, ticks = null
;
@@ -398,11 +432,11 @@ nv.models.axis = function() {
axisLabel.exit().remove();
switch (axis.orient()) {
case 'top':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
- .attr('text-anchor', 'middle')
- .attr('y', 0);
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));
axisLabel
+ .attr('text-anchor', 'middle')
+ .attr('y', 0)
.attr('x', w/2);
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -428,7 +462,7 @@ nv.models.axis = function() {
}
break;
case 'bottom':
- var xLabelMargin = 30;
+ var xLabelMargin = 36;
var maxTextWidth = 30;
var xTicks = g.selectAll('g').select("text");
if (rotateLabels%360) {
@@ -445,20 +479,22 @@ nv.models.axis = function() {
.attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })
.attr('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
}
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
- .attr('text-anchor', 'middle')
- .attr('y', xLabelMargin);
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));
axisLabel
+ .attr('text-anchor', 'middle')
+ .attr('y', xLabelMargin)
.attr('x', w/2);
if (showMaxMin) {
+ //if (showMaxMin && !isOrdinal) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
+ //.data(scale.domain())
+ .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);
axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');
axisMaxMin.exit().remove();
axisMaxMin
.attr('transform', function(d,i) {
- return 'translate(' + scale(d) + ',0)'
+ return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
})
.select('text')
.attr('dy', '.71em')
@@ -471,7 +507,9 @@ nv.models.axis = function() {
});
d3.transition(axisMaxMin)
.attr('transform', function(d,i) {
- return 'translate(' + scale.range()[i] + ',0)'
+ //return 'translate(' + scale.range()[i] + ',0)'
+ //return 'translate(' + scale(d) + ',0)'
+ return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
});
}
if (staggerLabels)
@@ -480,11 +518,11 @@ nv.models.axis = function() {
break;
case 'right':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
+ axisLabel
.attr('text-anchor', rotateYLabel ? 'middle' : 'begin')
.attr('transform', rotateYLabel ? 'rotate(90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.right,width) - 12) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
- axisLabel
+ .attr('y', rotateYLabel ? (-Math.max(margin.right,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
.attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding());
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -514,11 +552,19 @@ nv.models.axis = function() {
}
break;
case 'left':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel')
+ /*
+ //For dynamically placing the label. Can be used with dynamically-sized chart axis margins
+ var yTicks = g.selectAll('g').select("text");
+ yTicks.each(function(d,i){
+ var labelPadding = this.getBBox().width + axis.tickPadding() + 16;
+ if(labelPadding > width) width = labelPadding;
+ });
+ */
+ axisLabel.enter().append('text').attr('class', 'nv-axislabel');
+ axisLabel
.attr('text-anchor', rotateYLabel ? 'middle' : 'end')
.attr('transform', rotateYLabel ? 'rotate(-90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 12) : -10); //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
- axisLabel
+ .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart
.attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding());
if (showMaxMin) {
var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
@@ -552,27 +598,41 @@ nv.models.axis = function() {
.text(function(d) { return d });
- //check if max and min overlap other values, if so, hide the values that overlap
if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {
+ //check if max and min overlap other values, if so, hide the values that overlap
g.selectAll('g') // the g's wrapping each tick
.each(function(d,i) {
+ d3.select(this).select('text').attr('opacity', 1);
if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!
if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL
- d3.select(this).remove();
- else
- d3.select(this).select('text').remove(); // Don't remove the ZERO line!!
+ d3.select(this).attr('opacity', 0);
+
+ d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!
}
});
+
+ //if Max and Min = 0 only show min, Issue #281
+ if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0)
+ wrap.selectAll('g.nv-axisMaxMin')
+ .style('opacity', function(d,i) { return !i ? 1 : 0 });
+
}
if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {
var maxMinRange = [];
wrap.selectAll('g.nv-axisMaxMin')
.each(function(d,i) {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - this.getBBox().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
- else // i==0, min position
- maxMinRange.push(scale(d) + this.getBBox().width + 4)
+ try {
+ if (i) // i== 1, max position
+ maxMinRange.push(scale(d) - this.getBBox().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
+ else // i==0, min position
+ maxMinRange.push(scale(d) + this.getBBox().width + 4)
+ }catch (err) {
+ if (i) // i== 1, max position
+ maxMinRange.push(scale(d) - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case)
+ else // i==0, min position
+ maxMinRange.push(scale(d) + 4)
+ }
});
g.selectAll('g') // the g's wrapping each tick
.each(function(d,i) {
@@ -660,6 +720,7 @@ nv.models.axis = function() {
if (!arguments.length) return scale;
scale = _;
axis.scale(scale);
+ isOrdinal = typeof scale.rangeBands === 'function';
d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands');
return chart;
}
@@ -705,6 +766,7 @@ nv.models.historicalBar = function() {
, getY = function(d) { return d.y }
, forceX = []
, forceY = [0]
+ , padData = false
, clipEdge = true
, color = nv.utils.defaultColor()
, xDomain
@@ -726,9 +788,13 @@ nv.models.historicalBar = function() {
// Setup Scales
x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ))
- .range([0, availableWidth]);
- y .domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
+ if (padData)
+ x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
+
+ y .domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))
.range([availableHeight, 0]);
// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
@@ -846,13 +912,20 @@ nv.models.historicalBar = function() {
bars
.attr('fill', function(d,i) { return color(d, i); })
.attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - ((availableWidth / data[0].values.length) * .5)) + ',0)'; }) //TODO: better width calculations that don't assume always uniform data spacing;w
+ .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; }) //TODO: better width calculations that don't assume always uniform data spacing;w
.attr('width', (availableWidth / data[0].values.length) * .9 )
d3.transition(bars)
- .attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
- .attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });
+ //.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
+ .attr('y', function(d,i) {
+ return getY(d,i) < 0 ?
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 :
+ y(getY(d,i))
+ })
+ .attr('height', function(d,i) { return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) });
//.order(); // not sure if this makes any sense for this model
});
@@ -936,6 +1009,12 @@ nv.models.historicalBar = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -980,6 +1059,7 @@ nv.models.bullet = function() {
, width = 380
, height = 30
, tickFormat = null
+ , color = nv.utils.getColor(['#1f77b4'])
, dispatch = d3.dispatch('elementMouseover', 'elementMouseout')
;
@@ -1002,7 +1082,7 @@ nv.models.bullet = function() {
// Compute the new x-scale.
var x1 = d3.scale.linear()
- .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
+ .domain( d3.extent(d3.merge([forceX, rangez])) )
.range(reverse ? [availableWidth, 0] : [0, availableWidth]);
// Retrieve the old x-scale, if this is an update.
@@ -1013,6 +1093,11 @@ nv.models.bullet = function() {
// Stash the new scale.
this.__chart__ = x1;
+
+ var rangeMin = d3.min(rangez), //rangez[2]
+ rangeMax = d3.max(rangez), //rangez[0]
+ rangeAvg = rangez[1];
+
//------------------------------------------------------------
@@ -1024,6 +1109,12 @@ nv.models.bullet = function() {
var gEnter = wrapEnter.append('g');
var g = wrap.select('g');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg');
+ gEnter.append('rect').attr('class', 'nv-range nv-rangeMin');
+ gEnter.append('rect').attr('class', 'nv-measure');
+ gEnter.append('path').attr('class', 'nv-markerTriangle');
+
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
//------------------------------------------------------------
@@ -1032,8 +1123,118 @@ nv.models.bullet = function() {
var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
+ var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },
+ xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };
+
+
+ g.select('rect.nv-rangeMax')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))
+ .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))
+ .datum(rangeMax > 0 ? rangeMax : rangeMin)
+ /*
+ .attr('x', rangeMin < 0 ?
+ rangeMax > 0 ?
+ x1(rangeMin)
+ : x1(rangeMax)
+ : x1(0))
+ */
+
+ g.select('rect.nv-rangeAvg')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeAvg))
+ .attr('x', xp1(rangeAvg))
+ .datum(rangeAvg)
+ /*
+ .attr('width', rangeMax <= 0 ?
+ x1(rangeMax) - x1(rangeAvg)
+ : x1(rangeAvg) - x1(rangeMin))
+ .attr('x', rangeMax <= 0 ?
+ x1(rangeAvg)
+ : x1(rangeMin))
+ */
+
+ g.select('rect.nv-rangeMin')
+ .attr('height', availableHeight)
+ .attr('width', w1(rangeMax))
+ .attr('x', xp1(rangeMax))
+ .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))
+ .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))
+ .datum(rangeMax > 0 ? rangeMin : rangeMax)
+ /*
+ .attr('width', rangeMax <= 0 ?
+ x1(rangeAvg) - x1(rangeMin)
+ : x1(rangeMax) - x1(rangeAvg))
+ .attr('x', rangeMax <= 0 ?
+ x1(rangeMin)
+ : x1(rangeAvg))
+ */
+
+ g.select('rect.nv-measure')
+ .style('fill', color)
+ .attr('height', availableHeight / 3)
+ .attr('y', availableHeight / 3)
+ .attr('width', measurez < 0 ?
+ x1(0) - x1(measurez[0])
+ : x1(measurez[0]) - x1(0))
+ .attr('x', xp1(measurez))
+ .on('mouseover', function() {
+ dispatch.elementMouseover({
+ value: measurez[0],
+ label: 'Current',
+ pos: [x1(measurez[0]), availableHeight/2]
+ })
+ })
+ .on('mouseout', function() {
+ dispatch.elementMouseout({
+ value: measurez[0],
+ label: 'Current'
+ })
+ })
+
+ var h3 = availableHeight / 6;
+ if (markerz[0]) {
+ g.selectAll('path.nv-markerTriangle')
+ .attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' })
+ .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')
+ .on('mouseover', function() {
+ dispatch.elementMouseover({
+ value: markerz[0],
+ label: 'Previous',
+ pos: [x1(markerz[0]), availableHeight/2]
+ })
+ })
+ .on('mouseout', function() {
+ dispatch.elementMouseout({
+ value: markerz[0],
+ label: 'Previous'
+ })
+ });
+ } else {
+ g.selectAll('path.nv-markerTriangle').remove();
+ }
+
+
+ wrap.selectAll('.nv-range')
+ .on('mouseover', function(d,i) {
+ var label = !i ? "Maximum" : i == 1 ? "Mean" : "Minimum";
+
+ dispatch.elementMouseover({
+ value: d,
+ label: label,
+ pos: [x1(d), availableHeight/2]
+ })
+ })
+ .on('mouseout', function(d,i) {
+ var label = !i ? "Maximum" : i == 1 ? "Mean" : "Minimum";
+ dispatch.elementMouseout({
+ value: d,
+ label: label
+ })
+ })
+/* // THIS IS THE PREVIOUS BULLET IMPLEMENTATION, WILL REMOVE SHORTLY
// Update the range rects.
var range = g.selectAll('rect.nv-range')
.data(rangez);
@@ -1069,6 +1270,7 @@ nv.models.bullet = function() {
measure.enter().append('rect')
.attr('class', function(d, i) { return 'nv-measure nv-s' + i; })
+ .style('fill', function(d,i) { return color(d,i ) })
.attr('width', w0)
.attr('height', availableHeight / 3)
.attr('x', reverse ? x0 : 0)
@@ -1119,13 +1321,14 @@ nv.models.bullet = function() {
});
d3.transition(marker)
- .attr('transform', function(d) { return 'translate(' + x1(d) + ',' + (availableHeight / 2) + ')' });
+ .attr('transform', function(d) { return 'translate(' + (x1(d) - x1(0)) + ',' + (availableHeight / 2) + ')' });
marker.exit().remove();
+*/
});
- d3.timer.flush();
+ // d3.timer.flush(); // Not needed?
return chart;
}
@@ -1199,6 +1402,12 @@ nv.models.bullet = function() {
return chart;
};
+ chart.color = function(_) {
+ if (!arguments.length) return color;
+ color = nv.utils.getColor(_);
+ return chart;
+ };
+
//============================================================
@@ -1271,9 +1480,7 @@ nv.models.bulletChart = function() {
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
- /*
- // Disabled until I figure out a better way to check for no data with the bullet chart
- if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
+ if (!d || !ranges.call(this, d, i)) {
var noDataText = container.selectAll('.nv-noData').data([noData]);
noDataText.enter().append('text')
@@ -1283,14 +1490,13 @@ nv.models.bulletChart = function() {
noDataText
.attr('x', margin.left + availableWidth / 2)
- .attr('y', margin.top + availableHeight / 2)
+ .attr('y', 18 + margin.top + availableHeight / 2)
.text(function(d) { return d });
return chart;
} else {
container.selectAll('.nv-noData').remove();
}
- */
//------------------------------------------------------------
@@ -1382,7 +1588,7 @@ nv.models.bulletChart = function() {
// Update the tick groups.
var tick = g.selectAll('g.nv-tick')
- .data(x1.ticks( availableWidth / 100 ), function(d) {
+ .data(x1.ticks( availableWidth / 50 ), function(d) {
return this.textContent || format(d);
});
@@ -1467,6 +1673,8 @@ nv.models.bulletChart = function() {
chart.dispatch = dispatch;
chart.bullet = bullet;
+ d3.rebind(chart, bullet, 'color');
+
// left, right, top, bottom
chart.orient = function(x) {
if (!arguments.length) return orient;
@@ -1577,13 +1785,15 @@ nv.models.cumulativeLineChart = function() {
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, id = lines.id()
+ , state = { index: 0, rescaleY: rescaleY }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -1610,24 +1820,32 @@ nv.models.cumulativeLineChart = function() {
nv.tooltip.show([left, top], content, null, null, offsetElement);
};
-
+/*
+ //Moved to see if we can get better behavior to fix issue #315
var indexDrag = d3.behavior.drag()
.on('dragstart', dragStart)
.on('drag', dragMove)
.on('dragend', dragEnd);
- function dragStart(d,i) {}
+ function dragStart(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'ew-resize');
+ }
function dragMove(d,i) {
d.x += d3.event.dx;
d.i = Math.round(dx.invert(d.x));
d3.select(this).attr('transform', 'translate(' + dx(d.i) + ',0)');
+ chart.update();
}
function dragEnd(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'auto');
chart.update();
}
+*/
//============================================================
@@ -1646,6 +1864,48 @@ nv.models.cumulativeLineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
+
+ var indexDrag = d3.behavior.drag()
+ .on('dragstart', dragStart)
+ .on('drag', dragMove)
+ .on('dragend', dragEnd);
+
+
+ function dragStart(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'ew-resize');
+ }
+
+ function dragMove(d,i) {
+ index.x = d3.event.x;
+ index.i = Math.round(dx.invert(index.x));
+ updateZero();
+ }
+
+ function dragEnd(d,i) {
+ d3.select(chart.container)
+ .style('cursor', 'auto');
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+ }
+
+
+
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -1684,6 +1944,9 @@ nv.models.cumulativeLineChart = function() {
.map(function(series,i) {
var initialDomain = d3.extent(series.values, lines.y());
+ //account for series being disabled when losing 95% or more
+ if (initialDomain[0] < -.95) initialDomain[0] = -.95;
+
return [
(initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
(initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
@@ -1720,6 +1983,7 @@ nv.models.cumulativeLineChart = function() {
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
+ gEnter.append('g').attr('class', 'nv-background');
gEnter.append('g').attr('class', 'nv-linesWrap');
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
@@ -1771,9 +2035,30 @@ nv.models.cumulativeLineChart = function() {
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+ // Show error if series goes below 100%
+ var tempDisabled = data.filter(function(d) { return d.tempDisabled });
+
+ wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
+ if (tempDisabled.length) {
+ wrap.append('text').attr('class', 'tempDisabled')
+ .attr('x', availableWidth / 2)
+ .attr('y', '-.71em')
+ .style('text-anchor', 'end')
+ .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
+ }
+
+
+
//------------------------------------------------------------
// Main Chart Component(s)
+ gEnter.select('.nv-background')
+ .append('rect');
+
+ g.select('.nv-background rect')
+ .attr('width', availableWidth)
+ .attr('height', availableHeight);
+
lines
//.x(function(d) { return d.x })
.y(function(d) { return d.display.y })
@@ -1781,14 +2066,15 @@ nv.models.cumulativeLineChart = function() {
.height(availableHeight)
.color(data.map(function(d,i) {
return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled }));
var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
+ .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
- d3.transition(linesWrap).call(lines);
+ //d3.transition(linesWrap).call(lines);
+ linesWrap.call(lines);
var indexLine = linesWrap.selectAll('.nv-indexLine')
@@ -1812,7 +2098,8 @@ nv.models.cumulativeLineChart = function() {
xAxis
.scale(x)
- .ticks( availableWidth / 100 )
+ //Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)
+ .ticks( Math.min(data[0].values.length,availableWidth/70) )
.tickSize(-availableHeight, 0);
g.select('.nv-x.nv-axis')
@@ -1836,11 +2123,46 @@ nv.models.cumulativeLineChart = function() {
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
+
+ function updateZero() {
+ indexLine
+ .data([index]);
+
+ chart.update();
+ }
+
+ g.select('.nv-background rect')
+ .on('click', function() {
+ index.x = d3.mouse(this)[0];
+ index.i = Math.round(dx.invert(index.x));
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+
+ updateZero();
+ });
+
+ lines.dispatch.on('elementClick', function(e) {
+ index.i = e.pointIndex;
+ index.x = dx(index.i);
+
+ // update state and send stateChange with new index
+ state.index = index.i;
+ dispatch.stateChange(state);
+
+ updateZero();
+ });
+
controls.dispatch.on('legendClick', function(d,i) {
d.disabled = !d.disabled;
rescaleY = !d.disabled;
- selection.transition().call(chart);
+ state.rescaleY = rescaleY;
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ selection.call(chart);
});
@@ -1855,7 +2177,11 @@ nv.models.cumulativeLineChart = function() {
});
}
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ selection.call(chart);
});
/*
@@ -1875,6 +2201,37 @@ nv.models.cumulativeLineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+
+ if (typeof e.index !== 'undefined') {
+ index.i = e.index;
+ index.x = dx(index.i);
+
+ state.index = e.index;
+
+ indexLine
+ .data([index]);
+ }
+
+
+ if (typeof e.rescaleY !== 'undefined') {
+ rescaleY = e.rescaleY;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
});
@@ -1944,6 +2301,12 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.rescaleY = function(_) {
+ if (!arguments.length) return rescaleY;
+ rescaleY = _
+ return rescaleY;
+ };
+
chart.showControls = function(_) {
if (!arguments.length) return showControls;
showControls = _;
@@ -1968,6 +2331,18 @@ nv.models.cumulativeLineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -1986,16 +2361,20 @@ nv.models.cumulativeLineChart = function() {
return data.map(function(line, i) {
var v = lines.y()(line.values[idx], idx);
+ //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
+ if (v < -.95) {
+ //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
+ line.tempDisabled = true;
+ return line;
+ }
+
+ line.tempDisabled = false;
+
line.values = line.values.map(function(point, pointIndex) {
point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };
return point;
})
- /*
- TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
- if (v < -.9) {
- //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically currect till it hits 100)
- }
- */
+
return line;
})
}
@@ -2027,6 +2406,7 @@ nv.models.discreteBar = function() {
, xDomain
, yDomain
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
+ , rectClass = 'discreteBar'
;
//============================================================
@@ -2128,7 +2508,7 @@ nv.models.discreteBar = function() {
var barsEnter = bars.enter().append('g')
.attr('transform', function(d,i,j) {
- return 'translate(' + x(getX(d,i)) + ', ' + y(0) + ')'
+ return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'
})
.on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here
d3.select(this).classed('hover', true);
@@ -2180,13 +2560,13 @@ nv.models.discreteBar = function() {
barsEnter.append('rect')
.attr('height', 0)
- .attr('width', x.rangeBand() / data.length )
+ .attr('width', x.rangeBand() * .9 / data.length )
if (showValues) {
barsEnter.append('text')
.attr('text-anchor', 'middle')
bars.select('text')
- .attr('x', x.rangeBand() / 2)
+ .attr('x', x.rangeBand() * .9 / 2)
.attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })
.text(function(d,i) { return valueFormat(getY(d,i)) });
} else {
@@ -2198,16 +2578,24 @@ nv.models.discreteBar = function() {
.style('fill', function(d,i) { return d.color || color(d,i) })
.style('stroke', function(d,i) { return d.color || color(d,i) })
.select('rect')
- .attr('width', x.rangeBand() / data.length);
+ .attr('class', rectClass)
+ .attr('width', x.rangeBand() * .9 / data.length);
d3.transition(bars)
//.delay(function(d,i) { return i * 1200 / data[0].values.length })
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ', ' + (getY(d,i) < 0 ? y(0) : y(getY(d,i))) + ')'
+ .attr('transform', function(d,i) {
+ var left = x(getX(d,i)) + x.rangeBand() * .05,
+ top = getY(d,i) < 0 ?
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 : //make 1 px positive bars show up above y=0
+ y(getY(d,i));
+
+ return 'translate(' + left + ', ' + top + ')'
})
- .select('rect')
- .attr('height', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
- });
+ .select('rect')
+ .attr('height', function(d,i) {
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)) || 1)
+ });
//store old scales for use in transitions on update
@@ -2313,6 +2701,11 @@ nv.models.discreteBar = function() {
return chart;
};
+ chart.rectClass= function(_) {
+ if (!arguments.length) return rectClass;
+ rectClass = _;
+ return chart;
+ }
//============================================================
@@ -2343,7 +2736,7 @@ nv.models.discreteBarChart = function() {
, x
, y
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate')
;
xAxis
@@ -2388,7 +2781,7 @@ nv.models.discreteBarChart = function() {
- margin.top - margin.bottom;
- chart.update = function() { selection.transition().call(chart); };
+ chart.update = function() { dispatch.beforeUpdate(); selection.transition().call(chart); };
chart.container = this;
@@ -2486,10 +2879,11 @@ nv.models.discreteBarChart = function() {
var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
- if (staggerLabels)
+ if (staggerLabels) {
xTicks
.selectAll('text')
- .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '0' : '12') + ')' })
+ .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })
+ }
yAxis
.scale(y)
@@ -2753,7 +3147,6 @@ nv.models.distribution = function() {
return chart;
}
-
nv.models.indentedTree = function() {
//============================================================
@@ -2766,6 +3159,7 @@ nv.models.indentedTree = function() {
, color = nv.utils.defaultColor()
, id = Math.floor(Math.random() * 10000)
, header = true
+ , filterZero = false
, noData = "No Data Available."
, childIndent = 20
, columns = [{key:'key', label: 'Name', type:'text'}] //TODO: consider functions like chart.addColumn, chart.removeColumn, instead of a block like this
@@ -2777,30 +3171,32 @@ nv.models.indentedTree = function() {
//============================================================
+ var idx = 0;
function chart(selection) {
selection.each(function(data) {
- var i = 0,
- depth = 1;
+ var depth = 1,
+ container = d3.select(this);
var tree = d3.layout.tree()
.children(function(d) { return d.values })
.size([height, childIndent]); //Not sure if this is needed now that the result is HTML
- chart.update = function() { selection.transition().call(chart) };
- chart.container = this;
+ chart.update = function() { container.transition().duration(600).call(chart) };
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
-
- if (!data[0].key) data[0].key = noData;
+ if (!data[0]) data[0] = {key: noData};
//------------------------------------------------------------
var nodes = tree.nodes(data[0]);
+ // nodes.map(function(d) {
+ // d.id = i++;
+ // })
//------------------------------------------------------------
// Setup containers and skeleton of chart
@@ -2830,7 +3226,7 @@ nv.models.indentedTree = function() {
var tbody = table.selectAll('tbody')
- .data(function(d) {return d });
+ .data(function(d) { return d });
tbody.enter().append('tbody');
@@ -2842,12 +3238,12 @@ nv.models.indentedTree = function() {
// Update the nodes…
var node = tbody.selectAll('tr')
- .data(function(d) { return d }, function(d) { return d.id || (d.id == ++i)});
+ // .data(function(d) { return d; }, function(d) { return d.id || (d.id == ++i)});
+ .data(function(d) { return d.filter(function(d) { return (filterZero && !d.children) ? filterZero(d) : true; } )}, function(d,i) { return d.id || (d.id || ++idx)});
//.style('display', 'table-row'); //TODO: see if this does anything
node.exit().remove();
-
node.select('img.nv-treeicon')
.attr('src', icon)
.classed('folded', folded);
@@ -2880,22 +3276,24 @@ nv.models.indentedTree = function() {
.text(function(d) { return column.format ? column.format(d) :
(d[column.key] || '-') });
- if (column.showCount)
+ if (column.showCount) {
nodeName.append('span')
- .attr('class', 'nv-childrenCount')
- .text(function(d) {
- return ((d.values && d.values.length) || (d._values && d._values.length)) ?
- '(' + ((d.values && d.values.length) || (d._values && d._values.length)) + ')'
- : ''
- });
+ .attr('class', 'nv-childrenCount');
+ node.selectAll('span.nv-childrenCount').text(function(d) {
+ return ((d.values && d.values.length) || (d._values && d._values.length)) ? //If this is a parent
+ '(' + ((d.values && (d.values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length)) //If children are in values check its children and filter
+ || (d._values && d._values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length) //Otherwise, do the same, but with the other name, _values...
+ || 0) + ')' //This is the catch-all in case there are no children after a filter
+ : '' //If this is not a parent, just give an empty string
+ });
+ }
if (column.click)
nodeName.select('span').on('click', column.click);
});
-
node
.order()
.on('click', function(d) {
@@ -3031,6 +3429,12 @@ nv.models.indentedTree = function() {
return chart;
};
+ chart.filterZero = function(_) {
+ if (!arguments.length) return filterZero;
+ filterZero = _;
+ return chart;
+ };
+
chart.columns = function(_) {
if (!arguments.length) return columns;
columns = _;
@@ -3059,8 +3463,7 @@ nv.models.indentedTree = function() {
return chart;
-}
-nv.models.legend = function() {
+};nv.models.legend = function() {
//============================================================
// Public Variables with Default Settings
@@ -3270,24 +3673,24 @@ nv.models.line = function() {
// Public Variables with Default Settings
//------------------------------------------------------------
+ var scatter = nv.models.scatter()
+ ;
+
var margin = {top: 0, right: 0, bottom: 0, left: 0}
, width = 960
, height = 500
, color = nv.utils.defaultColor() // a function that returns a color
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID incase user doesn't select one
, getX = function(d) { return d.x } // accessor to get the x value from a data point
, getY = function(d) { return d.y } // accessor to get the y value from a data point
- , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continous when it is not defined
+ , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined
, isArea = function(d) { return d.area } // decides if a line is an area or just a line
, clipEdge = false // if true, masks lines within x and y scale
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, interpolate = "linear" // controls the line interpolation
- , scatter = nv.models.scatter()
;
scatter
- .id(id)
.size(16) // default size
.sizeDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
;
@@ -3354,16 +3757,16 @@ nv.models.line = function() {
defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
+ .attr('id', 'nv-edge-clip-' + scatter.id())
.append('rect');
- wrap.select('#nv-edge-clip-' + id + ' rect')
+ wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
.attr('width', availableWidth)
.attr('height', availableHeight);
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
+ g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
scatterWrap
- .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
+ .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
@@ -3474,7 +3877,7 @@ nv.models.line = function() {
chart.dispatch = scatter.dispatch;
chart.scatter = scatter;
- d3.rebind(chart, scatter, 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius');
+ d3.rebind(chart, scatter, 'id', 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius', 'padData');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -3524,12 +3927,6 @@ nv.models.line = function() {
return chart;
};
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
chart.interpolate = function(_) {
if (!arguments.length) return interpolate;
interpolate = _;
@@ -3566,6 +3963,7 @@ nv.models.lineChart = function() {
, legend = nv.models.legend()
;
+//set margin.right to 23 to fit dates on the x-axis within the chart
var margin = {top: 30, right: 20, bottom: 50, left: 60}
, color = nv.utils.defaultColor()
, width = null
@@ -3578,13 +3976,15 @@ nv.models.lineChart = function() {
}
, x
, y
+ , state = {}
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -3637,6 +4037,19 @@ nv.models.lineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -3770,6 +4183,9 @@ nv.models.lineChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -3789,6 +4205,20 @@ nv.models.lineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
});
@@ -3876,6 +4306,18 @@ nv.models.lineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -3917,16 +4359,23 @@ nv.models.linePlusBarChart = function() {
, x
, y1
, y2
+ , state = {}
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
+ bars
+ .padData(true)
+ ;
lines
.clipEdge(false)
+ .padData(true)
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
+ .highlightZero(false)
;
y1Axis
.orient('left')
@@ -3943,14 +4392,15 @@ nv.models.linePlusBarChart = function() {
//------------------------------------------------------------
var showTooltip = function(e, offsetElement) {
- var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
- top = e.pos[1] + ( offsetElement.offsetTop || 0),
- x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
- y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
- content = tooltip(e.series.key, x, y, e, chart);
+ var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
+ top = e.pos[1] + ( offsetElement.offsetTop || 0),
+ x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
+ y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
+ content = tooltip(e.series.key, x, y, e, chart);
- nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
- };
+ nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
+ }
+ ;
//------------------------------------------------------------
@@ -3969,6 +4419,19 @@ nv.models.linePlusBarChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -3997,51 +4460,19 @@ nv.models.linePlusBarChart = function() {
//------------------------------------------------------------
// Setup Scales
- x = xAxis.scale();
- y1 = bars.yScale();
- y2 = lines.yScale();
-
var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
+ //x = xAxis.scale();
+ x = dataLines.filter(function(d) { return !d.disabled; }).length && dataLines.filter(function(d) { return !d.disabled; })[0].values.length ? lines.xScale() : bars.xScale();
+ //x = dataLines.filter(function(d) { return !d.disabled; }).length ? lines.xScale() : bars.xScale(); //old code before change above
+ y1 = bars.yScale();
+ y2 = lines.yScale();
- //TODO: try to remove x scale computation from this layer
-
- var series1 = data.filter(function(d) { return !d.disabled && d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
+ //------------------------------------------------------------
- var series2 = data.filter(function(d) { return !d.disabled && !d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .range([0, availableWidth]);
-
-
-
- /*
- x .domain(d3.extent(d3.merge(data.map(function(d) { return d.values })), getX ))
- .range([0, availableWidth]);
-
- y1 .domain(d3.extent(d3.merge(dataBars), function(d) { return d.y } ))
- .range([availableHeight, 0]);
-
- y2 .domain(d3.extent(d3.merge(dataLines), function(d) { return d.y } ))
- .range([availableHeight, 0]);
- */
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
+ //------------------------------------------------------------
+ // Setup containers and skeleton of chart
var wrap = d3.select(this).selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
@@ -4111,7 +4542,7 @@ nv.models.linePlusBarChart = function() {
.datum(dataBars.length ? dataBars : [{values:[]}])
var linesWrap = g.select('.nv-linesWrap')
- .datum(!dataLines[0].disabled ? dataLines : [{values:[]}] );
+ .datum(dataLines[0] && !dataLines[0].disabled ? dataLines : [{values:[]}] );
//.datum(!dataLines[0].disabled ? dataLines : [{values:dataLines[0].values.map(function(d) { return [d[0], null] }) }] );
d3.transition(barsWrap).call(bars);
@@ -4124,6 +4555,7 @@ nv.models.linePlusBarChart = function() {
// Setup Axes
xAxis
+ .scale(x)
.ticks( availableWidth / 100 )
.tickSize(-availableHeight, 0);
@@ -4150,7 +4582,8 @@ nv.models.linePlusBarChart = function() {
g.select('.nv-y2.nv-axis')
.style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
+ .attr('transform', 'translate(' + availableWidth + ',0)');
+ //.attr('transform', 'translate(' + x.range()[1] + ',0)');
d3.transition(g.select('.nv-y2.nv-axis'))
.call(y2Axis);
@@ -4173,6 +4606,9 @@ nv.models.linePlusBarChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -4180,6 +4616,21 @@ nv.models.linePlusBarChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -4297,6 +4748,18 @@ nv.models.linePlusBarChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -4527,33 +4990,614 @@ nv.models.lineWithFocusChart = function() {
//------------------------------------------------------------
- /*
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
+ /*
+ var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
+ .datum(data.filter(function(d) { return !d.disabled }))
+
+ d3.transition(focusLinesWrap).call(lines);
+ */
+
+
+ //------------------------------------------------------------
+ // Setup Main (Focus) Axes
+
+ xAxis
+ .scale(x)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight1, 0);
+
+ yAxis
+ .scale(y)
+ .ticks( availableHeight1 / 36 )
+ .tickSize( -availableWidth, 0);
+
+ g.select('.nv-focus .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + availableHeight1 + ')');
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Brush
+
+ brush
+ .x(x2)
+ .on('brush', onBrush);
+
+ if (brushExtent) brush.extent(brushExtent);
+
+ var brushBG = g.select('.nv-brushBackground').selectAll('g')
+ .data([brushExtent || brush.extent()])
+
+ var brushBGenter = brushBG.enter()
+ .append('g');
+
+ brushBGenter.append('rect')
+ .attr('class', 'left')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight2);
+
+ brushBGenter.append('rect')
+ .attr('class', 'right')
+ .attr('x', 0)
+ .attr('y', 0)
+ .attr('height', availableHeight2);
+
+ gBrush = g.select('.nv-x.nv-brush')
+ .call(brush);
+ gBrush.selectAll('rect')
+ //.attr('y', -5)
+ .attr('height', availableHeight2);
+ gBrush.selectAll('.resize').append('path').attr('d', resizePath);
+
+ onBrush();
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Secondary (Context) Axes
+
+ x2Axis
+ .scale(x2)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight2, 0);
+
+ g.select('.nv-context .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ d3.transition(g.select('.nv-context .nv-x.nv-axis'))
+ .call(x2Axis);
+
+
+ y2Axis
+ .scale(y2)
+ .ticks( availableHeight2 / 36 )
+ .tickSize( -availableWidth, 0);
+
+ d3.transition(g.select('.nv-context .nv-y.nv-axis'))
+ .call(y2Axis);
+
+ g.select('.nv-context .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+
+ //------------------------------------------------------------
+
+
+ //============================================================
+ // Event Handling/Dispatching (in chart's scope)
+ //------------------------------------------------------------
+
+ legend.dispatch.on('legendClick', function(d,i) {
+ d.disabled = !d.disabled;
+
+ if (!data.filter(function(d) { return !d.disabled }).length) {
+ data.map(function(d) {
+ d.disabled = false;
+ wrap.selectAll('.nv-series').classed('disabled', false);
+ return d;
+ });
+ }
+
+ selection.transition().call(chart);
+ });
+
+ dispatch.on('tooltipShow', function(e) {
+ if (tooltips) showTooltip(e, that.parentNode);
+ });
+
+ //============================================================
+
+
+ //============================================================
+ // Functions
+ //------------------------------------------------------------
+
+ // Taken from crossfilter (http://square.github.com/crossfilter/)
+ function resizePath(d) {
+ var e = +(d == 'e'),
+ x = e ? 1 : -1,
+ y = availableHeight2 / 3;
+ return 'M' + (.5 * x) + ',' + y
+ + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)
+ + 'V' + (2 * y - 6)
+ + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)
+ + 'Z'
+ + 'M' + (2.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8)
+ + 'M' + (4.5 * x) + ',' + (y + 8)
+ + 'V' + (2 * y - 8);
+ }
+
+
+ function updateBrushBG() {
+ if (!brush.empty()) brush.extent(brushExtent);
+ brushBG
+ .data([brush.empty() ? x2.domain() : brushExtent])
+ .each(function(d,i) {
+ var leftWidth = x2(d[0]) - x.range()[0],
+ rightWidth = x.range()[1] - x2(d[1]);
+ d3.select(this).select('.left')
+ .attr('width', leftWidth < 0 ? 0 : leftWidth);
+
+ d3.select(this).select('.right')
+ .attr('x', x2(d[1]))
+ .attr('width', rightWidth < 0 ? 0 : rightWidth);
+ });
+ }
+
+
+ function onBrush() {
+ brushExtent = brush.empty() ? null : brush.extent();
+ extent = brush.empty() ? x2.domain() : brush.extent();
+
+
+ dispatch.brush({extent: extent, brush: brush});
+
+
+ updateBrushBG();
+
+ // Update Main (Focus)
+ var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
+ .datum(
+ data
+ .filter(function(d) { return !d.disabled })
+ .map(function(d,i) {
+ return {
+ key: d.key,
+ values: d.values.filter(function(d,i) {
+ return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
+ })
+ }
+ })
+ );
+ d3.transition(focusLinesWrap).call(lines);
+
+
+ // Update Main (Focus) Axes
+ d3.transition(g.select('.nv-focus .nv-x.nv-axis'))
+ .call(xAxis);
+ d3.transition(g.select('.nv-focus .nv-y.nv-axis'))
+ .call(yAxis);
+ }
+
+ //============================================================
+
+
+ });
+
+ return chart;
+ }
+
+
+ //============================================================
+ // Event Handling/Dispatching (out of chart's scope)
+ //------------------------------------------------------------
+
+ lines.dispatch.on('elementMouseover.tooltip', function(e) {
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
+ dispatch.tooltipShow(e);
+ });
+
+ lines.dispatch.on('elementMouseout.tooltip', function(e) {
+ dispatch.tooltipHide(e);
+ });
+
+ dispatch.on('tooltipHide', function() {
+ if (tooltips) nv.tooltip.cleanup();
+ });
+
+ //============================================================
+
+
+ //============================================================
+ // Expose Public Variables
+ //------------------------------------------------------------
+
+ // expose chart's sub-components
+ chart.dispatch = dispatch;
+ chart.legend = legend;
+ chart.lines = lines;
+ chart.lines2 = lines2;
+ chart.xAxis = xAxis;
+ chart.yAxis = yAxis;
+ chart.x2Axis = x2Axis;
+ chart.y2Axis = y2Axis;
+
+ d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
+
+ chart.x = function(_) {
+ if (!arguments.length) return lines.x;
+ lines.x(_);
+ lines2.x(_);
+ return chart;
+ };
+
+ chart.y = function(_) {
+ if (!arguments.length) return lines.y;
+ lines.y(_);
+ lines2.y(_);
+ return chart;
+ };
+
+ chart.margin = function(_) {
+ if (!arguments.length) return margin;
+ margin.top = typeof _.top != 'undefined' ? _.top : margin.top;
+ margin.right = typeof _.right != 'undefined' ? _.right : margin.right;
+ margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;
+ margin.left = typeof _.left != 'undefined' ? _.left : margin.left;
+ return chart;
+ };
+
+ chart.margin2 = function(_) {
+ if (!arguments.length) return margin2;
+ margin2 = _;
+ return chart;
+ };
+
+ chart.width = function(_) {
+ if (!arguments.length) return width;
+ width = _;
+ return chart;
+ };
+
+ chart.height = function(_) {
+ if (!arguments.length) return height;
+ height = _;
+ return chart;
+ };
+
+ chart.height2 = function(_) {
+ if (!arguments.length) return height2;
+ height2 = _;
+ return chart;
+ };
+
+ chart.color = function(_) {
+ if (!arguments.length) return color;
+ color =nv.utils.getColor(_);
+ legend.color(color);
+ return chart;
+ };
+
+ chart.showLegend = function(_) {
+ if (!arguments.length) return showLegend;
+ showLegend = _;
+ return chart;
+ };
+
+ chart.tooltips = function(_) {
+ if (!arguments.length) return tooltips;
+ tooltips = _;
+ return chart;
+ };
+
+ chart.tooltipContent = function(_) {
+ if (!arguments.length) return tooltip;
+ tooltip = _;
+ return chart;
+ };
+
+ chart.interpolate = function(_) {
+ if (!arguments.length) return lines.interpolate();
+ lines.interpolate(_);
+ lines2.interpolate(_);
+ return chart;
+ };
+
+ chart.noData = function(_) {
+ if (!arguments.length) return noData;
+ noData = _;
+ return chart;
+ };
+
+ // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
+ chart.xTickFormat = function(_) {
+ if (!arguments.length) return xAxis.tickFormat();
+ xAxis.tickFormat(_);
+ x2Axis.tickFormat(_);
+ return chart;
+ };
+
+ chart.yTickFormat = function(_) {
+ if (!arguments.length) return yAxis.tickFormat();
+ yAxis.tickFormat(_);
+ y2Axis.tickFormat(_);
+ return chart;
+ };
+
+ //============================================================
+
+
+ return chart;
+}
+
+nv.models.linePlusBarWithFocusChart = function() {
+
+ //============================================================
+ // Public Variables with Default Settings
+ //------------------------------------------------------------
+
+ var lines = nv.models.line()
+ , lines2 = nv.models.line()
+ , bars = nv.models.historicalBar()
+ , bars2 = nv.models.historicalBar()
+ , xAxis = nv.models.axis()
+ , x2Axis = nv.models.axis()
+ , y1Axis = nv.models.axis()
+ , y2Axis = nv.models.axis()
+ , y3Axis = nv.models.axis()
+ , y4Axis = nv.models.axis()
+ , legend = nv.models.legend()
+ , brush = d3.svg.brush()
+ ;
+
+ var margin = {top: 30, right: 30, bottom: 30, left: 60}
+ , margin2 = {top: 0, right: 30, bottom: 20, left: 60}
+ , width = null
+ , height = null
+ , height2 = 100
+ , getX = function(d) { return d.x }
+ , getY = function(d) { return d.y }
+ , color = nv.utils.defaultColor()
+ , showLegend = true
+ , extent
+ , brushExtent = null
+ , tooltips = true
+ , tooltip = function(key, x, y, e, graph) {
+ return '<h3>' + key + '</h3>' +
+ '<p>' + y + ' at ' + x + '</p>';
+ }
+ , x
+ , x2
+ , y1
+ , y2
+ , y3
+ , y4
+ , noData = "No Data Available."
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush')
+ ;
+
+ lines
+ .clipEdge(true)
+ ;
+ lines2
+ .interactive(false)
+ ;
+ xAxis
+ .orient('bottom')
+ .tickPadding(5)
+ ;
+ y1Axis
+ .orient('left')
+ ;
+ y2Axis
+ .orient('right')
+ ;
+ x2Axis
+ .orient('bottom')
+ .tickPadding(5)
+ ;
+ y3Axis
+ .orient('left')
+ ;
+ y4Axis
+ .orient('right')
+ ;
+
+ //============================================================
+
+
+ //============================================================
+ // Private Variables
+ //------------------------------------------------------------
+
+ var showTooltip = function(e, offsetElement) {
+ if (extent) {
+ e.pointIndex += Math.ceil(extent[0]);
+ }
+ var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
+ top = e.pos[1] + ( offsetElement.offsetTop || 0),
+ x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),
+ y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),
+ content = tooltip(e.series.key, x, y, e, chart);
+
+ nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
+ };
+
+ //------------------------------------------------------------
+
+
+
+ function chart(selection) {
+ selection.each(function(data) {
+ var container = d3.select(this),
+ that = this;
+
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
+ - margin.left - margin.right,
+ availableHeight1 = (height || parseInt(container.style('height')) || 400)
+ - margin.top - margin.bottom - height2,
+ availableHeight2 = height2 - margin2.top - margin2.bottom;
+
+ chart.update = function() { chart(selection) };
+ chart.container = this;
+
+
+ //------------------------------------------------------------
+ // Display No Data message if there's nothing to show.
+
+ if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {
+ var noDataText = container.selectAll('.nv-noData').data([noData]);
+
+ noDataText.enter().append('text')
+ .attr('class', 'nvd3 nv-noData')
+ .attr('dy', '-.7em')
+ .style('text-anchor', 'middle');
+
+ noDataText
+ .attr('x', margin.left + availableWidth / 2)
+ .attr('y', margin.top + availableHeight1 / 2)
+ .text(function(d) { return d });
+
+ return chart;
+ } else {
+ container.selectAll('.nv-noData').remove();
+ }
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup Scales
+
+ var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
+ var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
+
+ x = bars.xScale();
+ x2 = x2Axis.scale();
+ y1 = bars.yScale();
+ y2 = lines.yScale();
+ y3 = bars2.yScale();
+ y4 = lines2.yScale();
+
+ var series1 = data
+ .filter(function(d) { return !d.disabled && d.bar })
+ .map(function(d) {
+ return d.values.map(function(d,i) {
+ return { x: getX(d,i), y: getY(d,i) }
+ })
+ });
+
+ var series2 = data
+ .filter(function(d) { return !d.disabled && !d.bar })
+ .map(function(d) {
+ return d.values.map(function(d,i) {
+ return { x: getX(d,i), y: getY(d,i) }
+ })
+ });
+
+ x .range([0, availableWidth]);
+
+ x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
+ .range([0, availableWidth]);
+
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup containers and skeleton of chart
+
+ var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
+ var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
+ var g = wrap.select('g');
+
+ gEnter.append('g').attr('class', 'nv-legendWrap');
+
+ var focusEnter = gEnter.append('g').attr('class', 'nv-focus');
+ focusEnter.append('g').attr('class', 'nv-x nv-axis');
+ focusEnter.append('g').attr('class', 'nv-y1 nv-axis');
+ focusEnter.append('g').attr('class', 'nv-y2 nv-axis');
+ focusEnter.append('g').attr('class', 'nv-barsWrap');
+ focusEnter.append('g').attr('class', 'nv-linesWrap');
+
+ var contextEnter = gEnter.append('g').attr('class', 'nv-context');
+ contextEnter.append('g').attr('class', 'nv-x nv-axis');
+ contextEnter.append('g').attr('class', 'nv-y1 nv-axis');
+ contextEnter.append('g').attr('class', 'nv-y2 nv-axis');
+ contextEnter.append('g').attr('class', 'nv-barsWrap');
+ contextEnter.append('g').attr('class', 'nv-linesWrap');
+ contextEnter.append('g').attr('class', 'nv-brushBackground');
+ contextEnter.append('g').attr('class', 'nv-x nv-brush');
+
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Legend
+
+ if (showLegend) {
+ legend.width( availableWidth / 2 );
+
+ g.select('.nv-legendWrap')
+ .datum(data.map(function(series) {
+ series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
+ series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');
+ return series;
+ }))
+ .call(legend);
+
+ if ( margin.top != legend.height()) {
+ margin.top = legend.height();
+ availableHeight1 = (height || parseInt(container.style('height')) || 400)
+ - margin.top - margin.bottom - height2;
+ }
+
+ g.select('.nv-legendWrap')
+ .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
+ }
+
+ //------------------------------------------------------------
+
- d3.transition(focusLinesWrap).call(lines);
- */
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
//------------------------------------------------------------
- // Setup Main (Focus) Axes
+ // Context Components
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight1, 0);
+ bars2
+ .width(availableWidth)
+ .height(availableHeight2)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
- yAxis
- .scale(y)
- .ticks( availableHeight1 / 36 )
- .tickSize( -availableWidth, 0);
+ lines2
+ .width(availableWidth)
+ .height(availableHeight2)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
+
+ var bars2Wrap = g.select('.nv-context .nv-barsWrap')
+ .datum(dataBars.length ? dataBars : [{values:[]}]);
+
+ var lines2Wrap = g.select('.nv-context .nv-linesWrap')
+ .datum(!dataLines[0].disabled ? dataLines : [{values:[]}]);
+
+ g.select('.nv-context')
+ .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
- g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight1 + ')');
+ d3.transition(bars2Wrap).call(bars2);
+ d3.transition(lines2Wrap).call(lines2);
//------------------------------------------------------------
+
//------------------------------------------------------------
// Setup Brush
@@ -4581,51 +5625,60 @@ nv.models.lineWithFocusChart = function() {
.attr('y', 0)
.attr('height', availableHeight2);
- gBrush = g.select('.nv-x.nv-brush')
+ var gBrush = g.select('.nv-x.nv-brush')
.call(brush);
gBrush.selectAll('rect')
//.attr('y', -5)
.attr('height', availableHeight2);
gBrush.selectAll('.resize').append('path').attr('d', resizePath);
- onBrush();
-
//------------------------------------------------------------
-
//------------------------------------------------------------
// Setup Secondary (Context) Axes
x2Axis
- .scale(x2)
.ticks( availableWidth / 100 )
.tickSize(-availableHeight2, 0);
g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ .attr('transform', 'translate(0,' + y3.range()[0] + ')');
d3.transition(g.select('.nv-context .nv-x.nv-axis'))
.call(x2Axis);
- y2Axis
- .scale(y2)
+ y3Axis
+ .scale(y3)
.ticks( availableHeight2 / 36 )
.tickSize( -availableWidth, 0);
- d3.transition(g.select('.nv-context .nv-y.nv-axis'))
- .call(y2Axis);
+ g.select('.nv-context .nv-y1.nv-axis')
+ .style('opacity', dataBars.length ? 1 : 0)
+ .attr('transform', 'translate(0,' + x2.range()[0] + ')');
+
+ d3.transition(g.select('.nv-context .nv-y1.nv-axis'))
+ .call(y3Axis);
+
+
+ y4Axis
+ .scale(y4)
+ .ticks( availableHeight2 / 36 )
+ .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y2.range()[0] + ')');
+ g.select('.nv-context .nv-y2.nv-axis')
+ .style('opacity', dataLines.length ? 1 : 0)
+ .attr('transform', 'translate(' + x2.range()[1] + ',0)');
+ d3.transition(g.select('.nv-context .nv-y2.nv-axis'))
+ .call(y4Axis);
+
//------------------------------------------------------------
-
//============================================================
// Event Handling/Dispatching (in chart's scope)
//------------------------------------------------------------
- legend.dispatch.on('legendClick', function(d,i) {
+ legend.dispatch.on('legendClick', function(d,i) {
d.disabled = !d.disabled;
if (!data.filter(function(d) { return !d.disabled }).length) {
@@ -4636,7 +5689,7 @@ nv.models.lineWithFocusChart = function() {
});
}
- selection.transition().call(chart);
+ selection.call(chart);
});
dispatch.on('tooltipShow', function(e) {
@@ -4672,8 +5725,8 @@ nv.models.lineWithFocusChart = function() {
brushBG
.data([brush.empty() ? x2.domain() : brushExtent])
.each(function(d,i) {
- var leftWidth = x2(d[0]) - x.range()[0],
- rightWidth = x.range()[1] - x2(d[1]);
+ var leftWidth = x2(d[0]) - x2.range()[0],
+ rightWidth = x2.range()[1] - x2(d[1]);
d3.select(this).select('.left')
.attr('width', leftWidth < 0 ? 0 : leftWidth);
@@ -4691,14 +5744,43 @@ nv.models.lineWithFocusChart = function() {
dispatch.brush({extent: extent, brush: brush});
-
updateBrushBG();
- // Update Main (Focus)
+
+ //------------------------------------------------------------
+ // Prepare Main (Focus) Bars and Lines
+
+ bars
+ .width(availableWidth)
+ .height(availableHeight1)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
+
+
+ lines
+ .width(availableWidth)
+ .height(availableHeight1)
+ .color(data.map(function(d,i) {
+ return d.color || color(d, i);
+ }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
+
+ var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')
+ .datum(!dataBars.length ? [{values:[]}] :
+ dataBars
+ .map(function(d,i) {
+ return {
+ key: d.key,
+ values: d.values.filter(function(d,i) {
+ return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];
+ })
+ }
+ })
+ );
+
var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(
- data
- .filter(function(d) { return !d.disabled })
+ .datum(dataLines[0].disabled ? [{values:[]}] :
+ dataLines
.map(function(d,i) {
return {
key: d.key,
@@ -4707,19 +5789,75 @@ nv.models.lineWithFocusChart = function() {
})
}
})
- );
+ );
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Update Main (Focus) X Axis
+
+ if (dataBars.length) {
+ x = bars.xScale();
+ } else {
+ x = lines.xScale();
+ }
+
+ xAxis
+ .scale(x)
+ .ticks( availableWidth / 100 )
+ .tickSize(-availableHeight1, 0);
+
+ xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);
+
+ d3.transition(g.select('.nv-x.nv-axis'))
+ .call(xAxis);
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Update Main (Focus) Bars and Lines
+
+ d3.transition(focusBarsWrap).call(bars);
d3.transition(focusLinesWrap).call(lines);
+
+ //------------------------------------------------------------
+
+
+ //------------------------------------------------------------
+ // Setup and Update Main (Focus) Y Axes
+
+ g.select('.nv-focus .nv-x.nv-axis')
+ .attr('transform', 'translate(0,' + y1.range()[0] + ')');
- // Update Main (Focus) Axes
- d3.transition(g.select('.nv-focus .nv-x.nv-axis'))
- .call(xAxis);
- d3.transition(g.select('.nv-focus .nv-y.nv-axis'))
- .call(yAxis);
+ y1Axis
+ .scale(y1)
+ .ticks( availableHeight1 / 36 )
+ .tickSize(-availableWidth, 0);
+
+ g.select('.nv-focus .nv-y1.nv-axis')
+ .style('opacity', dataBars.length ? 1 : 0);
+
+
+ y2Axis
+ .scale(y2)
+ .ticks( availableHeight1 / 36 )
+ .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
+
+ g.select('.nv-focus .nv-y2.nv-axis')
+ .style('opacity', dataLines.length ? 1 : 0)
+ .attr('transform', 'translate(' + x.range()[1] + ',0)');
+
+ d3.transition(g.select('.nv-focus .nv-y1.nv-axis'))
+ .call(y1Axis);
+ d3.transition(g.select('.nv-focus .nv-y2.nv-axis'))
+ .call(y2Axis);
}
//============================================================
+ onBrush();
});
@@ -4740,6 +5878,15 @@ nv.models.lineWithFocusChart = function() {
dispatch.tooltipHide(e);
});
+ bars.dispatch.on('elementMouseover.tooltip', function(e) {
+ e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];
+ dispatch.tooltipShow(e);
+ });
+
+ bars.dispatch.on('elementMouseout.tooltip', function(e) {
+ dispatch.tooltipHide(e);
+ });
+
dispatch.on('tooltipHide', function() {
if (tooltips) nv.tooltip.cleanup();
});
@@ -4756,24 +5903,32 @@ nv.models.lineWithFocusChart = function() {
chart.legend = legend;
chart.lines = lines;
chart.lines2 = lines2;
+ chart.bars = bars;
+ chart.bars2 = bars2;
chart.xAxis = xAxis;
- chart.yAxis = yAxis;
chart.x2Axis = x2Axis;
+ chart.y1Axis = y1Axis;
chart.y2Axis = y2Axis;
+ chart.y3Axis = y3Axis;
+ chart.y4Axis = y4Axis;
- d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
+ d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');
+ //TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.
+ //d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
chart.x = function(_) {
- if (!arguments.length) return lines.x;
+ if (!arguments.length) return getX;
+ getX = _;
lines.x(_);
- lines2.x(_);
+ bars.x(_);
return chart;
};
chart.y = function(_) {
- if (!arguments.length) return lines.y;
+ if (!arguments.length) return getY;
+ getY = _;
lines.y(_);
- lines2.y(_);
+ bars.y(_);
return chart;
};
@@ -4786,12 +5941,6 @@ nv.models.lineWithFocusChart = function() {
return chart;
};
- chart.margin2 = function(_) {
- if (!arguments.length) return margin2;
- margin2 = _;
- return chart;
- };
-
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
@@ -4806,7 +5955,7 @@ nv.models.lineWithFocusChart = function() {
chart.color = function(_) {
if (!arguments.length) return color;
- color =nv.utils.getColor(_);
+ color = nv.utils.getColor(_);
legend.color(color);
return chart;
};
@@ -4829,33 +5978,18 @@ nv.models.lineWithFocusChart = function() {
return chart;
};
- chart.interpolate = function(_) {
- if (!arguments.length) return lines.interpolate();
- lines.interpolate(_);
- lines2.interpolate(_);
- return chart;
- };
-
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
return chart;
};
- // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
- chart.xTickFormat = function(_) {
- if (!arguments.length) return xAxis.tickFormat();
- xAxis.tickFormat(_);
- x2Axis.tickFormat(_);
+ chart.brushExtent = function(_) {
+ if (!arguments.length) return brushExtent;
+ brushExtent = _;
return chart;
};
- chart.yTickFormat = function(_) {
- if (!arguments.length) return yAxis.tickFormat();
- yAxis.tickFormat(_);
- y2Axis.tickFormat(_);
- return chart;
- };
//============================================================
@@ -4881,6 +6015,9 @@ nv.models.multiBar = function() {
, clipEdge = true
, stacked = false
, color = nv.utils.defaultColor()
+ , hideable = false
+ , barColor = null // adding the ability to set the color for each rather than the whole group
+ , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
, delay = 1200
, xDomain
, yDomain
@@ -4906,12 +6043,22 @@ nv.models.multiBar = function() {
availableHeight = height - margin.top - margin.bottom,
container = d3.select(this);
+ if(hideable && data.length) hideable = [{
+ values: data[0].values.map(function(d) {
+ return {
+ x: d.x,
+ y: 0,
+ series: d.series,
+ size: 0.01
+ };}
+ )}];
+
if (stacked)
data = d3.layout.stack()
.offset('zero')
.values(function(d){ return d.values })
.y(getY)
- (data);
+ (!data.length && hideable ? hideable : data);
//add series index to each data point for reference
@@ -4925,23 +6072,42 @@ nv.models.multiBar = function() {
//------------------------------------------------------------
+ // HACK for negative value stacking
+ if (stacked)
+ data[0].values.map(function(d,i) {
+ var posBase = 0, negBase = 0;
+ data.map(function(d) {
+ var f = d.values[i]
+ f.size = Math.abs(f.y);
+ if (f.y<0) {
+ f.y1 = negBase;
+ negBase = negBase - f.size;
+ } else
+ {
+ f.y1 = f.size + posBase;
+ posBase = posBase + f.size;
+ }
+ });
+ });
+
+ //------------------------------------------------------------
// Setup Scales
// remap and flatten the data for use in calculating the scales' domains
var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
data.map(function(d) {
return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
+ return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
})
});
x .domain(d3.merge(seriesData).map(function(d) { return d.x }))
.rangeBands([0, availableWidth], .1);
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ //y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y1 : 0) }).concat(forceY)))
+ y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 : d.y1 + d.y ) : d.y }).concat(forceY)))
.range([availableHeight, 0]);
-
// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point
if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true;
if (x.domain()[0] === x.domain()[1])
@@ -5013,7 +6179,7 @@ nv.models.multiBar = function() {
var bars = groups.selectAll('rect.nv-bar')
- .data(function(d) { return d.values });
+ .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
bars.exit().remove();
@@ -5079,14 +6245,28 @@ nv.models.multiBar = function() {
bars
.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
+
+ if (barColor) {
+ if (!disabled) disabled = data.map(function() { return true });
+ bars
+ //.style('fill', barColor)
+ //.style('stroke', barColor)
+ //.style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ //.style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
+ .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
+ }
+
+
if (stacked)
d3.transition(bars)
.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('y', function(d,i) {
- return y(getY(d,i) + (stacked ? d.y0 : 0));
+
+ return y((stacked ? d.y1 : 0));
})
.attr('height', function(d,i) {
- return Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0)))
+ return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1);
})
.each('end', function() {
d3.transition(d3.select(this))
@@ -5106,11 +6286,13 @@ nv.models.multiBar = function() {
d3.transition(d3.select(this))
.attr('y', function(d,i) {
return getY(d,i) < 0 ?
- y(0) :
- y(getY(d,i))
- })
- .attr('height', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
+ y(0) :
+ y(0) - y(getY(d,i)) < 1 ?
+ y(0) - 1 :
+ y(getY(d,i)) || 0;
+ })
+ .attr('height', function(d,i) {
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;
});
})
@@ -5212,12 +6394,30 @@ nv.models.multiBar = function() {
return chart;
};
+ chart.barColor = function(_) {
+ if (!arguments.length) return barColor;
+ barColor = nv.utils.getColor(_);
+ return chart;
+ };
+
+ chart.disabled = function(_) {
+ if (!arguments.length) return disabled;
+ disabled = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
return chart;
};
+ chart.hideable = function(_) {
+ if (!arguments.length) return hideable;
+ hideable = _;
+ return chart;
+ };
+
chart.delay = function(_) {
if (!arguments.length) return delay;
delay = _;
@@ -5258,8 +6458,11 @@ nv.models.multiBarChart = function() {
}
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
+ , state = { stacked: false }
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = function() { return showControls ? 180 : 0 }
;
multibar
@@ -5267,7 +6470,7 @@ nv.models.multiBarChart = function() {
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
.highlightZero(false)
.showMaxMin(false)
.tickFormat(function(d) { return d })
@@ -5310,7 +6513,19 @@ nv.models.multiBarChart = function() {
chart.update = function() { selection.transition().call(chart) };
chart.container = this;
-
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -5364,7 +6579,12 @@ nv.models.multiBarChart = function() {
// Legend
if (showLegend) {
- legend.width(availableWidth / 2);
+ legend.width(availableWidth - controlWidth());
+
+ if (multibar.barColor())
+ data.forEach(function(series,i) {
+ series.color = d3.rgb('#ccc').darker(i * 1.5).toString();
+ })
g.select('.nv-legendWrap')
.datum(data)
@@ -5377,7 +6597,7 @@ nv.models.multiBarChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -5392,7 +6612,7 @@ nv.models.multiBarChart = function() {
{ key: 'Stacked', disabled: !multibar.stacked() }
];
- controls.width(180).color(['#444', '#444', '#444']);
+ controls.width(controlWidth()).color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
.datum(controlsData)
.attr('transform', 'translate(0,' + (-margin.top) +')')
@@ -5409,6 +6629,7 @@ nv.models.multiBarChart = function() {
// Main Chart Component(s)
multibar
+ .disabled(data.map(function(series) { return series.disabled }))
.width(availableWidth)
.height(availableHeight)
.color(data.map(function(d,i) {
@@ -5453,9 +6674,12 @@ nv.models.multiBarChart = function() {
if(rotateLabels)
xTicks
- .selectAll('text')
- .attr('transform', function(d,i,j) { return 'rotate('+rotateLabels+' 0,0)' })
- .attr('text-transform', rotateLabels > 0 ? 'start' : 'end');
+ .selectAll('text')
+ .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')
+ .attr('text-anchor', rotateLabels > 0 ? 'start' : 'end');
+
+ g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')
+ .style('opacity', 1);
yAxis
.scale(y)
@@ -5484,6 +6708,9 @@ nv.models.multiBarChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -5504,6 +6731,9 @@ nv.models.multiBarChart = function() {
break;
}
+ state.stacked = multibar.stacked();
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -5511,6 +6741,25 @@ nv.models.multiBarChart = function() {
if (tooltips) showTooltip(e, that.parentNode)
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.stacked !== 'undefined') {
+ multibar.stacked(e.stacked);
+ state.stacked = e.stacked;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -5550,7 +6799,7 @@ nv.models.multiBarChart = function() {
chart.xAxis = xAxis;
chart.yAxis = yAxis;
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'stacked', 'delay');
+ d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'stacked', 'delay', 'barColor');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -5622,6 +6871,18 @@ nv.models.multiBarChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -5650,6 +6911,8 @@ nv.models.multiBarHorizontal = function() {
, getY = function(d) { return d.y }
, forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
, color = nv.utils.defaultColor()
+ , barColor = null // adding the ability to set the color for each rather than the whole group
+ , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
, stacked = false
, showValues = false
, valuePadding = 60
@@ -5698,6 +6961,28 @@ nv.models.multiBarHorizontal = function() {
});
+
+ //------------------------------------------------------------
+ // HACK for negative value stacking
+ if (stacked)
+ data[0].values.map(function(d,i) {
+ var posBase = 0, negBase = 0;
+ data.map(function(d) {
+ var f = d.values[i]
+ f.size = Math.abs(f.y);
+ if (f.y<0) {
+ f.y1 = negBase - f.size;
+ negBase = negBase - f.size;
+ } else
+ {
+ f.y1 = posBase;
+ posBase = posBase + f.size;
+ }
+ });
+ });
+
+
+
//------------------------------------------------------------
// Setup Scales
@@ -5705,14 +6990,15 @@ nv.models.multiBarHorizontal = function() {
var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate
data.map(function(d) {
return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
+ return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
})
});
x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
.rangeBands([0, availableHeight], .1);
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ //y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
+ y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY)))
if (showValues && !stacked)
y.range([(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);
@@ -5825,32 +7111,45 @@ nv.models.multiBarHorizontal = function() {
d3.event.stopPropagation();
});
+
+ barsEnter.append('text');
+
if (showValues && !stacked) {
- barsEnter.append('text')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
bars.select('text')
- .attr('y', x.rangeBand() / 2)
- .attr('dy', '-.32em')
+ .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
+ .attr('y', x.rangeBand() / (data.length * 2))
+ .attr('dy', '.32em')
.text(function(d,i) { return valueFormat(getY(d,i)) })
d3.transition(bars)
//.delay(function(d,i) { return i * delay / data[0].values.length })
.select('text')
.attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })
} else {
- bars.selectAll('text').remove();
+ //bars.selectAll('text').remove();
+ bars.selectAll('text').text('');
}
bars
.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
- //.attr('transform', function(d,i,j) {
- //return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + x(getX(d,i)) + ')'
- //})
+
+ if (barColor) {
+ if (!disabled) disabled = data.map(function() { return true });
+ bars
+ //.style('fill', barColor)
+ //.style('stroke', barColor)
+ //.style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ //.style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker(j).toString(); })
+ .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
+ .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
+ }
+
if (stacked)
d3.transition(bars)
//.delay(function(d,i) { return i * delay / data[0].values.length })
.attr('transform', function(d,i) {
//return 'translate(' + y(d.y0) + ',0)'
- return 'translate(' + y(d.y0) + ',' + x(getX(d,i)) + ')'
+ //return 'translate(' + y(d.y0) + ',' + x(getX(d,i)) + ')'
+ return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'
})
.select('rect')
.attr('width', function(d,i) {
@@ -5873,7 +7172,7 @@ nv.models.multiBarHorizontal = function() {
.select('rect')
.attr('height', x.rangeBand() / data.length )
.attr('width', function(d,i) {
- return Math.abs(y(getY(d,i)) - y(0))
+ return Math.max(Math.abs(y(getY(d,i)) - y(0)),1)
});
@@ -5968,6 +7267,18 @@ nv.models.multiBarHorizontal = function() {
return chart;
};
+ chart.barColor = function(_) {
+ if (!arguments.length) return barColor;
+ barColor = nv.utils.getColor(_);
+ return chart;
+ };
+
+ chart.disabled = function(_) {
+ if (!arguments.length) return disabled;
+ disabled = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
@@ -6031,8 +7342,11 @@ nv.models.multiBarHorizontalChart = function() {
}
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
+ , state = { stacked: stacked }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = function() { return showControls ? 180 : 0 }
;
multibar
@@ -6083,6 +7397,19 @@ nv.models.multiBarHorizontalChart = function() {
chart.update = function() { selection.transition().call(chart) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -6137,7 +7464,12 @@ nv.models.multiBarHorizontalChart = function() {
// Legend
if (showLegend) {
- legend.width(availableWidth / 2);
+ legend.width(availableWidth - controlWidth());
+
+ if (multibar.barColor())
+ data.forEach(function(series,i) {
+ series.color = d3.rgb('#ccc').darker(i * 1.5).toString();
+ })
g.select('.nv-legendWrap')
.datum(data)
@@ -6150,7 +7482,7 @@ nv.models.multiBarHorizontalChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -6165,7 +7497,7 @@ nv.models.multiBarHorizontalChart = function() {
{ key: 'Stacked', disabled: !multibar.stacked() }
];
- controls.width(180).color(['#444', '#444', '#444']);
+ controls.width(controlWidth()).color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
.datum(controlsData)
.attr('transform', 'translate(0,' + (-margin.top) +')')
@@ -6182,6 +7514,7 @@ nv.models.multiBarHorizontalChart = function() {
// Main Chart Component(s)
multibar
+ .disabled(data.map(function(series) { return series.disabled }))
.width(availableWidth)
.height(availableHeight)
.color(data.map(function(d,i) {
@@ -6244,6 +7577,9 @@ nv.models.multiBarHorizontalChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -6264,6 +7600,9 @@ nv.models.multiBarHorizontalChart = function() {
break;
}
+ state.stacked = multibar.stacked();
+ dispatch.stateChange(state);
+
selection.transition().call(chart);
});
@@ -6271,6 +7610,24 @@ nv.models.multiBarHorizontalChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.stacked !== 'undefined') {
+ multibar.stacked(e.stacked);
+ state.stacked = e.stacked;
+ }
+
+ selection.call(chart);
+ });
//============================================================
@@ -6310,7 +7667,7 @@ nv.models.multiBarHorizontalChart = function() {
chart.xAxis = xAxis;
chart.yAxis = yAxis;
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'delay', 'showValues', 'valueFormat', 'stacked');
+ d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'forceX', 'forceY', 'clipEdge', 'id', 'delay', 'showValues', 'valueFormat', 'stacked', 'barColor');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -6370,6 +7727,18 @@ nv.models.multiBarHorizontalChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -6427,7 +7796,7 @@ nv.models.multiChart = function() {
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
top = e.pos[1] + ( offsetElement.offsetTop || 0),
x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)),
- y = (e.series.bar ? yAxis1 : yAxis2).tickFormat()(lines1.y()(e.point, e.pointIndex)),
+ y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)),
content = tooltip(e.series.key, x, y, e, chart);
nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent);
@@ -6846,6 +8215,7 @@ nv.models.ohlcBar = function() {
, getLow = function(d) { return d.low }
, forceX = []
, forceY = []
+ , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
, clipEdge = true
, color = nv.utils.defaultColor()
, xDomain
@@ -6874,8 +8244,12 @@ nv.models.ohlcBar = function() {
//------------------------------------------------------------
// Setup Scales
- x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ))
- .range([0, availableWidth]);
+ x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));
+
+ if (padData)
+ x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
y .domain(yDomain || [
d3.min(data[0].values.map(getLow).concat(forceY)),
@@ -7156,6 +8530,12 @@ nv.models.ohlcBar = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -7179,7 +8559,6 @@ nv.models.ohlcBar = function() {
return chart;
}
-
nv.models.pie = function() {
//============================================================
@@ -7192,13 +8571,19 @@ nv.models.pie = function() {
, getValues = function(d) { return d.values }
, getX = function(d) { return d.x }
, getY = function(d) { return d.y }
+ , getDescription = function(d) { return d.description }
, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
, color = nv.utils.defaultColor()
, valueFormat = d3.format(',.2f')
, showLabels = true
+ , pieLabelsOutside = true
, donutLabelsOutside = false
, labelThreshold = .02 //if slice percentage is under this, don't show label
, donut = false
+ , labelSunbeamLayout = false
+ , startAngle = false
+ , endAngle = false
+ , donutRatio = 0.5
, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
;
@@ -7210,6 +8595,7 @@ nv.models.pie = function() {
var availableWidth = width - margin.left - margin.right,
availableHeight = height - margin.top - margin.bottom,
radius = Math.min(availableWidth, availableHeight) / 2,
+ arcRadius = radius-(radius / 5),
container = d3.select(this);
@@ -7242,10 +8628,11 @@ nv.models.pie = function() {
var arc = d3.svg.arc()
- .outerRadius((radius-(radius / 5)));
-
- if (donut) arc.innerRadius(radius / 2);
+ .outerRadius(arcRadius);
+ if (startAngle) arc.startAngle(startAngle)
+ if (endAngle) arc.endAngle(endAngle);
+ if (donut) arc.innerRadius(radius * donutRatio);
// Setup the Pie chart and choose the data element
var pie = d3.layout.pie()
@@ -7317,10 +8704,11 @@ nv.models.pie = function() {
if (showLabels) {
// This does the normal label
- var labelsArc = arc;
- if (donutLabelsOutside) {
- labelsArc = d3.svg.arc().outerRadius(arc.outerRadius())
- }
+ var labelsArc = d3.svg.arc().innerRadius(0);
+
+ if (pieLabelsOutside){ labelsArc = arc; }
+
+ if (donutLabelsOutside) { labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); }
ae.append("g").classed("nv-label", true)
.each(function(d, i) {
@@ -7328,9 +8716,21 @@ nv.models.pie = function() {
group
.attr('transform', function(d) {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc.centroid(d) + ')'
+ if (labelSunbeamLayout) {
+ d.outerRadius = arcRadius + 10; // Set Outer Coordinate
+ d.innerRadius = arcRadius + 15; // Set Inner Coordinate
+ var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
+ if ((d.startAngle+d.endAngle)/2 < Math.PI) {
+ rotateAngle -= 90;
+ } else {
+ rotateAngle += 90;
+ }
+ return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';
+ } else {
+ d.outerRadius = radius + 10; // Set Outer Coordinate
+ d.innerRadius = radius + 15; // Set Inner Coordinate
+ return 'translate(' + labelsArc.centroid(d) + ')'
+ }
});
group.append('rect')
@@ -7340,7 +8740,7 @@ nv.models.pie = function() {
.attr("ry", 3);
group.append('text')
- .style('text-anchor', 'middle') //center the text on it's origin
+ .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
.style('fill', '#000')
@@ -7348,9 +8748,21 @@ nv.models.pie = function() {
slices.select(".nv-label").transition()
.attr('transform', function(d) {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc.centroid(d) + ')';
+ if (labelSunbeamLayout) {
+ d.outerRadius = arcRadius + 10; // Set Outer Coordinate
+ d.innerRadius = arcRadius + 15; // Set Inner Coordinate
+ var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
+ if ((d.startAngle+d.endAngle)/2 < Math.PI) {
+ rotateAngle -= 90;
+ } else {
+ rotateAngle += 90;
+ }
+ return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';
+ } else {
+ d.outerRadius = radius + 10; // Set Outer Coordinate
+ d.innerRadius = radius + 15; // Set Inner Coordinate
+ return 'translate(' + labelsArc.centroid(d) + ')'
+ }
});
slices.each(function(d, i) {
@@ -7358,6 +8770,7 @@ nv.models.pie = function() {
slice
.select(".nv-label text")
+ .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned
.text(function(d, i) {
var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);
return (d.value && percent > labelThreshold) ? getX(d.data) : '';
@@ -7447,24 +8860,60 @@ nv.models.pie = function() {
getY = d3.functor(_);
return chart;
};
+
+ chart.description = function(_) {
+ if (!arguments.length) return getDescription;
+ getDescription = _;
+ return chart;
+ };
chart.showLabels = function(_) {
if (!arguments.length) return showLabels;
showLabels = _;
return chart;
};
+
+ chart.labelSunbeamLayout = function(_) {
+ if (!arguments.length) return labelSunbeamLayout;
+ labelSunbeamLayout = _;
+ return chart;
+ };
chart.donutLabelsOutside = function(_) {
if (!arguments.length) return donutLabelsOutside;
donutLabelsOutside = _;
return chart;
};
+
+ chart.pieLabelsOutside = function(_) {
+ if (!arguments.length) return pieLabelsOutside;
+ pieLabelsOutside = _;
+ return chart;
+ };
chart.donut = function(_) {
if (!arguments.length) return donut;
donut = _;
return chart;
};
+
+ chart.donutRatio = function(_) {
+ if (!arguments.length) return donutRatio;
+ donutRatio = _;
+ return chart;
+ };
+
+ chart.startAngle = function(_) {
+ if (!arguments.length) return startAngle;
+ startAngle = _;
+ return chart;
+ };
+
+ chart.endAngle = function(_) {
+ if (!arguments.length) return endAngle;
+ endAngle = _;
+ return chart;
+ };
chart.id = function(_) {
if (!arguments.length) return id;
@@ -7489,13 +8938,11 @@ nv.models.pie = function() {
labelThreshold = _;
return chart;
};
-
//============================================================
return chart;
}
-
nv.models.pieChart = function() {
//============================================================
@@ -7516,8 +8963,10 @@ nv.models.pieChart = function() {
return '<h3>' + key + '</h3>' +
'<p>' + y + '</p>'
}
+ , state = {}
+ , defaultState = null
, noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
;
//============================================================
@@ -7528,10 +8977,11 @@ nv.models.pieChart = function() {
//------------------------------------------------------------
var showTooltip = function(e, offsetElement) {
+ var tooltipLabel = pie.description()(e.point) || pie.x()(e.point)
var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ),
top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0),
y = pie.valueFormat()(pie.y()(e.point)),
- content = tooltip(pie.x()(e.point), y, e, chart);
+ content = tooltip(tooltipLabel, y, e, chart);
nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);
};
@@ -7544,7 +8994,7 @@ nv.models.pieChart = function() {
var container = d3.select(this),
that = this;
- var availableWidth = (width || parseInt(container.style('width')) || 960)
+ var availableWidth = (width || parseInt(container.style('width')) || 960)
- margin.left - margin.right,
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
@@ -7552,11 +9002,24 @@ nv.models.pieChart = function() {
chart.update = function() { chart(selection); };
chart.container = this;
+ //set state.disabled
+ state.disabled = data[0].map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
- if (!data || !data.length) {
+ if (!data[0] || !data[0].length) {
var noDataText = container.selectAll('.nv-noData').data([noData]);
noDataText.enter().append('text')
@@ -7649,6 +9112,9 @@ nv.models.pieChart = function() {
});
}
+ state.disabled = data[0].map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
selection.transition().call(chart)
});
@@ -7656,6 +9122,20 @@ nv.models.pieChart = function() {
dispatch.tooltipHide(e);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data[0].forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -7689,10 +9169,11 @@ nv.models.pieChart = function() {
//------------------------------------------------------------
// expose chart's sub-components
+ chart.legend = legend;
chart.dispatch = dispatch;
chart.pie = pie;
- d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'id', 'showLabels', 'donutLabelsOutside', 'donut', 'labelThreshold');
+ d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'description', 'id', 'showLabels', 'donutLabelsOutside', 'pieLabelsOutside', 'donut', 'donutRatio', 'labelThreshold');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -7741,6 +9222,18 @@ nv.models.pieChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -7759,33 +9252,36 @@ nv.models.scatter = function() {
// Public Variables with Default Settings
//------------------------------------------------------------
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , color = nv.utils.defaultColor() // chooses color
- , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
- , getX = function(d) { return d.x } // accessor to get the x value
- , getY = function(d) { return d.y } // accessor to get the y value
- , getSize = function(d) { return d.size } // accessor to get the point size
- , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
- , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , forceY = [] // List of numbers to Force into the Y scale
- , forceSize = [] // List of numbers to Force into the Size scale
- , interactive = true // If true, plots a voronoi overlay for advanced point interection
- , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
- , clipEdge = false // if true, masks points within x and y scale
- , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
- , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
- , xDomain = null // Override x domain (skips the calculation from data)
- , yDomain = null // Override y domain
- , sizeDomain = null // Override point size domain
- , sizeRange = null
- , singlePoint = false
- , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
- , useVoronoi = true
+ var margin = {top: 0, right: 0, bottom: 0, left: 0}
+ , width = 960
+ , height = 500
+ , color = nv.utils.defaultColor() // chooses color
+ , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
+ , x = d3.scale.linear()
+ , y = d3.scale.linear()
+ , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
+ , getX = function(d) { return d.x } // accessor to get the x value
+ , getY = function(d) { return d.y } // accessor to get the y value
+ , getSize = function(d) { return d.size || 1} // accessor to get the point size
+ , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
+ , onlyCircles = true // Set to false to use shapes
+ , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
+ , forceY = [] // List of numbers to Force into the Y scale
+ , forceSize = [] // List of numbers to Force into the Size scale
+ , interactive = true // If true, plots a voronoi overlay for advanced point intersection
+ , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
+ , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
+ , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding
+ , clipEdge = false // if true, masks points within x and y scale
+ , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance
+ , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips
+ , xDomain = null // Override x domain (skips the calculation from data)
+ , yDomain = null // Override y domain
+ , sizeDomain = null // Override point size domain
+ , sizeRange = null
+ , singlePoint = false
+ , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
+ , useVoronoi = true
;
//============================================================
@@ -7797,6 +9293,7 @@ nv.models.scatter = function() {
var x0, y0, z0 // used to store previous scales
, timeoutID
+ , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
;
//============================================================
@@ -7831,7 +9328,12 @@ nv.models.scatter = function() {
);
x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x }).concat(forceX)))
- .range([0, availableWidth]);
+
+ if (padData && data[0])
+ x.range([(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
+ //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
+ else
+ x.range([0, availableWidth]);
y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
.range([availableHeight, 0]);
@@ -7907,45 +9409,109 @@ nv.models.scatter = function() {
);
- if (clipVoronoi) {
- defsEnter.append('clipPath').attr('id', 'nv-points-clip-' + id);
- var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
- .data(vertices);
- pointClips.enter().append('circle')
- .attr('r', clipRadius);
- pointClips.exit().remove();
- pointClips
- .attr('cx', function(d) { return d[0] })
- .attr('cy', function(d) { return d[1] });
+ //inject series and point index for reference into voronoi
+ if (useVoronoi === true) {
+
+ if (clipVoronoi) {
+ var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
+ .data([id])
+ .enter();
+
+ pointClipsEnter.append('clipPath')
+ .attr('class', 'nv-point-clips')
+ .attr('id', 'nv-points-clip-' + id);
+
+ var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
+ .data(vertices);
+ pointClips.enter().append('circle')
+ .attr('r', clipRadius);
+ pointClips.exit().remove();
+ pointClips
+ .attr('cx', function(d) { return d[0] })
+ .attr('cy', function(d) { return d[1] });
+
+ wrap.select('.nv-point-paths')
+ .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
+ }
- wrap.select('.nv-point-paths')
- .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
- }
+ // if(vertices.length < 3) {
+ // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work
+ vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);
+ vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);
+ vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
+ vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
+ // }
+
+ var bounds = d3.geom.polygon([
+ [-10,-10],
+ [-10,height + 10],
+ [width + 10,height + 10],
+ [width + 10,-10]
+ ]);
- //inject series and point index for reference into voronoi
- if (useVoronoi === true) {
var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
return {
- 'data': d,
+ 'data': bounds.clip(d),
'series': vertices[i][2],
'point': vertices[i][3]
}
});
+
var pointPaths = wrap.select('.nv-point-paths').selectAll('path')
.data(voronoi);
pointPaths.enter().append('path')
.attr('class', function(d,i) { return 'nv-path-'+i; });
pointPaths.exit().remove();
pointPaths
- .attr('d', function(d) { return 'M' + d.data.join(',') + 'Z'; });
+ .attr('d', function(d) { return 'M' + d.data.join('L') + 'Z'; });
+
+ pointPaths
+ .on('click', function(d) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementClick({
+ point: point,
+ series: series,
+ pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ })
+ .on('mouseover', function(d) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementMouseover({
+ point: point,
+ series: series,
+ pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ })
+ .on('mouseout', function(d, i) {
+ if (needsUpdate) return 0;
+ var series = data[d.series],
+ point = series.values[d.point];
+
+ dispatch.elementMouseout({
+ point: point,
+ series: series,
+ seriesIndex: d.series,
+ pointIndex: d.point
+ });
+ });
- eventElements = pointPaths;
} else {
+ /*
// bring data in form needed for click handlers
var dataWithPoints = vertices.map(function(d, i) {
return {
@@ -7954,54 +9520,58 @@ nv.models.scatter = function() {
'point': vertices[i][3]
}
});
+ */
// add event handlers to points instead voronoi paths
- eventElements = wrap.select('.nv-groups').selectAll('.nv-group')
- .selectAll('path.nv-point')
- .data(dataWithPoints)
- .style('pointer-events', 'auto'); // recativate events, disabled by css
- }
+ wrap.select('.nv-groups').selectAll('.nv-group')
+ .selectAll('.nv-point')
+ //.data(dataWithPoints)
+ //.style('pointer-events', 'auto') // recativate events, disabled by css
+ .on('click', function(d,i) {
+ //nv.log('test', d, i);
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- eventElements
- .on('click', function(d) {
- var series = data[d.series],
- point = series.values[d.point];
-
- dispatch.elementClick({
- point: point,
- series: series,
- pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
- seriesIndex: d.series,
- pointIndex: d.point
- });
- })
- .on('mouseover', function(d) {
- var series = data[d.series],
- point = series.values[d.point];
+ dispatch.elementClick({
+ point: point,
+ series: series,
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: i
+ });
+ })
+ .on('mouseover', function(d,i) {
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- dispatch.elementMouseover({
- point: point,
- series: series,
- pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
- seriesIndex: d.series,
- pointIndex: d.point
- });
- })
- .on('mouseout', function(d, i) {
- var series = data[d.series],
- point = series.values[d.point];
+ dispatch.elementMouseover({
+ point: point,
+ series: series,
+ pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
+ seriesIndex: d.series,
+ pointIndex: i
+ });
+ })
+ .on('mouseout', function(d,i) {
+ if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point
+ var series = data[d.series],
+ point = series.values[i];
- dispatch.elementMouseout({
- point: point,
- series: series,
- seriesIndex: d.series,
- pointIndex: d.point
+ dispatch.elementMouseout({
+ point: point,
+ series: series,
+ seriesIndex: d.series,
+ pointIndex: i
+ });
});
- });
+ }
+ needsUpdate = false;
}
-
+ needsUpdate = true;
var groups = wrap.select('.nv-groups').selectAll('.nv-group')
.data(function(d) { return d }, function(d) { return d.key });
@@ -8022,38 +9592,62 @@ nv.models.scatter = function() {
.style('fill-opacity', .5);
- var points = groups.selectAll('path.nv-point')
- .data(function(d) { return d.values });
- points.enter().append('path')
- .attr('transform', function(d,i) {
- return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
- })
- .attr('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
- points.exit().remove();
- d3.transition(groups.exit().selectAll('path.nv-point'))
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
- })
- .remove();
- points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
- d3.transition(points)
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
- })
- .attr('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
+ if (onlyCircles) {
+
+ var points = groups.selectAll('circle.nv-point')
+ .data(function(d) { return d.values });
+ points.enter().append('circle')
+ .attr('cx', function(d,i) { return x0(getX(d,i)) })
+ .attr('cy', function(d,i) { return y0(getY(d,i)) })
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
+ points.exit().remove();
+ d3.transition(groups.exit().selectAll('path.nv-point'))
+ .attr('cx', function(d,i) { return x(getX(d,i)) })
+ .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .remove();
+ points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
+ d3.transition(points)
+ .attr('cx', function(d,i) { return x(getX(d,i)) })
+ .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
+
+ } else {
+
+ var points = groups.selectAll('path.nv-point')
+ .data(function(d) { return d.values });
+ points.enter().append('path')
+ .attr('transform', function(d,i) {
+ return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'
+ })
+ .attr('d',
+ d3.svg.symbol()
+ .type(getShape)
+ .size(function(d,i) { return z(getSize(d,i)) })
+ );
+ points.exit().remove();
+ d3.transition(groups.exit().selectAll('path.nv-point'))
+ .attr('transform', function(d,i) {
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
+ })
+ .remove();
+ points.attr('class', function(d,i) { return 'nv-point nv-point-' + i });
+ d3.transition(points)
+ .attr('transform', function(d,i) {
+ //nv.log(d,i,getX(d,i), x(getX(d,i)));
+ return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
+ })
+ .attr('d',
+ d3.svg.symbol()
+ .type(getShape)
+ .size(function(d,i) { return z(getSize(d,i)) })
+ );
+ }
// Delay updating the invisible interactive layer for smoother animation
clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
- timeoutID = setTimeout(updateInteractiveLayer, 1000);
+ timeoutID = setTimeout(updateInteractiveLayer, 300);
+ //updateInteractiveLayer();
//store old scales for use in transitions on update
x0 = x.copy();
@@ -8202,6 +9796,18 @@ nv.models.scatter = function() {
return chart;
};
+ chart.padData = function(_) {
+ if (!arguments.length) return padData;
+ padData = _;
+ return chart;
+ };
+
+ chart.padDataOuter = function(_) {
+ if (!arguments.length) return padDataOuter;
+ padDataOuter = _;
+ return chart;
+ };
+
chart.clipEdge = function(_) {
if (!arguments.length) return clipEdge;
clipEdge = _;
@@ -8241,6 +9847,12 @@ nv.models.scatter = function() {
return chart;
};
+ chart.onlyCircles = function(_) {
+ if (!arguments.length) return onlyCircles;
+ onlyCircles = _;
+ return chart;
+ };
+
chart.id = function(_) {
if (!arguments.length) return id;
id = _;
@@ -8274,7 +9886,7 @@ nv.models.scatterChart = function() {
, distY = nv.models.distribution()
;
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 75}
, width = null
, height = null
, color = nv.utils.defaultColor()
@@ -8293,7 +9905,9 @@ nv.models.scatterChart = function() {
, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }
//, tooltip = function(key, x, y) { return '<h3>' + key + '</h3>' }
, tooltip = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , state = {}
+ , defaultState = null
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
, noData = "No Data Available."
;
@@ -8365,6 +9979,19 @@ nv.models.scatterChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -8405,10 +10032,10 @@ nv.models.scatterChart = function() {
var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
var gEnter = wrapEnter.append('g');
- var g = wrap.select('g')
+ var g = wrap.select('g');
// background for pointer events
- gEnter.append('rect').attr('class', 'nvd3 nv-background')
+ gEnter.append('rect').attr('class', 'nvd3 nv-background');
gEnter.append('g').attr('class', 'nv-x nv-axis');
gEnter.append('g').attr('class', 'nv-y nv-axis');
@@ -8417,8 +10044,6 @@ nv.models.scatterChart = function() {
gEnter.append('g').attr('class', 'nv-legendWrap');
gEnter.append('g').attr('class', 'nv-controlsWrap');
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
//------------------------------------------------------------
@@ -8459,6 +10084,9 @@ nv.models.scatterChart = function() {
//------------------------------------------------------------
+ wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
+
+
//------------------------------------------------------------
// Main Chart Component(s)
@@ -8493,7 +10121,7 @@ nv.models.scatterChart = function() {
xAxis
.scale(x)
- .ticks( xAxis.ticks() ? xAxis.ticks() : availableWidth / 100 )
+ .ticks( xAxis.ticks() && xAxis.ticks().length ? xAxis.ticks() : availableWidth / 100 )
.tickSize( -availableHeight , 0);
g.select('.nv-x.nv-axis')
@@ -8503,7 +10131,7 @@ nv.models.scatterChart = function() {
yAxis
.scale(y)
- .ticks( yAxis.ticks() ? yAxis.ticks() : availableHeight / 36 )
+ .ticks( yAxis.ticks() && yAxis.ticks().length ? yAxis.ticks() : availableHeight / 36 )
.tickSize( -availableWidth, 0);
g.select('.nv-y.nv-axis')
@@ -8623,6 +10251,9 @@ nv.models.scatterChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
chart(selection);
});
@@ -8652,6 +10283,20 @@ nv.models.scatterChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -8797,6 +10442,18 @@ nv.models.scatterChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -8824,7 +10481,7 @@ nv.models.scatterPlusLineChart = function() {
, distY = nv.models.distribution()
;
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
+ var margin = {top: 30, right: 20, bottom: 50, left: 75}
, width = null
, height = null
, color = nv.utils.defaultColor()
@@ -8839,9 +10496,12 @@ nv.models.scatterPlusLineChart = function() {
, tooltips = true
, tooltipX = function(key, x, y) { return '<strong>' + x + '</strong>' }
, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }
- //, tooltip = function(key, x, y) { return '<h3>' + key + '</h3>' }
- , tooltip = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , tooltip = function(key, x, y, date) { return '<h3>' + key + '</h3>'
+ + '<p>' + date + '</p>' }
+ //, tooltip = null
+ , state = {}
+ , defaultState = null
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
, noData = "No Data Available."
;
@@ -8890,7 +10550,7 @@ nv.models.scatterPlusLineChart = function() {
if( tooltipY != null )
nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip');
if( tooltip != null )
- nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);
+ nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);
};
var controlsData = [
@@ -8913,6 +10573,19 @@ nv.models.scatterPlusLineChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
//------------------------------------------------------------
// Display noData message if there's nothing to show.
@@ -9187,6 +10860,9 @@ nv.models.scatterPlusLineChart = function() {
});
}
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
chart(selection);
});
@@ -9216,6 +10892,20 @@ nv.models.scatterPlusLineChart = function() {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ selection.call(chart);
+ });
+
//============================================================
@@ -9349,6 +11039,18 @@ nv.models.scatterPlusLineChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -9429,15 +11131,32 @@ nv.models.sparkline = function() {
// TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
var points = wrap.selectAll('circle.nv-point')
- .data(function(d) { return d.filter(function(p,i) { return y.domain().indexOf(getY(p,i)) != -1 || getX(p,i) == x.domain()[1] }) });
- points.enter().append('circle').attr('class', 'nv-point');
+ .data(function(data) {
+ var yValues = data.map(function(d, i) { return getY(d,i); });
+ function pointIndex(index) {
+ if (index != -1) {
+ var result = data[index];
+ result.pointIndex = index;
+ return result;
+ } else {
+ return null;
+ }
+ }
+ var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),
+ minPoint = pointIndex(yValues.indexOf(y.domain()[0])),
+ currentPoint = pointIndex(yValues.length - 1);
+ return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});
+ });
+ points.enter().append('circle');
points.exit().remove();
points
- .attr('cx', function(d,i) { return x(getX(d,i)) })
- .attr('cy', function(d,i) { return y(getY(d,i)) })
+ .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })
+ .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })
.attr('r', 2)
- .style('stroke', function(d,i) { return d.x == x.domain()[1] ? '#444' : d.y == y.domain()[0] ? '#d62728' : '#2ca02c' })
- .style('fill', function(d,i) { return d.x == x.domain()[1] ? '#444' : d.y == y.domain()[0] ? '#d62728' : '#2ca02c' });
+ .attr('class', function(d,i) {
+ return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
+ getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
+ });
});
return chart;
@@ -9531,16 +11250,18 @@ nv.models.sparklinePlus = function() {
var sparkline = nv.models.sparkline();
- var margin = {top: 15, right: 40, bottom: 3, left: 40}
+ var margin = {top: 15, right: 100, bottom: 10, left: 50}
, width = null
, height = null
, x
, y
- , color = nv.utils.defaultColor()
- , index
+ , index = []
, paused = false
, xTickFormat = d3.format(',r')
, yTickFormat = d3.format(',.2f')
+ , showValue = true
+ , alignValue = true
+ , rightAlignValue = false
, noData = "No Data Available."
;
@@ -9556,6 +11277,7 @@ nv.models.sparklinePlus = function() {
availableHeight = (height || parseInt(container.style('height')) || 400)
- margin.top - margin.bottom;
+ var currentValue = sparkline.y()(data[data.length-1], data.length-1);
chart.update = function() { chart(selection) };
chart.container = this;
@@ -9604,6 +11326,7 @@ nv.models.sparklinePlus = function() {
var g = wrap.select('g');
gEnter.append('g').attr('class', 'nv-sparklineWrap');
+ gEnter.append('g').attr('class', 'nv-valueWrap');
gEnter.append('g').attr('class', 'nv-hoverArea');
wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
@@ -9621,81 +11344,99 @@ nv.models.sparklinePlus = function() {
.height(availableHeight);
sparklineWrap
- .style('stroke', function(d, i){ return d.color || color(d, i) })
.call(sparkline);
//------------------------------------------------------------
+ var valueWrap = g.select('.nv-valueWrap');
+
+ var value = valueWrap.selectAll('.nv-currentValue')
+ .data([currentValue]);
+
+ value.enter().append('text').attr('class', 'nv-currentValue')
+ .attr('dx', rightAlignValue ? -8 : 8)
+ .attr('dy', '.9em')
+ .style('text-anchor', rightAlignValue ? 'end' : 'start');
+
+ value
+ .attr('x', availableWidth + (rightAlignValue ? margin.right : 0))
+ .attr('y', alignValue ? function(d) { return y(d) } : 0)
+ .style('fill', sparkline.color()(data[data.length-1], data.length-1))
+ .text(yTickFormat(currentValue));
+
+
gEnter.select('.nv-hoverArea').append('rect')
.on('mousemove', sparklineHover)
.on('click', function() { paused = !paused })
- .on('mouseout', function() { index = null; updateValueLine(); });
+ .on('mouseout', function() { index = []; updateValueLine(); });
+ //.on('mouseout', function() { index = null; updateValueLine(); });
g.select('.nv-hoverArea rect')
.attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })
.attr('width', availableWidth + margin.left + margin.right)
.attr('height', availableHeight + margin.top);
- // if index is not set, default to last point
- //index = typeof index == 'undefined' ? data.length - 1 : index;
- // if index is not set, default to null
- index = typeof index == 'undefined' ? null : index;
- var hoverValue = g.selectAll('.nv-hoverValue').data([index]);
- var hoverG = hoverValue.enter().append('g').attr('class', 'nv-hoverValue');
+ function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way
+ if (paused) return;
- var hoverLine = hoverG.append('line')
- .attr('x1', 0)
- .attr('y1', -margin.top)
- .attr('x2', 0)
- .attr('y2', availableHeight);
+ var hoverValue = g.selectAll('.nv-hoverValue').data(index)
- var hoverX = hoverG.append('text').attr('class', 'nv-xValue')
- .attr('x', -6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'end')
- .attr('dy', '.9em');
+ var hoverEnter = hoverValue.enter()
+ .append('g').attr('class', 'nv-hoverValue')
+ .style('stroke-opacity', 0)
+ .style('fill-opacity', 0);
- var hoverY = hoverG.append('text').attr('class', 'nv-yValue')
- .attr('x', 6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'start')
- .attr('dy', '.9em');
+ hoverValue.exit()
+ .transition().duration(250)
+ .style('stroke-opacity', 0)
+ .style('fill-opacity', 0)
+ .remove();
- updateValueLine();
+ hoverValue
+ .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
+ .transition().duration(250)
+ .style('stroke-opacity', 1)
+ .style('fill-opacity', 1);
+ if (!index.length) return;
- function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way
- if (paused) return;
+ hoverEnter.append('line')
+ .attr('x1', 0)
+ .attr('y1', -margin.top)
+ .attr('x2', 0)
+ .attr('y2', availableHeight);
- hoverValue.data([index])
- //d3.transition(hoverValue)
- hoverValue
- .transition().duration(250)
- .style('stroke-opacity', function(d) { return d === null ? 0 : 1 })
- .style('fill-opacity', function(d) { return d === null ? 0 : 1 });
+ hoverEnter.append('text').attr('class', 'nv-xValue')
+ .attr('x', -6)
+ .attr('y', -margin.top)
+ .attr('text-anchor', 'end')
+ .attr('dy', '.9em')
- if (index == null) return;
- hoverValue
- .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
+ g.select('.nv-hoverValue .nv-xValue')
+ .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));
+
+ hoverEnter.append('text').attr('class', 'nv-yValue')
+ .attr('x', 6)
+ .attr('y', -margin.top)
+ .attr('text-anchor', 'start')
+ .attr('dy', '.9em')
- hoverValue.select('.nv-xValue')
- .text(xTickFormat(sparkline.x()(data[index], index)));
+ g.select('.nv-hoverValue .nv-yValue')
+ .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));
- hoverValue.select('.nv-yValue')
- .text(yTickFormat(sparkline.y()(data[index], index)));
}
function sparklineHover() {
if (paused) return;
- var pos = d3.event.offsetX - margin.left;
+ var pos = d3.mouse(this)[0] - margin.left;
function getClosestIndex(data, x) {
var distance = Math.abs(sparkline.x()(data[0], 0) - x);
@@ -9709,7 +11450,7 @@ nv.models.sparklinePlus = function() {
return closestIndex;
}
- index = getClosestIndex(data, Math.round(x.invert(pos)));
+ index = [getClosestIndex(data, Math.round(x.invert(pos)))];
updateValueLine();
}
@@ -9727,7 +11468,7 @@ nv.models.sparklinePlus = function() {
// expose chart's sub-components
chart.sparkline = sparkline;
- d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale');
+ d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale', 'color');
chart.margin = function(_) {
if (!arguments.length) return margin;
@@ -9762,6 +11503,24 @@ nv.models.sparklinePlus = function() {
return chart;
};
+ chart.showValue = function(_) {
+ if (!arguments.length) return showValue;
+ showValue = _;
+ return chart;
+ };
+
+ chart.alignValue = function(_) {
+ if (!arguments.length) return alignValue;
+ alignValue = _;
+ return chart;
+ };
+
+ chart.rightAlignValue = function(_) {
+ if (!arguments.length) return rightAlignValue;
+ rightAlignValue = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -9800,7 +11559,7 @@ nv.models.stackedArea = function() {
scatter
.size(2.2) // default size
- .sizeDomain([2.2]) // all the same size by default
+ .sizeDomain([2.2,2.2]) // all the same size by default
;
/************************************
@@ -9891,7 +11650,8 @@ nv.models.stackedArea = function() {
var scatterWrap = g.select('.nv-scatterWrap')
.datum(data.filter(function(d) { return !d.disabled }))
- d3.transition(scatterWrap).call(scatter);
+ //d3.transition(scatterWrap).call(scatter);
+ scatterWrap.call(scatter);
@@ -9953,13 +11713,15 @@ nv.models.stackedArea = function() {
seriesIndex: i
});
})
- d3.transition(path.exit())
+ //d3.transition(path.exit())
+ path.exit()
.attr('d', function(d,i) { return zeroArea(d.values,i) })
.remove();
path
.style('fill', function(d,i){ return d.color || color(d, i) })
.style('stroke', function(d,i){ return d.color || color(d, i) });
- d3.transition(path)
+ //d3.transition(path)
+ path
.attr('d', function(d,i) { return area(d.values,i) })
@@ -10134,13 +11896,16 @@ nv.models.stackedAreaChart = function() {
, x //can be accessed via chart.xScale()
, y //can be accessed via chart.yScale()
, yAxisTickFormat = d3.format(',.2f')
+ , state = { style: stacked.style() }
+ , defaultState = null
, noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide')
+ , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
+ , controlWidth = 250
;
xAxis
.orient('bottom')
- .tickPadding(5)
+ .tickPadding(7)
;
yAxis
.orient('left')
@@ -10185,6 +11950,20 @@ nv.models.stackedAreaChart = function() {
chart.update = function() { chart(selection) };
chart.container = this;
+ //set state.disabled
+ state.disabled = data.map(function(d) { return !!d.disabled });
+
+ if (!defaultState) {
+ var key;
+ defaultState = {};
+ for (key in state) {
+ if (state[key] instanceof Array)
+ defaultState[key] = state[key].slice(0);
+ else
+ defaultState[key] = state[key];
+ }
+ }
+
//------------------------------------------------------------
// Display No Data message if there's nothing to show.
@@ -10239,7 +12018,7 @@ nv.models.stackedAreaChart = function() {
if (showLegend) {
legend
- .width( availableWidth * 2 / 3 );
+ .width( availableWidth - controlWidth );
g.select('.nv-legendWrap')
.datum(data)
@@ -10252,7 +12031,7 @@ nv.models.stackedAreaChart = function() {
}
g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + ( availableWidth * 1 / 3 ) + ',' + (-margin.top) +')');
+ .attr('transform', 'translate(' + controlWidth + ',' + (-margin.top) +')');
}
//------------------------------------------------------------
@@ -10269,7 +12048,7 @@ nv.models.stackedAreaChart = function() {
];
controls
- .width( Math.min(280, availableWidth * 1 / 3) )
+ .width( controlWidth )
.color(['#444', '#444', '#444']);
g.select('.nv-controlsWrap')
@@ -10303,7 +12082,8 @@ nv.models.stackedAreaChart = function() {
var stackedWrap = g.select('.nv-stackedWrap')
.datum(data);
- d3.transition(stackedWrap).call(stacked);
+ //d3.transition(stackedWrap).call(stacked);
+ stackedWrap.call(stacked);
//------------------------------------------------------------
@@ -10318,7 +12098,9 @@ nv.models.stackedAreaChart = function() {
g.select('.nv-x.nv-axis')
.attr('transform', 'translate(0,' + availableHeight + ')');
- d3.transition(g.select('.nv-x.nv-axis'))
+ //d3.transition(g.select('.nv-x.nv-axis'))
+ g.select('.nv-x.nv-axis')
+ .transition().duration(0)
.call(xAxis);
yAxis
@@ -10327,7 +12109,9 @@ nv.models.stackedAreaChart = function() {
.tickSize(-availableWidth, 0)
.setTickFormat(stacked.offset() == 'expand' ? d3.format('%') : yAxisTickFormat);
- d3.transition(g.select('.nv-y.nv-axis'))
+ //d3.transition(g.select('.nv-y.nv-axis'))
+ g.select('.nv-y.nv-axis')
+ .transition().duration(0)
.call(yAxis);
//------------------------------------------------------------
@@ -10349,7 +12133,11 @@ nv.models.stackedAreaChart = function() {
return d
});
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
legend.dispatch.on('legendClick', function(d,i) {
@@ -10362,7 +12150,11 @@ nv.models.stackedAreaChart = function() {
});
}
- selection.transition().call(chart);
+ state.disabled = data.map(function(d) { return !!d.disabled });
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
controls.dispatch.on('legendClick', function(d,i) {
@@ -10386,13 +12178,35 @@ nv.models.stackedAreaChart = function() {
break;
}
- selection.transition().call(chart);
+ state.style = stacked.style();
+ dispatch.stateChange(state);
+
+ //selection.transition().call(chart);
+ chart(selection);
});
dispatch.on('tooltipShow', function(e) {
if (tooltips) showTooltip(e, that.parentNode);
});
+ // Update chart from a state object passed to event handler
+ dispatch.on('changeState', function(e) {
+
+ if (typeof e.disabled !== 'undefined') {
+ data.forEach(function(series,i) {
+ series.disabled = e.disabled[i];
+ });
+
+ state.disabled = e.disabled;
+ }
+
+ if (typeof e.style !== 'undefined') {
+ stacked.style(e.style);
+ }
+
+ selection.call(chart);
+ });
+
});
@@ -10502,6 +12316,18 @@ nv.models.stackedAreaChart = function() {
return chart;
};
+ chart.state = function(_) {
+ if (!arguments.length) return state;
+ state = _;
+ return chart;
+ };
+
+ chart.defaultState = function(_) {
+ if (!arguments.length) return defaultState;
+ defaultState = _;
+ return chart;
+ };
+
chart.noData = function(_) {
if (!arguments.length) return noData;
noData = _;
@@ -10509,6 +12335,7 @@ nv.models.stackedAreaChart = function() {
};
yAxis.setTickFormat = yAxis.tickFormat;
+
yAxis.tickFormat = function(_) {
if (!arguments.length) return yAxisTickFormat;
yAxisTickFormat = _;
commit d81ef0a6ec22ddc6ce32eeb2a47754a6f9abb01b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 3 13:42:29 2013 -0700
[BZ 958938] - Dashboard graphs need refresh when switching View/Edit portlet modes.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
index 779c795..9c310ca 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/DashboardView.java
@@ -784,6 +784,7 @@ public class DashboardView extends EnhancedVLayout {
}
this.editForm.markForRedraw();
this.portalLayout.show();
+ redraw();
this.portalLayout.markForRedraw();
}
commit 8737595774416a54383483fdd1678a436226af05
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 3 16:38:56 2013 +0200
Bug 911321 - [EAP 6.1] Reload operation fails in standalone mode
EAP can close the management http connection when receiving a reload operation request. In this case, we will set a specific error message in ASConnection which BaseServerComponent code will be able to detect.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
index 729201f..662d6ef 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/ASConnection.java
@@ -33,6 +33,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
+import org.apache.http.NoHttpResponseException;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
@@ -82,6 +83,8 @@ public class ASConnection {
@Deprecated
public static final String MANAGEMENT = MANAGEMENT_URI;
+ static final String FAILURE_NO_RESPONSE = "The server closed the connection before sending the response";
+
private static final Log LOG = LogFactory.getLog(ASConnection.class);
private static final int MAX_POOLED_CONNECTIONS = 10;
@@ -367,6 +370,16 @@ public class ASConnection {
return operationResult;
+ } catch (NoHttpResponseException e) {
+ // For some operations like reload or shutdown, the server closes the connection before sending the
+ // response. We use a specific description here so that callers can write code to decide what to do
+ // in this situation.
+ Result failure = new Result();
+ failure.setFailureDescription(FAILURE_NO_RESPONSE);
+ failure.setOutcome("failure");
+ failure.setRhqThrowable(e);
+ JsonNode ret = mapper.valueToTree(failure);
+ return ret;
} catch (IOException e) {
Result failure = new Result();
failure.setFailureDescription(e.getMessage());
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
index 6d889c5..b80a39a 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseServerComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,13 +13,12 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7;
import java.io.File;
-import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
@@ -54,6 +53,7 @@ import org.rhq.core.system.ProcessExecutionResults;
import org.rhq.core.system.ProcessInfo;
import org.rhq.core.system.SystemInfo;
import org.rhq.core.util.PropertiesFileUpdate;
+import org.rhq.core.util.StringUtil;
import org.rhq.modules.plugins.jbossas7.helper.HostConfiguration;
import org.rhq.modules.plugins.jbossas7.helper.HostPort;
import org.rhq.modules.plugins.jbossas7.helper.ServerPluginConfiguration;
@@ -492,26 +492,23 @@ public abstract class BaseServerComponent<T extends ResourceComponent<?>> extend
return operationResult;
}
- if (name.equals("shutdown") || name.equals("restart")) {
+ if (name.equals("shutdown") || name.equals("restart") || name.equals("reload")) {
/*
- * Shutdown needs a special treatment, because after sending the operation, if shutdown succeeds,
- * the server connection is closed and we can't read from it. So if we get connection refused for
- * reading, this is a good sign.
+ * Shutdown, restart and reload need a special treatment, because after sending the operation, event if
+ * it succeeds, the server connection is sometimes closed and we can't read from it.
*/
if (!res.isSuccess()) {
- if (res.getRhqThrowable() != null
- && (res.getRhqThrowable() instanceof ConnectException || res.getRhqThrowable().getMessage()
- .equals("Connection refused"))) {
+ if (StringUtil.isNotBlank(res.getFailureDescription())
+ && res.getFailureDescription().startsWith(ASConnection.FAILURE_NO_RESPONSE)) {
operationResult.setSimpleResult("Success");
- log.debug("Got a ConnectionRefused for operation "
- + name
- + " this is considered ok, as the remote server sometimes closes the communications channel before sending a reply");
- }
- if (res.getFailureDescription().contains("Socket closed")) { // See https://issues.jboss.org/browse/AS7-4192
- operationResult.setSimpleResult("Success");
- log.debug("Got a 'Socket closed' result from AS for operation " + name);
- } else
+ if (log.isDebugEnabled()) {
+ log.debug("Got no response for operation '" + name + "'. "
+ + "This is considered ok, as the remote server sometimes closes the communications "
+ + "channel before sending a reply");
+ }
+ } else {
operationResult.setErrorMessage(res.getFailureDescription());
+ }
} else {
operationResult.setSimpleResult("Success");
}
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
index 778d127..d399d1b 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/StandaloneASComponent.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7;
@@ -213,7 +213,9 @@ public class StandaloneASComponent<T extends ResourceComponent<?>> extends BaseS
count++;
}
- log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+ if (log.isDebugEnabled()) {
+ log.debug("waitUntilReloaded: Used " + count + " delay round(s) to reload. Reload=" + reloaded);
+ }
return reloaded;
}
commit 1ad9d648c0c90774d4a3379d54802c7ecd771b97
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Fri May 3 10:44:30 2013 +0200
as7plugin: LD_LIBRARY_PATH is not necessarily discovered in Linux environment
diff --git a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
index 7aa92b6..f34a554 100644
--- a/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
+++ b/modules/plugins/jboss-as-7/src/test/java/org/rhq/modules/plugins/jbossas7/itest/AbstractServerComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.modules.plugins.jbossas7.itest;
@@ -205,14 +205,6 @@ public abstract class AbstractServerComponentTest extends AbstractJBossAS7Plugin
String[] pathElements = path.split(File.pathSeparator);
Assert.assertTrue(pathElements.length >= 1);
Assert.assertTrue(new File(pathElements[0]).isDirectory());
-
- if (File.separatorChar == '/') {
- String ldLibraryPath = env.get("LD_LIBRARY_PATH");
- Assert.assertNotNull(ldLibraryPath);
- String[] ldLibraryPathElements = ldLibraryPath.split(File.pathSeparator);
- Assert.assertTrue(ldLibraryPathElements.length >= 1);
- Assert.assertTrue(new File(ldLibraryPathElements[0]).isDirectory());
- }
}
protected abstract String getBindAddressSystemPropertyName();
commit 059c8c96f82bf1c20863fde8ba334b95b5a98687
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 2 11:46:26 2013 -0700
[BZ 958734] - Add autogroup metric to dashboard fails for d3 graphs. Turned off the autogroups right click menu to create dashboard graphs from resource tree as the full fix for this is risky given we are releasing 4.7 straightaway.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
index 87c73c2..0fe3cd9 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
@@ -247,156 +247,161 @@ public class ResourceGroupContextMenu extends Menu {
addItem(operations);
// Metric graph addition menu
- addItem(buildMetricsMenu(resourceType));
+ addItem(buildMetricsMenu(resourceType, group));
}
- private MenuItem buildMetricsMenu(final ResourceType type) {
+ private MenuItem buildMetricsMenu(final ResourceType type, final ResourceGroup resourceGroup) {
MenuItem measurements = new MenuItem(MSG.view_tree_common_contextMenu_measurements());
final Menu measurementsSubMenu = new Menu();
DashboardCriteria criteria = new DashboardCriteria();
- GWTServiceLookup.getDashboardService().findDashboardsByCriteria(criteria,
- new AsyncCallback<PageList<Dashboard>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_dashboards(),
- caught);
- }
-
- public void onSuccess(PageList<Dashboard> result) {
-
- if (type.getMetricDefinitions() != null) {
- //sort the display items alphabetically
- TreeSet<String> ordered = new TreeSet<String>();
- Map<String, MeasurementDefinition> definitionMap = new HashMap<String, MeasurementDefinition>();
- for (MeasurementDefinition m : type.getMetricDefinitions()) {
- ordered.add(m.getDisplayName());
- definitionMap.put(m.getDisplayName(), m);
- }
-
- for (String displayName : ordered) {
- final MeasurementDefinition def = definitionMap.get(displayName);
- //only add menu items for Measurement
- if (def.getDataType().equals(DataType.MEASUREMENT)) {
- MenuItem defItem = new MenuItem(def.getDisplayName());
- measurementsSubMenu.addItem(defItem);
- Menu defSubItem = new Menu();
- defItem.setSubmenu(defSubItem);
-
- for (final Dashboard d : result) {
- MenuItem addToDBItem = new MenuItem(MSG
- .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
- defSubItem.addItem(addToDBItem);
-
- addToDBItem.addClickHandler(new ClickHandler() {
- public void onClick(MenuItemClickEvent menuItemClickEvent) {
-
- DashboardPortlet p = new DashboardPortlet(MSG
- .view_tree_common_contextMenu_groupGraph(),
- ResourceGroupD3GraphPortlet.KEY, 250);
- p.getConfiguration().put(
- new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
- group.getId()));
- p.getConfiguration().put(
- new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
- .getId()));
-
- d.addPortlet(p);
-
- GWTServiceLookup.getDashboardService().storeDashboard(d,
- new AsyncCallback<Dashboard>() {
- public void onFailure(Throwable caught) {
- CoreGUI
- .getErrorHandler()
- .handleError(
- MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
- caught);
- }
-
- public void onSuccess(Dashboard result) {
- String msg = MSG
- .view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
- .getName());
- CoreGUI.getMessageCenter().notify(
- new Message(msg, Message.Severity.Info));
- }
- });
-
- }
- });
-
- //add new menu item for adding current graphable element to view if on Monitor/Graphs tab
- String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/NewGraphs") > -1) {
- MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
- defSubItem.addItem(addGraphItem);
+ final EntityContext context = EntityContext.forGroup(resourceGroup);
+ if(!context.isAutoGroup()){
+
+ GWTServiceLookup.getDashboardService().findDashboardsByCriteria(criteria,
+ new AsyncCallback<PageList<Dashboard>>() {
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_dashboards(),
+ caught);
+ }
- addGraphItem.addClickHandler(new ClickHandler() {
+ public void onSuccess(PageList<Dashboard> result) {
+
+ if (type.getMetricDefinitions() != null) {
+ //sort the display items alphabetically
+ TreeSet<String> ordered = new TreeSet<String>();
+ Map<String, MeasurementDefinition> definitionMap = new HashMap<String, MeasurementDefinition>();
+ for (MeasurementDefinition m : type.getMetricDefinitions()) {
+ ordered.add(m.getDisplayName());
+ definitionMap.put(m.getDisplayName(), m);
+ }
+
+ for (String displayName : ordered) {
+ final MeasurementDefinition def = definitionMap.get(displayName);
+ //only add menu items for Measurement
+ if (def.getDataType().equals(DataType.MEASUREMENT)) {
+ MenuItem defItem = new MenuItem(def.getDisplayName());
+ measurementsSubMenu.addItem(defItem);
+ Menu defSubItem = new Menu();
+ defItem.setSubmenu(defSubItem);
+
+ for (final Dashboard d : result) {
+
+ MenuItem addToDBItem = new MenuItem(MSG
+ .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
+ defSubItem.addItem(addToDBItem);
+
+ addToDBItem.addClickHandler(new ClickHandler() {
public void onClick(MenuItemClickEvent menuItemClickEvent) {
- //generate javascript to call out to.
- //Ex. menuLayers.hide();addMetric('${metric.resourceId},${metric.scheduleId}')
- String grpGraphElements = "";
- if (isAutoGroup) {
- grpGraphElements += "ag,";
- } else {
- grpGraphElements += "cg,";
- }
- grpGraphElements += group.getId() + "," + def.getId();
- if (isAutoGroup) {//need to postpend the resource type as third element
- grpGraphElements += "," + group.getResourceType().getId();
- }
- //construct portal.war url to access
- String baseUrl = "/resource/common/monitor/visibility/IndicatorCharts.do";
- //No need to rebuild the autogroup url as everything handled as a compatible group now
- // if (isAutoGroup) {
- // //Ex. ?parent=10001&ctype=1013&view=Default
- // baseUrl += "?parent=" + group.getAutoGroupParentResource().getId()
- // + "&ctype="
- // + group.getResourceType().getId();
- // jsCode = "ag," + group.getAutoGroupParentResource().getId() + ","
- // + def.getId() + ","
- // + group.getResourceType().getId();
- // } else {
- //Ex. ?groupId=10001&view=Default
- baseUrl += "?groupId=" + group.getId();
- baseUrl += "&view=Default";
- baseUrl += "&action=addChart&metric=" + grpGraphElements;
- baseUrl += "&view=Default";
- final String url = baseUrl;
- //initiate HTTP request
- final RequestBuilder b = new RequestBuilder(RequestBuilder.GET, baseUrl);
-
- try {
- b.setCallback(new RequestCallback() {
- public void onResponseReceived(final Request request,
- final Response response) {
- Log.trace("Successfully submitted request to add graph to view:"
- + url);
-
- //kick off a page reload.
- String currentViewPath = History.getToken();
- CoreGUI.goToView(currentViewPath, true);
+
+ DashboardPortlet p = new DashboardPortlet(MSG
+ .view_tree_common_contextMenu_groupGraph(),
+ ResourceGroupD3GraphPortlet.KEY, 250);
+ p.getConfiguration().put(
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
+ group.getId()));
+ p.getConfiguration().put(
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
+ .getId()));
+
+ d.addPortlet(p);
+
+ GWTServiceLookup.getDashboardService().storeDashboard(d,
+ new AsyncCallback<Dashboard>() {
+ public void onFailure(Throwable caught) {
+ CoreGUI
+ .getErrorHandler()
+ .handleError(
+ MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
+ caught);
}
- @Override
- public void onError(Request request, Throwable t) {
- Log.trace("Error adding Metric:" + url, t);
+ public void onSuccess(Dashboard result) {
+ String msg = MSG
+ .view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
+ .getName());
+ CoreGUI.getMessageCenter().notify(
+ new Message(msg, Message.Severity.Info));
}
});
- b.send();
- } catch (RequestException e) {
- Log.trace("Error adding Metric:" + url, e);
- }
- }//end of onClick definition
- });//end of onClick Handler definition
- }//end of Monitoring/Graphs view check
- }//end of dashabord iteration
- }//end of check for Measurement
- }//end of metric definition iteration
- }
- }
- });
+ }
+ });
+
+ //add new menu item for adding current graphable element to view if on Monitor/Graphs tab
+ String currentViewPath = History.getToken();
+ if (currentViewPath.contains("Monitoring/NewGraphs")) {
+ MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
+ defSubItem.addItem(addGraphItem);
+
+ addGraphItem.addClickHandler(new ClickHandler() {
+ public void onClick(MenuItemClickEvent menuItemClickEvent) {
+ //generate javascript to call out to.
+ //Ex. menuLayers.hide();addMetric('${metric.resourceId},${metric.scheduleId}')
+ String grpGraphElements = "";
+ if (isAutoGroup) {
+ grpGraphElements += "ag,";
+ } else {
+ grpGraphElements += "cg,";
+ }
+ grpGraphElements += group.getId() + "," + def.getId();
+ if (isAutoGroup) {//need to postpend the resource type as third element
+ grpGraphElements += "," + group.getResourceType().getId();
+ }
+ //construct portal.war url to access
+ String baseUrl = "/resource/common/monitor/visibility/IndicatorCharts.do";
+ //No need to rebuild the autogroup url as everything handled as a compatible group now
+ // if (isAutoGroup) {
+ // //Ex. ?parent=10001&ctype=1013&view=Default
+ // baseUrl += "?parent=" + group.getAutoGroupParentResource().getId()
+ // + "&ctype="
+ // + group.getResourceType().getId();
+ // jsCode = "ag," + group.getAutoGroupParentResource().getId() + ","
+ // + def.getId() + ","
+ // + group.getResourceType().getId();
+ // } else {
+ //Ex. ?groupId=10001&view=Default
+ baseUrl += "?groupId=" + group.getId();
+ baseUrl += "&view=Default";
+ baseUrl += "&action=addChart&metric=" + grpGraphElements;
+ baseUrl += "&view=Default";
+ final String url = baseUrl;
+ //initiate HTTP request
+ final RequestBuilder b = new RequestBuilder(RequestBuilder.GET, baseUrl);
+
+ try {
+ b.setCallback(new RequestCallback() {
+ public void onResponseReceived(final Request request,
+ final Response response) {
+ Log.trace("Successfully submitted request to add graph to view:"
+ + url);
+
+ //kick off a page reload.
+ String currentViewPath = History.getToken();
+ CoreGUI.goToView(currentViewPath, true);
+ }
+
+ @Override
+ public void onError(Request request, Throwable t) {
+ Log.trace("Error adding Metric:" + url, t);
+ }
+ });
+ b.send();
+ } catch (RequestException e) {
+ Log.trace("Error adding Metric:" + url, e);
+ }
+ }//end of onClick definition
+ });//end of onClick Handler definition
+ }//end of Monitoring/Graphs view check
+ }//end of dashabord iteration
+ }//end of check for Measurement
+ }//end of metric definition iteration
+ }
+
+ }
+ });
+ }
measurements.setSubmenu(measurementsSubMenu);
return measurements;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index 72a46a8..071f831 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -757,7 +757,7 @@ public class ResourceTreeView extends EnhancedVLayout {
defItem.setSubmenu(defSubItem);
for (final Dashboard d : result) {
- MenuItem addToDBItem = new MenuItem("d3-"+MSG
+ MenuItem addToDBItem = new MenuItem(MSG
.view_tree_common_contextMenu_addChartToDashboard(d.getName()));
defSubItem.addItem(addToDBItem);
@@ -802,7 +802,7 @@ public class ResourceTreeView extends EnhancedVLayout {
//add new menu item for adding current graphable element to view if on Monitor/Graphs tab
String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/Graphs") > -1) {
+ if (currentViewPath.contains("Monitoring/NewGraphs")) {
MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
defSubItem.addItem(addGraphItem);
commit d6ff5eb184fb65c358c2af40e42d0156f69c1475
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 2 07:47:04 2013 -0700
[BZ 924300] - Time range start date and the date picker disappears on clicking 'Advanced' button on time range selector.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
index 406a4fe..328112f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/measurement/AbstractMeasurementRangeEditor.java
@@ -257,7 +257,7 @@ public abstract class AbstractMeasurementRangeEditor extends DynamicForm impleme
protected void update() {
if (advanced) {
advancedSimpleButton.setTitle(MSG.view_measureRange_simple());
- showItem(ADVANCED_END_ITEM);
+ showItem(ADVANCED_START_ITEM);
showItem(ADVANCED_END_ITEM);
hideItem(SIMPLE_VALUE_ITEM);
hideItem(SIMPLE_UNIT_ITEM);
commit 8e62d50b8edd576ca3b53ecb9c198d9df288b35d
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Thu May 2 12:55:57 2013 +0200
Bug 952652 - Unable to delete a user who has saved searches objects in the database
Now deleting saved searches prior to deleting the user.
Merged delete methods.
Fail fast if caller tries to delete a superuser.
Added itest for the BZ
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
index 4b17dc5..9f204dd 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/auth/test/SubjectManagerBeanTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.auth.test;
@@ -41,6 +41,8 @@ import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.SubjectCriteria;
+import org.rhq.core.domain.search.SavedSearch;
+import org.rhq.core.domain.search.SearchSubsystem;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
@@ -50,6 +52,7 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.PermissionException;
import org.rhq.enterprise.server.authz.RoleManagerLocal;
+import org.rhq.enterprise.server.search.SavedSearchManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -70,12 +73,14 @@ public class SubjectManagerBeanTest extends AbstractEJB3Test {
private SubjectManagerLocal subjectManager;
private AuthorizationManagerLocal authorizationManager;
private RoleManagerLocal roleManager;
+ private SavedSearchManagerLocal savedSearchManager;
@Override
protected void beforeMethod() {
subjectManager = LookupUtil.getSubjectManager();
authorizationManager = LookupUtil.getAuthorizationManager();
roleManager = LookupUtil.getRoleManager();
+ savedSearchManager = LookupUtil.getSavedSearchManager();
createITestSubject();
}
@@ -756,4 +761,24 @@ public class SubjectManagerBeanTest extends AbstractEJB3Test {
}
});
}
-}
\ No newline at end of file
+
+ public void shouldBeAbleToDeleteASubjectWhoOwnsASavedSearch() {
+ // See https://bugzilla.redhat.com/show_bug.cgi?id=952652
+ SavedSearch savedSearch = new SavedSearch(SearchSubsystem.GROUP, "fake saved search", "pipo", subjectManager.getSubjectByName(ITEST_USER));
+ Integer savedSearchId = savedSearchManager.createSavedSearch(subjectManager.getOverlord(), savedSearch);
+ boolean subjectDeleted = false;
+ try {
+ deleteITestSubject();
+ subjectDeleted = true;
+ } catch (Exception e) {
+ LOG.error("Failed to delete a subject who owns a saved search", e);
+ fail("Failed to delete a subject who owns a saved search");
+ } finally {
+ // This is only necessary if we failed to delete subject
+ if (!subjectDeleted) {
+ savedSearchManager.deleteSavedSearch(subjectManager.getOverlord(), savedSearchId);
+ }
+ }
+ }
+
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
index c78a1bd..43d955f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/auth/SubjectManagerBean.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2012 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.auth;
@@ -59,8 +59,10 @@ import org.rhq.core.domain.common.composite.SystemSettings;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.RoleCriteria;
+import org.rhq.core.domain.criteria.SavedSearchCriteria;
import org.rhq.core.domain.criteria.SubjectCriteria;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.search.SavedSearch;
import org.rhq.core.domain.server.PersistenceUtility;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -75,6 +77,7 @@ import org.rhq.enterprise.server.core.CustomJaasDeploymentServiceMBean;
import org.rhq.enterprise.server.exception.LoginException;
import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
+import org.rhq.enterprise.server.search.SavedSearchManagerLocal;
import org.rhq.enterprise.server.system.SystemManagerLocal;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
@@ -117,6 +120,9 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
//@IgnoreDependency
private RepoManagerLocal repoManager;
+ @EJB
+ private SavedSearchManagerLocal savedSearchManager;
+
@Resource
private TimerService timerService;
@@ -661,6 +667,10 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
throw new PermissionException("You cannot remove yourself: " + doomedSubject.getName());
}
+ if (authorizationManager.isSystemSuperuser(doomedSubject)) {
+ throw new PermissionException("You cannot delete a system root user - they must always exist");
+ }
+
Set<Role> roles = doomedSubject.getRoles();
doomedSubject.setRoles(new HashSet<Role>()); // clean out roles
@@ -694,7 +704,20 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
}
}
- deleteSubject(doomedSubject);
+ // Delete searches saved by this user
+ SavedSearchCriteria savedSearchCriteria = new SavedSearchCriteria();
+ savedSearchCriteria.addFilterSubjectId(doomedSubjectId);
+ savedSearchCriteria.clearPaging();
+ PageList<SavedSearch> savedSearches = savedSearchManager.findSavedSearchesByCriteria(subject, savedSearchCriteria);
+ for (SavedSearch savedSearch : savedSearches) {
+ savedSearchManager.deleteSavedSearch(subject, savedSearch.getId());
+ }
+
+ alertNotificationManager.cleanseAlertNotificationBySubject(doomedSubject.getId());
+
+ repoManager.removeOwnershipOfSubject(doomedSubject.getId());
+
+ entityManager.remove(doomedSubject);
}
return;
@@ -709,27 +732,6 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
}
/**
- * Deletes the given {@link Subject} from the database.
- *
- *
- * @param doomedSubject identifies the subject to delete
- *
- * @throws PermissionException if caller tried to delete a system superuser
- */
- private void deleteSubject(Subject doomedSubject) throws PermissionException {
- if (authorizationManager.isSystemSuperuser(doomedSubject)) {
- throw new PermissionException("You cannot delete a system root user - they must always exist");
- }
-
- alertNotificationManager.cleanseAlertNotificationBySubject(doomedSubject.getId());
- repoManager.removeOwnershipOfSubject(doomedSubject.getId());
-
- entityManager.remove(doomedSubject);
-
- return;
- }
-
- /**
* Delete a user's principal from the internal database.
*
*
@@ -883,4 +885,4 @@ public class SubjectManagerBean implements SubjectManagerLocal, SubjectManagerRe
return;
}
-}
\ No newline at end of file
+}
commit 248cb85b93eadfe328fc4f8e0ab708239a813610
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 16:50:11 2013 -0700
Javascript console object is not valid under IE8 removing console.log statement.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
index 7390349..75ce6e3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphIE8Impl.java
@@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.common.charttype;
/**
* Contains the javascript chart definition for an IE8 d3 Stacked Bar graph chart.
+ * Curr
*
* @author Mike Thompson
*/
@@ -39,8 +40,7 @@ public final class StackedBarMetricGraphIE8Impl extends StackedBarMetricGraphImp
*/
@Override
public native void drawJsniChart() /*-{
- console.log("Using StackedBarMetricGraphIE8Impl for IE8.");
-
+ // no-op implementation for ie8
}-*/;
}
commit 339eb402b41277d45bb32b8b6da837cb02c2f38e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 14:59:58 2013 -0700
Fix to keep IE9 from behaving like IE8 with respect to charting.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
index d682a24..d942b8c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractD3GraphListView.java
@@ -38,8 +38,8 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
* and User Preferences pickers for the date range.
*/
public abstract class AbstractD3GraphListView extends EnhancedVLayout implements AutoRefresh {
- protected static int SINGLE_CHART_HEIGHT = 225;
- protected static int MULTI_CHART_HEIGHT = 195;
+ protected final static int SINGLE_CHART_HEIGHT = 225;
+ protected final static int MULTI_CHART_HEIGHT = 195;
protected List<Availability> availabilityList;
protected List<ResourceGroupAvailability> groupAvailabilityList;
protected AvailabilityD3Graph availabilityGraph;
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index f3c93be..d5ae804 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -36,6 +36,10 @@
</any>
</replace-with>
+ <replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl">
+ <when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
+ </replace-with>
+
<replace-with class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphIE8Impl">
<when-type-is class="org.rhq.enterprise.gui.coregui.client.inventory.common.charttype.StackedBarMetricGraphImpl"/>
<when-property-is name="user.agent" value="ie8"/>
commit 93a7c3264c30a6ea08d2c767fa6f087a3a86aa1d
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 1 07:54:40 2013 -0700
Fix IE issues with "Move jquery(1.7.2) library out of CoreGUI.gwt.xml now that we don't have GFlot dependency (GFlot was removed with addition of d3 charts)."
This reverts commit 8c54ef01abaa6790f49f96c492fe6649a0245a6f.
Revert "UI Performance - Move non-essential javascripts (like charting) out of CoreGUI.gwt.xml to CoreGUI.html and add the 'defer' script evaluation attribute for faster page load time. Also moved stylesheets to load ahead of javascripts as they load faster and provide less blocking time than the external javascripts. This shaved about 0.5 sec on my box will probably save more on slower hardware/connection/mobile. The *.gwt.xml prevents race conditions at the expense of speed so moving out increases startup speed."
This commit has unintended consequences for IE9 browser. Javascript
libraries that are supposed to be loaded are not (although this works in
other browsers).
This reverts commit e4ac4b1b628ae5e577510045ead7967a603d4c1c.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 7d50e87..f3c93be 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,6 +46,17 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
+ <!-- External javascript libraries -->
+ <!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
+ embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
+ the version of jquery (1.7.2).
+ -->
+ <script src="/coregui/js/jquery-1.7.2.min.js"/>
+ <script src="/coregui/js/jquery.sparkline-2.1.min.js"/>
+ <script src="/coregui/js/d3.v3.js"/>
+ <script src="/coregui/js/nv.d3.js"/>
+ <script src="/coregui/js/jquery.tipsy.js"/>
+
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 1b69b53..206b586 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -10,19 +10,7 @@
<!-- support internationalized characters -->
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
- <link rel="stylesheet" href="CoreGUI.css">
- <link rel="stylesheet" href="css/nv.d3.css">
- <link rel="stylesheet" href="css/tipsy.css">
- <link rel="stylesheet" href="css/charts.css">
-
- <script defer="defer" type="text/javascript" src="/coregui/js/rhq.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/d3.v3.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/nv.d3.js"></script>
- <!-- jquery dependent js libs -->
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery-1.7.2.min.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.tipsy.js"></script>
-
+ <script type="text/javascript" src="js/rhq.js"></script>
<script type="text/javascript">
var search = location.search;
// only do this if you have not specified locale as query param
@@ -42,6 +30,12 @@
var isomorphicDir = "org.rhq.enterprise.gui.coregui.CoreGUI/sc/";
</script>
+
+ <link rel="stylesheet" href="CoreGUI.css">
+ <link rel="stylesheet" href="css/nv.d3.css">
+ <link rel="stylesheet" href="css/tipsy.css">
+ <link rel="stylesheet" href="css/charts.css">
+
</head>
<body>
commit 4c50679d28c84c2d0057c2438bb985c562fc8ac5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed May 1 12:14:40 2013 -0400
BZ 893609 - remove temp workaround code now that we are on a newer EAP that doesn't have the bad issues anymore
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 9a766f4..8cef6e1 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -46,6 +46,29 @@ public class CoreJBossASClient extends JBossASClient {
}
/**
+ * Given a string with possible ${x} expressions in it, this will resolve that expression
+ * using system property values that are set within the AS JVM itself. If the string
+ * to resolve has no expressions, or has no expressions that are resolveable, the expression
+ * string itself is returned as-is (this includes if <code>expression</code> is <code>null</code>).
+ *
+ * @param expression string containing zero, one or more ${x} expressions to be resolved
+ * @return the expression with the expressions resolved using system properties of the AS JVM
+ * @throws Exception if failed to resolve the expression.
+ */
+ public String resolveExpression(String expression) throws Exception {
+ if (expression == null || expression.length() == 0) {
+ return expression;
+ }
+ final ModelNode request = createRequest("resolve-expression", Address.root());
+ request.get("expression").set(expression);
+ final ModelNode response = execute(request);
+ if (!isSuccess(response)) {
+ throw new FailureException(response);
+ }
+ return getResults(response).asString();
+ }
+
+ /**
* This returns the system properties that are set in the AS JVM. This is not the system properties
* in the JVM of this client object - it is actually the system properties in the remote
* JVM of the AS instance that the client is talking to.
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
index babe373..ee7466e 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/LoggingJBossASClient.java
@@ -72,7 +72,7 @@ public class LoggingJBossASClient extends JBossASClient {
final ModelNode request;
if (isLogger(loggerName)) {
- request = createWriteAttributeRequest("level", level.toUpperCase(), addr);
+ request = createWriteAttributeRequest("level", level, addr);
} else {
final String dmrTemplate = "" //
+ "{" //
@@ -80,7 +80,7 @@ public class LoggingJBossASClient extends JBossASClient {
+ ", \"level\" => \"%s\" " //
+ ", \"use-parent-handlers\" => \"true\" " //
+ "}";
- final String dmr = String.format(dmrTemplate, loggerName, level.toUpperCase());
+ final String dmr = String.format(dmrTemplate, loggerName, level);
request = ModelNode.fromString(dmr);
request.get(OPERATION).set(ADD);
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
index f977f0a..5caa45e 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/SecurityDomainJBossASClient.java
@@ -26,6 +26,7 @@ import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
/**
* Provides convenience methods associated with security domain management.
@@ -71,49 +72,6 @@ public class SecurityDomainJBossASClient extends JBossASClient {
* Create a new security domain using the SecureIdentity authentication method.
* This is used when you want to obfuscate a database password in the configuration.
*
- * @param securityDomainName the name of the new security domain
- * @param username the username associated with the security domain
- * @param password the value of the password to store in the configuration (e.g. the obfuscated password itself)
- *
- * @throws Exception if failed to create security domain
- */
- public void createNewSecureIdentitySecurityDomain71(String securityDomainName, String username, String password)
- throws Exception {
-
- Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN, securityDomainName);
- ModelNode addTopNode = createRequest(ADD, addr);
- addTopNode.get(CACHE_TYPE).set("default");
-
- ModelNode addAuthNode = createRequest(ADD, addr.clone().add(AUTHENTICATION, CLASSIC));
- ModelNode loginModulesNode = addAuthNode.get(LOGIN_MODULES);
- ModelNode loginModule = new ModelNode();
- loginModule.get(CODE).set("SecureIdentity");
- loginModule.get(FLAG).set("required");
- ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
- moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
- loginModulesNode.add(loginModule);
-
- ModelNode batch = createBatchRequest(addTopNode, addAuthNode);
-
- System.err.println("== security domain ==> " + batch.toJSONString(false));
-
- ModelNode results = execute(batch);
- if (!isSuccess(results)) {
- throw new FailureException(results, "Failed to create security domain [" + securityDomainName + "]");
- }
-
- return;
- }
-
- /**
- * Create a new security domain using the SecureIdentity authentication method.
- * This is used when you want to obfuscate a database password in the configuration.
- *
* This is the version for as7.2+ (e.g. eap 6.1)
*
* @param securityDomainName the name of the new security domain
@@ -139,11 +97,8 @@ public class SecurityDomainJBossASClient extends JBossASClient {
loginModule.get(FLAG).set("required");
ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
+ addPossibleExpression(moduleOptions, USERNAME, username);
+ addPossibleExpression(moduleOptions, PASSWORD, password);
ModelNode batch = createBatchRequest(addTopNode, addAuthNode, loginModule);
@@ -178,11 +133,8 @@ public class SecurityDomainJBossASClient extends JBossASClient {
loginModule.get(FLAG).set("required");
ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
moduleOptions.setEmptyList();
- // TODO: we really want to use addExpression (e.g. ${rhq.server.database.user-name})
- // for username and password so rhq-server.properties can be used to set these.
- // However, AS7.1 doesn't support this yet - see https://issues.jboss.org/browse/AS7-5177
- moduleOptions.add(USERNAME, username);
- moduleOptions.add(PASSWORD, password);
+ addPossibleExpression(moduleOptions, USERNAME, username);
+ addPossibleExpression(moduleOptions, PASSWORD, password);
// login modules attribute must be a list - we only have one item in it, the loginModule
ModelNode loginModuleList = new ModelNode();
@@ -202,6 +154,14 @@ public class SecurityDomainJBossASClient extends JBossASClient {
return;
}
+ private void addPossibleExpression(ModelNode node, String name, String value) {
+ if (value != null && value.contains("${")) {
+ node.add(name, new ModelNode(ModelType.EXPRESSION).setExpression(value));
+ } else {
+ node.add(name, value);
+ }
+ }
+
/**
* Given the name of an existing security domain that uses the SecureIdentity authentication method,
* this returns the module options for that security domain authentication method. This includes
@@ -231,49 +191,6 @@ public class SecurityDomainJBossASClient extends JBossASClient {
/**
* Create a new security domain using the database server authentication method.
* This is used when you want to directly authenticate against a db entry.
- *
- * @param securityDomainName the name of the new security domain
- * @param dsJndiName the jndi name for the datasource to query against
- * @param principalsQuery the SQL query for selecting password info for a principal
- * @param rolesQuery the SQL query for selecting role info for a principal
- * @param hashAlgorithm if null defaults to "MD5"
- * @param hashEncoding if null defaults to "base64"
- * @throws Exception if failed to create security domain
- */
- public void createNewDatabaseServerSecurityDomain71(String securityDomainName, String dsJndiName,
- String principalsQuery, String rolesQuery, String hashAlgorithm,
- String hashEncoding) throws Exception {
-
- Address addr = Address.root().add(SUBSYSTEM, SUBSYSTEM_SECURITY, SECURITY_DOMAIN, securityDomainName);
- ModelNode addTopNode = createRequest(ADD, addr);
- addTopNode.get(CACHE_TYPE).set("default");
-
- ModelNode addAuthNode = createRequest(ADD, addr.clone().add(AUTHENTICATION, CLASSIC));
- ModelNode loginModulesNode = addAuthNode.get(LOGIN_MODULES);
- ModelNode loginModule = new ModelNode();
- loginModule.get(CODE).set("Database");
- loginModule.get(FLAG).set("required");
- ModelNode moduleOptions = loginModule.get(MODULE_OPTIONS);
- moduleOptions.setEmptyList();
- moduleOptions.add(DS_JNDI_NAME, dsJndiName);
- moduleOptions.add(PRINCIPALS_QUERY, principalsQuery);
- moduleOptions.add(ROLES_QUERY, rolesQuery);
- moduleOptions.add(HASH_ALGORITHM, (null == hashAlgorithm ? "MD5" : hashAlgorithm));
- moduleOptions.add(HASH_ENCODING, (null == hashEncoding ? "base64" : hashEncoding));
- loginModulesNode.add(loginModule);
-
- ModelNode batch = createBatchRequest(addTopNode, addAuthNode);
- ModelNode results = execute(batch);
- if (!isSuccess(results)) {
- throw new FailureException(results, "Failed to create security domain [" + securityDomainName + "]");
- }
-
- return;
- }
-
- /**
- * Create a new security domain using the database server authentication method.
- * This is used when you want to directly authenticate against a db entry.
* This is for AS 7.2+ (e.g. EAP 6.1) and works around https://issues.jboss.org/browse/AS7-6527
*
* @param securityDomainName the name of the new security domain
diff --git a/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh b/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
index fbbc397..5369ab2 100755
--- a/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
+++ b/modules/enterprise/server/appserver/src/main/dev-resources/bin/rhq-autoinstall.sh
@@ -18,8 +18,6 @@ do
eval ${_INSTALLER_SCRIPT}
if [ "$?" -eq "0" ]; then
echo Installer finished
- # most times, the installation was already done, but see if changes to rhq-server.properties requires a reconfiguration
- eval ${_INSTALLER_SCRIPT} --reconfig
break;
elif [ "$?" -eq "1" ]; then
echo The installer has been disabled - please fix rhq-server.properties
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index 20ff84b..05619cb 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -495,16 +495,17 @@ rhq.communications.multicast-detector.port=16162
# Server-side SSL Security Configuration for HTTPS thru Tomcat
# These are used for browser https access and
# for incoming messages from agents over sslservlet transport.
-# Relative filenames are relative to jboss.server.config.dir.
-# [you cannot use ${x} variables in these rhq.server.tomcat settings]
+# [Due to issue https://issues.jboss.org/browse/WFLY-1177, you cannot change
+# rhq.server.tomcat.security.keystore.file or rhq.server.tomcat.security.truststore.file
+# after you install RHQ. If you need to change those again, you must manually do so in standalone-full.xml.]
rhq.server.tomcat.security.client-auth-mode=false
rhq.server.tomcat.security.secure-socket-protocol=TLS
rhq.server.tomcat.security.algorithm=SunX509
rhq.server.tomcat.security.keystore.alias=RHQ
-rhq.server.tomcat.security.keystore.file=rhq.keystore
+rhq.server.tomcat.security.keystore.file=${jboss.server.config.dir}/rhq.keystore
rhq.server.tomcat.security.keystore.password=RHQManagement
rhq.server.tomcat.security.keystore.type=JKS
-rhq.server.tomcat.security.truststore.file=rhq.truststore
+rhq.server.tomcat.security.truststore.file=${jboss.server.config.dir}/rhq.truststore
rhq.server.tomcat.security.truststore.password=RHQManagement
rhq.server.tomcat.security.truststore.type=JKS
@@ -637,32 +638,11 @@ rhq.sync.endpoint-address=false
</replace>
</target>
- <!-- This is so we can work around all the issues due to https://issues.jboss.org/browse/AS7-6120
- so once that is fixed, we don't have to run the installer "reconfig" automatically on startup of the server.
- Note that if we predeploy (i.e. are doing a dev build), rather than jump through more hoops for this,
- just assume the developer knows that if they change rhq-server.properties, they have to reconfig the server.
- We don't do anything in this target if we are building a dev build. -->
- <target name="add-auto-reconfig" unless="predeploy">
- <echo>Add auto-reconfig to rhq-server scripts so users don't have to when changing rhq-server.properties</echo>
- <replace file="${project.build.outputDirectory}/bin/rhq-server.sh">
- <replacefilter>
- <replacetoken># START SERVER</replacetoken>
- <replacevalue><![CDATA[export RHQ_SERVER_HOME; ${RHQ_SERVER_HOME}/bin/rhq-installer.sh --reconfig &]]></replacevalue>
- </replacefilter>
- </replace>
- <replace file="${project.build.outputDirectory}/bin/rhq-server.bat">
- <replacefilter>
- <replacetoken>rem START SERVER</replacetoken>
- <replacevalue><![CDATA[start /B %RHQ_SERVER_HOME%\bin\rhq-installer.bat --reconfig < nul > nul]]></replacevalue>
- </replacefilter>
- </replace>
- </target>
<target name="prepare-release"
description="If this is a release build, make sure it is properly prepared."
depends="initialize,
developer-release-message,
copy-dev-resources,
- add-auto-reconfig,
fix-perms,
deploy-postgres-ds,
deploy-oracle-ds">
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
index 26bc2f6..36da859 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/Installer.java
@@ -47,7 +47,7 @@ public class Installer {
private InstallerConfiguration installerConfig;
private enum WhatToDo {
- DISPLAY_USAGE, DO_NOTHING, RECONFIGURE, TEST, SETUPDB, LIST_SERVERS, INSTALL
+ DISPLAY_USAGE, DO_NOTHING, TEST, SETUPDB, LIST_SERVERS, INSTALL
}
public static void main(String[] args) {
@@ -108,20 +108,6 @@ public class Installer {
}
continue;
}
- case RECONFIGURE: {
- try {
- final InstallerService installerService = new InstallerServiceImpl(installerConfig);
- final HashMap<String, String> serverProperties = installerService.getServerProperties();
- final boolean reconfigured = installerService.reconfigure(serverProperties);
- if (reconfigured) {
- LOG.info("Reconfiguration is complete.");
- }
- } catch (Exception e) {
- LOG.error(ThrowableUtil.getAllMessages(e));
- System.exit(EXIT_CODE_INSTALLATION_ERROR);
- }
- continue;
- }
case INSTALL: {
try {
final InstallerService installerService = new InstallerServiceImpl(installerConfig);
@@ -159,28 +145,25 @@ public class Installer {
usage.append("\t--force, -f: force the installer to try to install everything").append("\n");
usage.append("\t--listservers, -l: show list of known installed servers (install not performed)").append("\n");
usage.append("\t--setupdb, -b: only perform database schema creation or update").append("\n");
- usage.append("\t--reconfig, -r: resets some configuration settings in an installed server").append("\n");
usage.append("\t--dbpassword, -d: encodes a DB password for rhq-server.properties (install not performed)")
.append("\n");
LOG.info(usage);
}
private WhatToDo[] processArguments(String[] args) throws Exception {
- String sopts = "-:HD:h:p:d:bflrt";
+ String sopts = "-:HD:h:p:d:bflt";
LongOpt[] lopts = { new LongOpt("help", LongOpt.NO_ARGUMENT, null, 'H'),
new LongOpt("host", LongOpt.REQUIRED_ARGUMENT, null, 'h'),
new LongOpt("port", LongOpt.REQUIRED_ARGUMENT, null, 'p'),
new LongOpt("dbpassword", LongOpt.REQUIRED_ARGUMENT, null, 'd'),
new LongOpt("setupdb", LongOpt.NO_ARGUMENT, null, 'b'),
new LongOpt("listservers", LongOpt.NO_ARGUMENT, null, 'l'),
- new LongOpt("reconfig", LongOpt.NO_ARGUMENT, null, 'r'),
new LongOpt("force", LongOpt.NO_ARGUMENT, null, 'f'),
new LongOpt("test", LongOpt.NO_ARGUMENT, null, 't') };
boolean test = false;
boolean listservers = false;
boolean setupdb = false;
- boolean reconfig = false;
String dbpassword = null;
Getopt getopt = new Getopt("installer", args, sopts, lopts);
@@ -267,11 +250,6 @@ public class Installer {
break; // don't return, we need to allow more args to be processed, like -p or -h
}
- case 'r': {
- reconfig = true;
- break; // don't return, we need to allow more args to be processed, like -p or -h
- }
-
case 't': {
test = true;
break; // don't return, we need to allow more args to be processed, like -p or -h
@@ -286,10 +264,6 @@ public class Installer {
return new WhatToDo[] { WhatToDo.DO_NOTHING };
}
- if (reconfig) {
- return new WhatToDo[] { WhatToDo.RECONFIGURE };
- }
-
if (test || setupdb || listservers) {
ArrayList<WhatToDo> whatToDo = new ArrayList<WhatToDo>();
if (test) {
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
index c1ffa48..6eff4b7 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerService.java
@@ -121,23 +121,6 @@ public interface InstallerService {
String existingSchemaOption) throws Exception;
/**
- * This will take server properties and reconfigure an already-installed server
- * with those values if the settings were previously hardcoded to old values (as opposed to being
- * set to expressions that allow them to be overridden with system property settings).
- * Note that is function is here only to workaround various bugs in AS7
- * that force us to not be able to use expressions in certain app server subsystem attribute
- * settings - see https://issues.jboss.org/browse/AS7-6120. Once this issues are fixed, this
- * method will go away.
- *
- * @param serverProperties the new server properties
- * @return true if the reconfigure was at least attempted; false if the server isn't ready to be reconfigured
- * such as when it hasn't been fully installed yet
- * @throws Exception
- */
- @Deprecated
- boolean reconfigure(HashMap<String, String> serverProperties) throws Exception;
-
- /**
* Returns a list of all registered servers in the database.
*
* @param connectionUrl
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 95b4bc3..8173e68 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -563,81 +563,6 @@ public class InstallerServiceImpl implements InstallerService {
return map;
}
- // This is here only to help users workaround https://issues.jboss.org/browse/AS7-6120.
- // It will go away once all the issues with expression support in AS7 are fixed.
- // Notice in this method we only reconfigure some things - only the subsystems/services
- // that didn't support expressions in their attributes are reconfigured here since it
- // is those whose values are hardcoded and we must alter to pick up changes to
- // rhq-server.properties. All other services can pick up the property value changes
- // make to rhq-server.properties on restart (since rhq-server.properties are system
- // properties set in the AS7 instance via -P option to AS7).
- @Override
- public boolean reconfigure(HashMap<String, String> serverProperties) throws Exception {
-
- // make sure we can connect using our configuration
- testModelControllerClient(serverProperties, 30);
-
- if (null == getInstallationResults()) {
- log("Run the installer on this server.");
- return false;
- }
-
- String appServerConfigDir = getAppServerConfigDir();
- ModelControllerClient mcc = null;
-
- try {
- mcc = getModelControllerClient();
-
- // Before we do anything, let's first make sure we really do need to reconfigure something.
- // Check to see if everything that didn't use expressions is still the same. If so,
- // just skip everything else and return immediate since there is nothing to do. We don't
- // even need to reload/restart the server in this case.
- try {
- if (ServerInstallUtil.isSameDatasourceSecurityDomainExisting(mcc, serverProperties)) {
- if (ServerInstallUtil.isSameMailServiceExisting(mcc, serverProperties)) {
- if (ServerInstallUtil.isSameWebConnectorsExisting(mcc, appServerConfigDir, serverProperties)) {
- if (ServerInstallUtil.isSameLoggingExisting(mcc, serverProperties)) {
- log("Nothing in the configuration changed that requires a reconfig - everything looks OK");
- return true; // nothing to do, return immediately
- }
- }
- }
- }
- } catch (Exception e) {
- log("Cannot determine if the config is the same, will reconfigure just in case", e);
- }
-
- // first, put the server in admin-only mode so we can start changing things around
- CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- coreClient.reload(true);
-
- // not sure if we have to, but see if we need to wait for the reload to finish
- testModelControllerClient(30);
-
- mcc = getModelControllerClient(); // get a new controller
-
- // create the security domain needed by the datasources
- ServerInstallUtil.createDatasourceSecurityDomain(mcc, serverProperties);
-
- // setup the email service
- ServerInstallUtil.setupMailService(mcc, serverProperties);
-
- // setup the secure Tomcat web connectors
- ServerInstallUtil.setupWebConnectors(mcc, appServerConfigDir, serverProperties);
-
- // setup the logging level
- ServerInstallUtil.configureLogging(mcc, serverProperties);
-
- // now restart - don't just reload, some of our stuff won't restart properly if we just reload
- coreClient = new CoreJBossASClient(mcc);
- coreClient.restart();
- } finally {
- safeClose(mcc);
- }
-
- return true;
- }
-
/**
* Makes sure the data is at least in the correct format (booleans are true/false, integers are valid numbers).
*
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
index 687e496..d6e0d10 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/ServerInstallUtil.java
@@ -167,7 +167,7 @@ public class ServerInstallUtil {
LoggingJBossASClient client = new LoggingJBossASClient(mcc);
// we want to create our own category
- String val = buildExpression(ServerProperties.PROP_LOG_LEVEL, serverProperties, false); // enable when AS7-5321 is fixed
+ String val = buildExpression(ServerProperties.PROP_LOG_LEVEL, serverProperties, true);
client.setLoggerLevel("org.rhq", val);
LOG.info("Logging category org.rhq set to [" + val + "]");
}
@@ -209,7 +209,7 @@ public class ServerInstallUtil {
throws Exception {
String fromAddressExpr = buildExpression(ServerProperties.PROP_EMAIL_FROM_ADDRESS, serverProperties, true);
- String smtpHostExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_HOST, serverProperties, false); // enable when AS7-5321 is fixed
+ String smtpHostExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_HOST, serverProperties, true);
String smtpPortExpr = buildExpression(ServerProperties.PROP_EMAIL_SMTP_PORT, serverProperties, true);
// Tweek the mail configuration that comes out of box. Setup a batch request to write the proper attributes.
@@ -283,19 +283,13 @@ public class ServerInstallUtil {
public static void createDatasourceSecurityDomain(ModelControllerClient mcc,
HashMap<String, String> serverProperties) throws Exception {
- final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
- final String obfuscatedPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
+ final String dbUsername = buildExpression(ServerProperties.PROP_DATABASE_USERNAME, serverProperties, true);
+ final String obfuscatedPassword = buildExpression(ServerProperties.PROP_DATABASE_PASSWORD, serverProperties,
+ true);
final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- String asVersion = coreClient.getAppServerVersion();
final String securityDomain = RHQ_DS_SECURITY_DOMAIN;
if (!client.isSecurityDomain(securityDomain)) {
- if (asVersion.startsWith("7.2")) {
- client.createNewSecureIdentitySecurityDomain72(securityDomain, dbUsername, obfuscatedPassword);
- }
- else {
- client.createNewSecureIdentitySecurityDomain71(securityDomain, dbUsername, obfuscatedPassword);
- }
+ client.createNewSecureIdentitySecurityDomain72(securityDomain, dbUsername, obfuscatedPassword);
LOG.info("Security domain [" + securityDomain + "] created");
} else {
LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
@@ -384,21 +378,12 @@ public class ServerInstallUtil {
throws Exception {
final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final CoreJBossASClient coreClient = new CoreJBossASClient(mcc);
- String asRelase = coreClient.getAppServerVersion();
final String securityDomain = RHQ_REST_SECURITY_DOMAIN;
if (!client.isSecurityDomain(securityDomain)) {
String dsJndiName = "java:jboss/datasources/" + RHQ_DATASOURCE_NAME_XA;
- if (asRelase.startsWith("7.2")) {
- client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- }
- else {
- client.createNewDatabaseServerSecurityDomain71(securityDomain, dsJndiName,
- "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
- "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
- }
+ client.createNewDatabaseServerSecurityDomain72(securityDomain, dsJndiName,
+ "SELECT PASSWORD FROM RHQ_PRINCIPAL WHERE principal=?",
+ "SELECT 'all', 'Roles' FROM RHQ_PRINCIPAL WHERE principal=?", null, null);
LOG.info("Security domain [" + securityDomain + "] created");
} else {
LOG.info("Security domain [" + securityDomain + "] already exists, skipping the creation request");
@@ -1256,15 +1241,24 @@ public class ServerInstallUtil {
LOG.info("Creating https connector...");
ConnectorConfiguration connector = buildSecureConnectorConfiguration(configDirStr, serverProperties);
- // verify that we have a truststore file - if user is relying on our self-signed certs, we'll have to create one for them
+ // https://issues.jboss.org/browse/WFLY-1177 - we need to resolve the paths right now. the user won't be able
+ // to change these again in the future unless they go directly into standalone.xml and change it manually
String truststoreFileString = connector.getSslConfiguration().getCaCertificateFile();
+ truststoreFileString = resolveExpression(mcc, truststoreFileString);
+ connector.getSslConfiguration().setCaCertificateFile(truststoreFileString);
+
+ String keystoreFileString = connector.getSslConfiguration().getCertificateKeyFile();
+ keystoreFileString = resolveExpression(mcc, keystoreFileString);
+ connector.getSslConfiguration().setCertificateKeyFile(keystoreFileString);
+
+ // verify that we have a truststore file - if user is relying on our self-signed certs, we'll have to create one for them
if (truststoreFileString == null) {
LOG.warn("Missing a valid truststore location - you must specify a valid truststore location!");
} else {
File truststoreFile = new File(truststoreFileString);
if (!truststoreFile.exists()) {
// user didn't provide a truststore file, copy the keystore and use it as the truststore; tell the user about this
- File keystoreFile = new File(connector.getSslConfiguration().getCertificateKeyFile());
+ File keystoreFile = new File(keystoreFileString);
if (!keystoreFile.isFile()) {
LOG.warn("Missing both keystore [" + keystoreFile + "] and truststore [" + truststoreFile + "]");
} else {
@@ -1283,41 +1277,64 @@ public class ServerInstallUtil {
LOG.info("https connector created.");
if (client.isConnector(connectorName)) {
+ client.changeConnector(connectorName, "max-connections",
+ buildExpression("rhq.server.startup.web.max-connections", serverProperties, true));
client.changeConnector(connectorName, "redirect-port",
- buildExpression("rhq.server.socket.binding.port.https", serverProperties, false));
+ buildExpression("rhq.server.socket.binding.port.https", serverProperties, true));
} else {
LOG.warn("There doesn't appear to be a http connector configured already - this is strange.");
}
}
+ private static String resolveExpression(ModelControllerClient mcc, String expression) {
+ if (expression == null) {
+ return null;
+ }
+
+ CoreJBossASClient client = new CoreJBossASClient(mcc);
+ String resolvedExpression;
+ try {
+ resolvedExpression = client.resolveExpression(expression);
+
+ // https://issues.jboss.org/browse/WFLY-1177 - app server doesn't do recursive resolving, we have to do it here
+ while (resolvedExpression != null && resolvedExpression.contains("${")
+ && !resolvedExpression.equals(expression)) {
+ expression = resolvedExpression;
+ resolvedExpression = client.resolveExpression(expression);
+ }
+ } catch (Exception e) {
+ LOG.warn("Cannot resolve expression [" + expression + "]; will use it as-is but errors may occur later.");
+ resolvedExpression = expression;
+ }
+ return resolvedExpression;
+ }
+
private static ConnectorConfiguration buildSecureConnectorConfiguration(String configDirStr,
HashMap<String, String> serverProperties) {
SSLConfiguration ssl = new SSLConfiguration();
// truststore
- ssl.setCaCertificateFile(getAbsoluteFileLocation("rhq.server.tomcat.security.truststore.file",
- serverProperties, configDirStr)); // this cannot be an expression - AS7 doesn't support that now
+ ssl.setCaCertificateFile(buildExpression("rhq.server.tomcat.security.truststore.file", serverProperties, true));
ssl.setCaCertificationPassword(buildExpression("rhq.server.tomcat.security.truststore.password",
- serverProperties, false));
- ssl.setTruststoreType(buildExpression("rhq.server.tomcat.security.truststore.type", serverProperties, false));
+ serverProperties, true));
+ ssl.setTruststoreType(buildExpression("rhq.server.tomcat.security.truststore.type", serverProperties, true));
// keystore
- ssl.setCertificateKeyFile(getAbsoluteFileLocation("rhq.server.tomcat.security.keystore.file", serverProperties,
- configDirStr)); // this cannot be an expression - AS7 doesn't support that now
- ssl.setPassword(buildExpression("rhq.server.tomcat.security.keystore.password", serverProperties, false));
- ssl.setKeyAlias(buildExpression("rhq.server.tomcat.security.keystore.alias", serverProperties, false));
- ssl.setKeystoreType(buildExpression("rhq.server.tomcat.security.keystore.type", serverProperties, false));
+ ssl.setCertificateKeyFile(buildExpression("rhq.server.tomcat.security.keystore.file", serverProperties, true));
+ ssl.setPassword(buildExpression("rhq.server.tomcat.security.keystore.password", serverProperties, true));
+ ssl.setKeyAlias(buildExpression("rhq.server.tomcat.security.keystore.alias", serverProperties, true));
+ ssl.setKeystoreType(buildExpression("rhq.server.tomcat.security.keystore.type", serverProperties, true));
// SSL protocol config
- ssl.setProtocol(buildExpression("rhq.server.tomcat.security.secure-socket-protocol", serverProperties, false));
- ssl.setVerifyClient(buildExpression("rhq.server.tomcat.security.client-auth-mode", serverProperties, false));
+ ssl.setProtocol(buildExpression("rhq.server.tomcat.security.secure-socket-protocol", serverProperties, true));
+ ssl.setVerifyClient(buildExpression("rhq.server.tomcat.security.client-auth-mode", serverProperties, true));
// note: there doesn't appear to be a way for AS7 to support algorithm, like SunX509 or IbmX509
// so I think it just uses the JVM's default. This means "rhq.server.tomcat.security.algorithm" is unused
ConnectorConfiguration connector = new ConnectorConfiguration();
- connector.setMaxConnections(buildExpression("rhq.server.startup.web.max-connections", serverProperties, false));
+ connector.setMaxConnections(buildExpression("rhq.server.startup.web.max-connections", serverProperties, true));
connector.setScheme("https");
connector.setSocketBinding("https");
connector.setSslConfiguration(ssl);
@@ -1502,159 +1519,4 @@ public class ServerInstallUtil {
}
}
}
-
- /**
- * This checks to see if the logging settings have the same values as those found in the given properties.
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the logging settings
- * @return true if the logging settings have the same values
- * @throws Exception
- */
- public static boolean isSameLoggingExisting(ModelControllerClient mcc, HashMap<String, String> serverProperties) {
- try {
- LoggingJBossASClient client = new LoggingJBossASClient(mcc);
- String currentLevel = client.getLoggerLevel("org.rhq");
- String newLevel = serverProperties.get(ServerProperties.PROP_LOG_LEVEL);
- return !isEmpty(currentLevel) && currentLevel.equalsIgnoreCase(newLevel);
- } catch (Exception e) {
- return false; // assume they aren't the same - this may be due to the category org.rhq just missing
- }
- }
-
- /**
- * This checks to see if the mail service already exists
- * and has the same settings as those found in the given properties.
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the mail service settings
- * @return true if the mail service exists with the same settings
- * @throws Exception
- */
- public static boolean isSameMailServiceExisting(ModelControllerClient mcc, HashMap<String, String> serverProperties)
- throws Exception {
- // we know the only problem attribute we care about is the smtp host - that's the only
- // one we use that doesn't support expressions. So we only need to check this one
- Address addr = Address.root().add("socket-binding-group", "standard-sockets",
- "remote-destination-outbound-socket-binding", "mail-smtp");
- JBossASClient client = new JBossASClient(mcc);
- String currentHost = client.getStringAttribute("host", addr);
- String host = serverProperties.get(ServerProperties.PROP_EMAIL_SMTP_HOST);
- return !isEmpty(currentHost) && currentHost.equals(host);
- }
-
- /**
- * This checks to see if the security domain for the datasources already exists
- * and has the same username/password as those found in the given properties
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param serverProperties contains the obfuscated password and username to compare
- * @return true if the domain exists with the same username and password
- * @throws Exception
- */
- public static boolean isSameDatasourceSecurityDomainExisting(ModelControllerClient mcc,
- HashMap<String, String> serverProperties) throws Exception {
-
- final String dbUsername = serverProperties.get(ServerProperties.PROP_DATABASE_USERNAME);
- final String obfuscatedPassword = serverProperties.get(ServerProperties.PROP_DATABASE_PASSWORD);
- final SecurityDomainJBossASClient client = new SecurityDomainJBossASClient(mcc);
- final String securityDomain = RHQ_DS_SECURITY_DOMAIN;
- boolean sameUsernamePassword = false;
- if (client.isSecurityDomain(securityDomain)) {
- boolean sameUsername = false;
- boolean samePassword = false;
- ModelNode opts;
- opts = client.getSecureIdentitySecurityDomainModuleOptions(securityDomain);
- if (opts != null) {
- List<ModelNode> optsList = opts.asList();
- for (ModelNode opt : optsList) {
- if (opt.has(SecurityDomainJBossASClient.USERNAME)) {
- sameUsername = dbUsername.equals(opt.get(SecurityDomainJBossASClient.USERNAME).asString());
- }
- if (opt.has(SecurityDomainJBossASClient.PASSWORD)) {
- samePassword = obfuscatedPassword.equals(opt.get(SecurityDomainJBossASClient.PASSWORD)
- .asString());
- }
- }
- }
- sameUsernamePassword = sameUsername & samePassword;
- }
- return sameUsernamePassword;
- }
-
- /**
- * This checks to see if the web connectors already exist
- * and have the same settings as those found in the given properties
- *
- * THIS IS ONLY HERE TO SUPPORT INSTALLER --reconfig OPTION WHICH SHOULD
- * GO AWAY ONCE AS7 SUPPORTS EXPRESSIONS WHERE WE NEED THEM - JIRA AS7-5321.
- * ONCE AS7 DOES THIS, THIS METHOD CAN GO AWAY.
- *
- * @param mcc the JBossAS management client
- * @param configDirStr location of a configuration directory where the keystore is to be stored
- * @param serverProperties contains the obfuscated password and username to compare
- * @return true if the domain exists with the same username and password
- * @throws Exception
- */
- public static boolean isSameWebConnectorsExisting(ModelControllerClient mcc, String appServerConfigDir,
- HashMap<String, String> serverProperties) throws Exception {
-
- HashMap<String, String> settingsToCheck = new HashMap<String, String>();
- WebJBossASClient client = new WebJBossASClient(mcc);
-
- // FIRST check the https connector
- ModelNode httpsNode = client.getConnector("https");
-
- ConnectorConfiguration connectorConfig = buildSecureConnectorConfiguration(appServerConfigDir, serverProperties);
- SSLConfiguration sslConfig = connectorConfig.getSslConfiguration();
-
- // check the https connector's main config
- settingsToCheck.clear();
- settingsToCheck.put("max-connections", connectorConfig.getMaxConnections());
- for (Map.Entry<String, String> propToCheck : settingsToCheck.entrySet()) {
- if (!httpsNode.get(propToCheck.getKey()).asString().equals(propToCheck.getValue())) {
- return false; // something is different, no need to check further, return false to say we are different
- }
- }
-
- // now check the https connector's ssl config
- ModelNode sslNode = httpsNode.get("ssl").get("configuration");
- settingsToCheck.clear();
- settingsToCheck.put("ca-certificate-file", sslConfig.getCaCertificateFile());
- settingsToCheck.put("ca-certificate-password", sslConfig.getCaCertificatePassword());
- settingsToCheck.put("certificate-key-file", sslConfig.getCertificateKeyFile());
- settingsToCheck.put("key-alias", sslConfig.getKeyAlias());
- settingsToCheck.put("keystore-type", sslConfig.getKeystoreType());
- settingsToCheck.put("password", sslConfig.getPassword());
- settingsToCheck.put("protocol", sslConfig.getProtocol());
- settingsToCheck.put("truststore-type", sslConfig.getTruststoreType());
- settingsToCheck.put("verify-client", sslConfig.getVerifyClient());
- for (Map.Entry<String, String> propToCheck : settingsToCheck.entrySet()) {
- if (!sslNode.get(propToCheck.getKey()).asString().equals(propToCheck.getValue())) {
- return false; // something is different, no need to check further, return false to say we are different
- }
- }
-
- // SECOND check the http connector
- ModelNode httpNode = client.getConnector("http");
- String nodeString = httpNode.get("redirect-port").asString();
- String propString = serverProperties.get("rhq.server.socket.binding.port.https");
- if (!nodeString.equals(propString)) {
- return false; // something is different, no need to check further, return false to say we are different
- }
-
- return true;
- }
}
commit c430d28ff07adb87cccc8823a3b24d598867c462
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 14:47:27 2013 -0700
[BZ 950701] Fix SVG text fonts in d3 graphs so that they dont look fuzzy.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
index 2693772..d9a4205 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/charttype/StackedBarMetricGraphImpl.java
@@ -31,13 +31,6 @@ public class StackedBarMetricGraphImpl extends AbstractGraph {
public StackedBarMetricGraphImpl() {
super();
}
- /**
- * General constructor for stacked bar graph when you have all the data needed to produce the graph. (This is true
- * for all cases but the dashboard portlet).
- */
-// public StackedBarMetricGraphImpl(MetricGraphData metricGraphData) {
-// setMetricGraphData(metricGraphData);
-// }
/**
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
index 099f23a..8728026 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
+++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css
@@ -27,11 +27,11 @@
}
.y.axis text, .x.axis text {
- font-family: 'Liberation Sans', Arial, Helvetica, sans-serif;
+ font-family: Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: normal;
font-style: normal;
- stroke: #50505a;
+ fill: #50505a;
text-rendering: optimize-legibility;
}
@@ -47,8 +47,8 @@
.minLabel, .avgLabel, .highLabel {
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
+ font-weight: bold;
text-anchor: start;
- stroke: #003168;
fill: #003168;
text-rendering: optimize-legibility;
}
@@ -57,7 +57,6 @@
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
text-anchor: start;
- stroke: #003168;
fill: #003168;
text-rendering: optimize-legibility;
}
commit 813c49855969171406f638a9d32112b722b99d19
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 13:37:35 2013 -0700
[BZ 955760] Syntax fix for gzip compression enablement.
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
index 29a6d76..4e90c62 100755
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
@@ -348,7 +348,7 @@ fi
# Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
# Note that the double equals for the policy file specification IS INTENTIONAL
-_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on org.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on -Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_HTTP_COMPRESSION} ${_JBOSS_DEBUG_LOGGING}"
debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
commit 8c54ef01abaa6790f49f96c492fe6649a0245a6f
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue Apr 30 09:06:23 2013 -0700
Move jquery(1.7.2) library out of CoreGUI.gwt.xml now that we don't have GFlot dependency (GFlot was removed with addition of d3 charts).
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 3d5ae84..7d50e87 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -46,14 +46,6 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
- <!-- External javascript libraries -->
- <!-- jquery.sparkline requires jquery. We don't explicitly provide jquery here because it is already
- embedded in the GFlot JAR (the charting lib used for GraphPortlet). Furthermore, GFlot 2.4.2 requires
- the version of jquery (1.7.2).
- -->
- <script src="/coregui/js/jquery-1.7.2.min.js"/>
-
-
<!--
Limit compilation to your preferred browser(s) to speed up compile time.
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
index 8722614..1b69b53 100644
--- a/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
+++ b/modules/enterprise/gui/coregui/src/main/webapp/CoreGUI.html
@@ -15,10 +15,12 @@
<link rel="stylesheet" href="css/tipsy.css">
<link rel="stylesheet" href="css/charts.css">
- <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/rhq.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/d3.v3.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/nv.d3.js"></script>
+ <!-- jquery dependent js libs -->
+ <script defer="defer" type="text/javascript" src="/coregui/js/jquery-1.7.2.min.js"></script>
+ <script defer="defer" type="text/javascript" src="/coregui/js/jquery.sparkline-2.1.min.js"></script>
<script defer="defer" type="text/javascript" src="/coregui/js/jquery.tipsy.js"></script>
<script type="text/javascript">
commit bcda4cd317f159f335aa544604ed9a0b0b3842a8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 15:41:46 2013 -0400
BZ 955760 - pass in the http compression sysprops to the RHQ Server at startup
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
index 42c8e45..29a6d76 100755
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/rhq-server.sh
@@ -348,7 +348,8 @@ fi
# Add the JVM opts that we always want to specify, whether or not the user set RHQ_SERVER_JAVA_OPTS.
# Note that the double equals for the policy file specification IS INTENTIONAL
-RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_JBOSS_DEBUG_LOGGING}"
+_HTTP_COMPRESSION="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on org.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+RHQ_SERVER_JAVA_OPTS="-Dapp.name=rhq-server ${RHQ_SERVER_JAVA_OPTS} -Drhq.server.home=${RHQ_SERVER_HOME} -Djboss.server.log.dir=${_LOG_DIR_PATH} -Djava.awt.headless=true -Dsun.lang.ClassLoader.allowArraySyntax=true -Djboss.server.default.config=standalone-full.xml -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.security.manager -Djava.security.policy==${RHQ_SERVER_HOME}/bin/rhq-server.security-policy ${_HTTP_COMPRESSION} ${_JBOSS_DEBUG_LOGGING}"
debug_msg "RHQ_SERVER_JAVA_OPTS: $RHQ_SERVER_JAVA_OPTS"
debug_msg "RHQ_SERVER_ADDITIONAL_JAVA_OPTS: $RHQ_SERVER_ADDITIONAL_JAVA_OPTS"
diff --git a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
index 3780f90..c5afd1b 100644
--- a/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
+++ b/modules/enterprise/server/appserver/src/main/bin-resources/bin/wrapper/rhq-server-wrapper.conf
@@ -82,11 +82,14 @@ wrapper.java.additional.18=-Dsun.lang.ClassLoader.allowArraySyntax=true
wrapper.java.additional.19=-Djava.security.manager
# the double equals for the policy file specification IS INTENTIONAL
wrapper.java.additional.20="-Djava.security.policy==%RHQ_SERVER_HOME%/bin/rhq-server.security-policy"
+wrapper.java.additional.21="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION=on"
+wrapper.java.additional.22="-Dorg.apache.coyote.http11.Http11Protocol.COMPRESSION_MIME_TYPES=text/javascript,text/css,text/html"
+
# use these if your JVM supports it
-#wrapper.java.additional.21=-XX:+TieredCompilation
-#wrapper.java.additional.22=-XX:+UseCompressedOops
+#wrapper.java.additional.23=-XX:+TieredCompilation
+#wrapper.java.additional.24=-XX:+UseCompressedOops
# Don't need these now, but this is commented out in case we need to add an endorsed dir in the future
-#wrapper.java.additional.23="-Djava.endorsed.dirs=%RHQ_SERVER_HOME%/jbossas/lib/endorsed"
+#wrapper.java.additional.25="-Djava.endorsed.dirs=%RHQ_SERVER_HOME%/jbossas/lib/endorsed"
# We want to make sure the Server starts in the JBossAS bin directory
wrapper.working.dir=%RHQ_SERVER_HOME%/jbossas/bin
diff --git a/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc b/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
index b76cd2f..8094241 100644
--- a/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
+++ b/modules/enterprise/server/appserver/src/main/dev-resources/bin/wrapper/rhq-server-wrapper.inc
@@ -4,12 +4,12 @@
#
# enable remote debugging
-wrapper.java.additional.9=-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n
+wrapper.java.additional.23=-agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=n
# enable jprofiler
#set.PATH=%PATH%;<jprofiler-install-dir>\bin\windows
-#wrapper.java.additional.10=-agentlib:jprofilerti=port=8849
-#wrapper.java.additional.11=-Xbootclasspath/a:<jprofiler-install-dir>\bin\agent.jar
+#wrapper.java.additional.23=-agentlib:jprofilerti=port=8849
+#wrapper.java.additional.24=-Xbootclasspath/a:<jprofiler-install-dir>\bin\agent.jar
# disable JVM startup timeout
wrapper.startup.timeout=0
commit 9a4c406425741f4dc3ecc546c27aec5d558fa37b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 14:25:36 2013 -0400
BZ 917085 fix test to hopefully run on windows
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index f0605a2..76742e8 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -530,8 +530,21 @@ public class AntBundlePluginComponentTest {
assert winDirs.size() == 1 : "should only have 1 ext backup dir on windows: " + winDirs;
backupDir = winDirs.values().iterator().next().getAbsoluteFile();
}
- File file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
- File file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+
+ File file3Backup;
+ File file4Backup;
+ boolean isWindows = (File.separatorChar == '\\');
+ if (isWindows) {
+ StringBuilder file3AbsPath = new StringBuilder(file3Dest.getAbsolutePath());
+ StringBuilder file4AbsPath = new StringBuilder(file4Dest.getAbsolutePath());
+ FileUtil.stripDriveLetter(file3AbsPath);
+ FileUtil.stripDriveLetter(file4AbsPath);
+ file3Backup = new File(backupDir, file3AbsPath.toString());
+ file4Backup = new File(backupDir, file4AbsPath.toString());
+ } else {
+ file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
+ file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+ }
assert file3Backup.isFile() : "should have been backed up: " + file3Backup;
assert file4Backup.isFile() : "should have been backed up: " + file4Backup;
assert (TEST3 + "modified").equals(readFile(file3Backup)) : "bad backup file: " + file3Backup;
commit 03caa3d61d59d2e041750b0581a31098acf61f10
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Apr 30 09:47:25 2013 -0400
these methods' @TranAttrib annotations are unused. Also, spoke to lukas, he said these methods should be made private
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
index bfe9f32..6689de5 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/StrippedDownStartupBean.java
@@ -21,8 +21,6 @@
package org.rhq.enterprise.server.test;
import javax.ejb.Singleton;
-import javax.ejb.TransactionAttribute;
-import javax.ejb.TransactionAttributeType;
import org.rhq.enterprise.server.core.StartupBean;
import org.rhq.enterprise.server.naming.NamingHack;
@@ -34,8 +32,7 @@ import org.rhq.enterprise.server.naming.NamingHack;
@Singleton
public class StrippedDownStartupBean {
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public void secureNaming() {
+ private void secureNaming() {
NamingHack.bruteForceInitialContextFactoryBuilder();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index 5b5aa8c..90ffbaf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -146,11 +146,8 @@ public class StartupBean implements StartupLocal {
/**
* Modifies the naming subsystem to be able to check for Java security permissions on JNDI lookup.
- * <p>
- * Made public so that this can be reused in tests.
*/
- @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
- public void secureNaming() {
+ private void secureNaming() {
NamingHack.bruteForceInitialContextFactoryBuilder();
}
commit c923c9a9951f9ee1bc352c65a6178f64225c14b3
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon Apr 29 14:06:22 2013 -0700
[BZ 956875] - Remove old charts now that they have been validated with new d3 charts. Eliminates the confusing second set of charts. Also removed GFlot charting library from codebase as it is no longer needed.
diff --git a/.classpath b/.classpath
index 9ff8db2..aa4c157 100644
--- a/.classpath
+++ b/.classpath
@@ -279,7 +279,6 @@
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-user/2.5.0/gwt-user-2.5.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/google/gwt/gwt-dev/2.5.0/gwt-dev-2.5.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/smartgwt/smartgwt/3.0/smartgwt-3.0.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/com/googlecode/gflot/gflot/2.4.2/gflot-2.4.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/jcraft/jsch/0.1.29/jsch-0.1.29.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-jxpath/commons-jxpath/1.3/commons-jxpath-1.3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/dbunit/dbunit/2.4.8/dbunit-2.4.8.jar"/>
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
index cea3bc0..f7dd822 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/PortletFactory.java
@@ -39,11 +39,9 @@ import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupOobs
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupOperationsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.groups.GroupPkgHistoryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.queue.AutodiscoveryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.FavoriteResourcesPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.platform.PlatformSummaryPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.recent.alerts.RecentAlertsPortlet;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.recent.imported.RecentlyAddedResourcesPortlet;
@@ -100,9 +98,7 @@ public class PortletFactory {
globalPortletFactoryMap.put(PlatformSummaryPortlet.KEY, PlatformSummaryPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(AutodiscoveryPortlet.KEY, AutodiscoveryPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(RecentAlertsPortlet.KEY, RecentAlertsPortlet.Factory.INSTANCE);
- globalPortletFactoryMap.put(ResourceGraphPortlet.KEY, ResourceGraphPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(ResourceD3GraphPortlet.KEY, ResourceD3GraphPortlet.Factory.INSTANCE);
- globalPortletFactoryMap.put(ResourceGroupGraphPortlet.KEY, ResourceGroupGraphPortlet.Factory.INSTANCE);
globalPortletFactoryMap.put(ResourceGroupD3GraphPortlet.KEY, ResourceGroupD3GraphPortlet.Factory.INSTANCE);
//conditionally add tags. Defaults to true, not available in JON builds.
if (CoreGUI.isTagsEnabledForUI()) {
@@ -123,9 +119,7 @@ public class PortletFactory {
globalPortletNameMap.put(PlatformSummaryPortlet.NAME, PlatformSummaryPortlet.KEY);
globalPortletNameMap.put(AutodiscoveryPortlet.NAME, AutodiscoveryPortlet.KEY);
globalPortletNameMap.put(RecentAlertsPortlet.NAME, RecentAlertsPortlet.KEY);
- globalPortletNameMap.put(ResourceGraphPortlet.NAME, ResourceGraphPortlet.KEY);
globalPortletNameMap.put(ResourceD3GraphPortlet.NAME, ResourceD3GraphPortlet.KEY);
- globalPortletNameMap.put(ResourceGroupGraphPortlet.NAME, ResourceGroupGraphPortlet.KEY);
globalPortletNameMap.put(ResourceGroupD3GraphPortlet.NAME, ResourceGroupD3GraphPortlet.KEY);
//conditionally add tags. Defaults to true, not available in JON builds.
if (CoreGUI.isTagsEnabledForUI()) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
index 013332c..ed59f8b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/GroupMetricsPortlet.java
@@ -371,8 +371,8 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
}
}
DynamicForm row = new DynamicForm();
- row.setNumCols(4);
- row.setColWidths(65, "*", 20, 100);
+ row.setNumCols(3);
+ row.setColWidths(65, "*", 100);
row.setWidth100();
row.setAutoHeight();
row.setOverflow(Overflow.VISIBLE);
@@ -418,31 +418,7 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
link.disable();
}
- //@todo: this goes away once we have validated the new d3 charts
- final String destination = "/resource/common/monitor/Visibility.do?mode=chartSingleMetricMultiResource&groupId="
- + groupId + "&m=" + md.getId();
- LinkItem oldLink = AbstractActivityView.newLinkItem("*",
- destination);
- oldLink.setTooltip("Link to Old Charts");
- oldLink.setTitleVAlign(VerticalAlignment.TOP);
- oldLink.setAlign(Alignment.LEFT);
- oldLink.setClipValue(true);
- oldLink.setWrap(true);
- oldLink.setHeight(26);
- oldLink.setWidth("100%");
-
- oldLink.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- ChartViewWindow window = new ChartViewWindow(title);
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- // .extendLocatorId("View"),
- // AbstractActivityView.iframeLink(destination));
- window.addItem(iframe);
- window.show();
- }
- });
+
//Value
String convertedValue = AbstractActivityView
.convertLastValueForDisplay(lastValue, md);
@@ -452,7 +428,7 @@ public class GroupMetricsPortlet extends EnhancedVLayout implements CustomSettin
value.setAlign(Alignment.RIGHT);
value.setWidth("100%");
- row.setItems(graphContainer, link, oldLink, value);
+ row.setItems(graphContainer, link, value);
row.setWidth100();
//if graph content returned
if ((!md.getName().trim().contains("Trait."))
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
index 856a177..1416b9d 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupD3GraphPortlet.java
@@ -80,7 +80,7 @@ public class ResourceGroupD3GraphPortlet extends MetricD3GraphView implements Au
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceGroupMetricD3";
// A default displayed, persisted name for the portlet
- public static final String NAME = "d3-" + MSG.view_portlet_defaultName_groupMetric();
+ public static final String NAME = MSG.view_portlet_defaultName_groupMetric();
// set on initial configuration, the window for this portlet view.
private PortletWindow portletWindow;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
deleted file mode 100644
index 6a728c7..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/groups/graph/ResourceGroupGraphPortlet.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph;
-
-import com.smartgwt.client.data.Criteria;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.types.TitleOrientation;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
-import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
-import com.smartgwt.client.widgets.form.fields.CanvasItem;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.SpacerItem;
-
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.dashboard.DashboardPortlet;
-import org.rhq.core.domain.resource.group.GroupCategory;
-import org.rhq.enterprise.gui.coregui.client.components.form.SortedSelectItem;
-import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedEvent;
-import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedHandler;
-import org.rhq.enterprise.gui.coregui.client.dashboard.CustomSettingsPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.Portlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
-import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.ResourceGroupMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.selection.SingleResourceGroupSelector;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceGroupD3GraphPortlet
- */
-@Deprecated
-public class ResourceGroupGraphPortlet extends ResourceGroupMetricGraphView implements CustomSettingsPortlet {
-
- // A non-displayed, persisted identifier for the portlet
- public static final String KEY = "ResourceGroupMetric";
- // A default displayed, persisted name for the portlet
- public static final String NAME = MSG.view_portlet_defaultName_groupMetric();
-
- // set on initial configuration, the window for this portlet view.
- private PortletWindow portletWindow;
-
- public static final String CFG_RESOURCE_GROUP_ID = "resourceGroupId";
- public static final String CFG_DEFINITION_ID = "definitionId";
-
- public ResourceGroupGraphPortlet() {
- super();
- setOverflow(Overflow.HIDDEN);
- }
-
- public void configure(PortletWindow portletWindow, DashboardPortlet storedPortlet) {
-
- if (null == this.portletWindow && null != portletWindow) {
- this.portletWindow = portletWindow;
- }
-
- if ((null == storedPortlet) || (null == storedPortlet.getConfiguration())) {
- return;
- }
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID).getIntegerValue();
- if (integerValue != null)
- setEntityId(integerValue);
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null)
- setDefinitionId(propertySimple.getIntegerValue());
- }
- }
-
- public Canvas getHelpCanvas() {
- return new HTMLFlow(MSG.view_portlet_help_graph());
- }
-
- @Override
- protected void onDraw() {
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- removeMembers(getMembers());
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- super.onDraw();
- }
- }
-
- public DynamicForm getCustomSettingsForm() {
- final DynamicForm form = new DynamicForm();
- form.setWidth(750);
- form.setNumCols(1);
-
- final CanvasItem selectorItem = new CanvasItem();
- selectorItem.setTitleOrientation(TitleOrientation.TOP);
- selectorItem.setShowTitle(false);
-
- final SingleResourceGroupSelector resourceGroupSelector = new SingleResourceGroupSelector(
- GroupCategory.COMPATIBLE, false);
- resourceGroupSelector.setWidth(700);
- resourceGroupSelector.setHeight(300);
- //TODO, would probaby be nice to find a way to seed assigned with the current group
- //ListGridRecord rec = new ListGridRecord();
- //rec.setAttribute("id", getEntityId());
- //rec.setAttribute("name", "current");
- //resourceGroupSelector.setAssigned(new ListGridRecord[] { rec });
-
- final SelectItem metric = new SortedSelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
- @Override
- protected Criteria getPickListFilterCriteria() {
- Criteria criteria = new Criteria();
-
- if (resourceGroupSelector.getSelectedItems().size() == 1) {
- int groupId = resourceGroupSelector.getSelectedItems().iterator().next().getId();
- criteria.addCriteria(CFG_RESOURCE_GROUP_ID, groupId);
- form.setValue(CFG_RESOURCE_GROUP_ID, groupId);
- }
- return criteria;
- }
- };
- metric.setWidth(300);
- metric.setTitleOrientation(TitleOrientation.TOP);
- metric.setValueField("id");
- metric.setDisplayField("displayName");
- metric.setOptionDataSource(new ResourceScheduledMetricDatasource());
-
- resourceGroupSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() {
-
- public void onSelectionChanged(AssignedItemsChangedEvent event) {
-
- if (resourceGroupSelector.getSelectedItems().size() == 1) {
- metric.fetchData();
- form.clearValue(CFG_DEFINITION_ID);
- }
- }
- });
-
- final DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID).getIntegerValue();
- if (integerValue != null)
- form.setValue(CFG_RESOURCE_GROUP_ID, integerValue);
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null)
- form.setValue(CFG_DEFINITION_ID, propertySimple.getIntegerValue());
- }
-
- selectorItem.setCanvas(resourceGroupSelector);
- form.setFields(selectorItem, metric, new SpacerItem());
-
- form.addSubmitValuesHandler(new SubmitValuesHandler() {
- public void onSubmitValues(SubmitValuesEvent submitValuesEvent) {
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_RESOURCE_GROUP_ID, form.getValue(CFG_RESOURCE_GROUP_ID)));
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_DEFINITION_ID, form.getValue(CFG_DEFINITION_ID)));
-
- configure(portletWindow, storedPortlet);
-
- redraw();
- }
- });
-
- return form;
- }
-
- @Override
- public void redraw() {
- super.redraw();
-
- removeMembers(getMembers());
-
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_GROUP_ID);
- if (simple == null | simple.getIntegerValue() == null) {
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- renderGraph();
- }
- }
-
- public static final class Factory implements PortletViewFactory {
- public static PortletViewFactory INSTANCE = new Factory();
-
- public final Portlet getInstance(EntityContext context) {
-
- return new ResourceGroupGraphPortlet();
- }
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
index d706da9..0d6bcfd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceD3GraphPortlet.java
@@ -75,7 +75,7 @@ public class ResourceD3GraphPortlet extends MetricD3GraphView implements AutoRef
// A non-displayed, persisted identifier for the portlet
public static final String KEY = "ResourceMetricD3";
// A default displayed, persisted name for the portlet
- public static final String NAME = "d3-" + MSG.view_portlet_defaultName_resourceMetric();
+ public static final String NAME = MSG.view_portlet_defaultName_resourceMetric();
public static final String CFG_RESOURCE_ID = "resourceId";
public static final String CFG_DEFINITION_ID = "definitionId";
// set on initial configuration, the window for this portlet view.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java
deleted file mode 100644
index 5f38301..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/inventory/resource/graph/ResourceGraphPortlet.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph;
-
-import com.smartgwt.client.data.Criteria;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.form.DynamicForm;
-import com.smartgwt.client.widgets.form.events.SubmitValuesEvent;
-import com.smartgwt.client.widgets.form.events.SubmitValuesHandler;
-import com.smartgwt.client.widgets.form.fields.SelectItem;
-import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
-
-import org.rhq.core.domain.common.EntityContext;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.dashboard.DashboardPortlet;
-import org.rhq.enterprise.gui.coregui.client.components.lookup.ResourceLookupComboBoxItem;
-import org.rhq.enterprise.gui.coregui.client.dashboard.CustomSettingsPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.Portlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletViewFactory;
-import org.rhq.enterprise.gui.coregui.client.dashboard.PortletWindow;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.ResourceScheduledMetricDatasource;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceD3GraphPortlet
- */
-@Deprecated
-public class ResourceGraphPortlet extends ResourceMetricGraphView implements CustomSettingsPortlet {
-
- // A non-displayed, persisted identifier for the portlet
- public static final String KEY = "ResourceMetric";
- // A default displayed, persisted name for the portlet
- public static final String NAME = MSG.view_portlet_defaultName_resourceMetric();
-
- // set on initial configuration, the window for this portlet view.
- private PortletWindow portletWindow;
-
- public static final String CFG_RESOURCE_ID = "resourceId";
- public static final String CFG_DEFINITION_ID = "definitionId";
-
- public ResourceGraphPortlet() {
- super();
- setOverflow(Overflow.HIDDEN);
- }
-
- public void configure(PortletWindow portletWindow, DashboardPortlet storedPortlet) {
-
- if (null == this.portletWindow && null != portletWindow) {
- this.portletWindow = portletWindow;
- }
-
- if ((null == storedPortlet) || (null == storedPortlet.getConfiguration())) {
- return;
- }
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID) != null) {
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (propertySimple != null) {
- Integer integerValue = propertySimple.getIntegerValue();
- if (integerValue != null)
- setEntityId(integerValue);
- }
- propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null) {
-
- Integer integerValue = propertySimple.getIntegerValue();
- if (integerValue != null)
- setDefinitionId(integerValue);
- }
- }
- }
-
- public Canvas getHelpCanvas() {
- return new HTMLFlow(MSG.view_portlet_help_graph());
- }
-
- @Override
- protected void onDraw() {
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- removeMembers(getMembers());
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- super.onDraw();
- }
- }
-
- public DynamicForm getCustomSettingsForm() {
- final DynamicForm form = new DynamicForm();
-
- final ResourceLookupComboBoxItem resourceLookupComboBoxItem = new ResourceLookupComboBoxItem(CFG_RESOURCE_ID,
- MSG.common_title_resource());
- resourceLookupComboBoxItem.setWidth(300);
-
- final SelectItem metric = new SelectItem(CFG_DEFINITION_ID, MSG.common_title_metric()) {
- @Override
- protected Criteria getPickListFilterCriteria() {
- Criteria criteria = new Criteria();
-
- if (resourceLookupComboBoxItem.getValue() != null) {
- int resourceId = (Integer) resourceLookupComboBoxItem.getValue();
- criteria.addCriteria(CFG_RESOURCE_ID, resourceId);
- }
- return criteria;
- }
- };
-
- final DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
-
- metric.setWidth(300);
- metric.setValueField("id");
- metric.setDisplayField("displayName");
- metric.setOptionDataSource(new ResourceScheduledMetricDatasource());
-
- resourceLookupComboBoxItem
- .addChangedHandler(new com.smartgwt.client.widgets.form.fields.events.ChangedHandler() {
- public void onChanged(ChangedEvent event) {
-
- if (form.getValue(CFG_RESOURCE_ID) instanceof Integer) {
- metric.fetchData();
- form.clearValue(CFG_DEFINITION_ID);
- }
- }
- });
-
- if (storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID) != null) {
- Integer integerValue = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID).getIntegerValue();
- if (integerValue != null) {
- form.setValue(CFG_RESOURCE_ID, integerValue);
- }
-
- PropertySimple propertySimple = storedPortlet.getConfiguration().getSimple(CFG_DEFINITION_ID);
- if (propertySimple != null && propertySimple.getIntegerValue() != null) {
- form.setValue(CFG_DEFINITION_ID, propertySimple.getIntegerValue());
- }
- }
-
- form.setFields(resourceLookupComboBoxItem, metric);
-
- form.addSubmitValuesHandler(new SubmitValuesHandler() {
- public void onSubmitValues(SubmitValuesEvent submitValuesEvent) {
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_RESOURCE_ID, form.getValue(CFG_RESOURCE_ID)));
- storedPortlet.getConfiguration().put(
- new PropertySimple(CFG_DEFINITION_ID, form.getValue(CFG_DEFINITION_ID)));
-
- configure(portletWindow, storedPortlet);
-
- redraw();
- }
- });
-
- return form;
- }
-
- @Override
- public void redraw() {
- super.redraw();
-
- removeMembers(getMembers());
-
- DashboardPortlet storedPortlet = portletWindow.getStoredPortlet();
- PropertySimple simple = storedPortlet.getConfiguration().getSimple(CFG_RESOURCE_ID);
- if (simple == null || simple.getIntegerValue() == null) {
- addMember(new Label("<i>" + MSG.view_portlet_configure_needed() + "</i>"));
- } else {
- renderGraph();
- }
- }
-
- public static final class Factory implements PortletViewFactory {
- public static PortletViewFactory INSTANCE = new Factory();
-
- @Override
- public final Portlet getInstance(EntityContext context) {
-
- return new ResourceGraphPortlet();
- }
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
index 62afc42..39ce5bd 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/resource/ResourceMetricsPortlet.java
@@ -243,8 +243,8 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
}
}
DynamicForm row = new DynamicForm();
- row.setNumCols(4);
- row.setColWidths(65, "*", 20, 100);
+ row.setNumCols(3);
+ row.setColWidths(65, "*", 100);
row.setWidth100();
row.setAutoHeight();
row.setOverflow(Overflow.VISIBLE);
@@ -297,31 +297,6 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
link.disable();
}
- //@todo: this goes away once we have validated charts
- final String chartTitle = md.getDisplayName();
- final String destination = "/resource/common/monitor/Visibility.do?mode=chartSingleMetricSingleResource&id="
- + resourceId + "&m=" + md.getId();
-
- //have link launch modal window on click
- LinkItem oldLink = AbstractActivityView.newLinkItem("*",
- destination);
- oldLink.setTooltip("Link to test Old Chart");
- oldLink.setTitleVAlign(VerticalAlignment.TOP);
- oldLink.setAlign(Alignment.LEFT);
- oldLink.setClipValue(true);
- oldLink.setWrap(true);
- oldLink.setHeight(26);
- oldLink.setWidth("100%");
- oldLink.addClickHandler(new ClickHandler() {
- @Override
- public void onClick(ClickEvent event) {
- ChartViewWindow window = new ChartViewWindow(chartTitle);
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- window.addItem(iframe);
- window.show();
- }
- });
//Value
String convertedValue;
@@ -332,7 +307,7 @@ public class ResourceMetricsPortlet extends GroupMetricsPortlet {
value.setVAlign(VerticalAlignment.TOP);
value.setAlign(Alignment.RIGHT);
- row.setItems(sparklineContainer, link, oldLink, value);
+ row.setItems(sparklineContainer, link, value);
row.setWidth100();
//if graph content returned
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
deleted file mode 100644
index c921acf..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/AbstractMetricGraphView.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.common;
-
-import java.util.Date;
-import java.util.List;
-
-import ca.nanometrics.gflot.client.Axis;
-import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.SeriesHandler;
-import ca.nanometrics.gflot.client.SimplePlot;
-import ca.nanometrics.gflot.client.event.PlotHoverListener;
-import ca.nanometrics.gflot.client.event.PlotItem;
-import ca.nanometrics.gflot.client.event.PlotPosition;
-import ca.nanometrics.gflot.client.jsni.Plot;
-import ca.nanometrics.gflot.client.options.AxisOptions;
-import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
-import ca.nanometrics.gflot.client.options.GridOptions;
-import ca.nanometrics.gflot.client.options.LineSeriesOptions;
-import ca.nanometrics.gflot.client.options.PlotOptions;
-import ca.nanometrics.gflot.client.options.PointsSeriesOptions;
-import ca.nanometrics.gflot.client.options.TickFormatter;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
-import com.smartgwt.client.types.AnimationEffect;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.WidgetCanvas;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated this code will go away once D3 graphs have been validated.
- */
-@Deprecated
-public abstract class AbstractMetricGraphView extends EnhancedVLayout {
-
- private static final String INSTRUCTIONS = MSG.view_resource_monitor_graph_instructions();
-
- /*
- private static final String[] MONTH_NAMES = { MSG.common_calendar_january_short(),
- MSG.common_calendar_february_short(), MSG.common_calendar_march_short(), MSG.common_calendar_april_short(),
- MSG.common_calendar_may_short(), MSG.common_calendar_june_short(), MSG.common_calendar_july_short(),
- MSG.common_calendar_august_short(), MSG.common_calendar_september_short(), MSG.common_calendar_october_short(),
- MSG.common_calendar_november_short(), MSG.common_calendar_december_short() };
- */
-
- private final Label selectedPointLabel = new Label(INSTRUCTIONS);
- private final Label positionLabel = new Label();
- private final Label hoverLabel = new Label();
-
- private HTMLFlow resourceTitle;
-
- private int entityId;
- private int definitionId;
-
- private MeasurementDefinition definition;
- private List<MeasurementDataNumericHighLowComposite> data;
-
- public AbstractMetricGraphView() {
- super();
- }
-
- public AbstractMetricGraphView(int entityId, int definitionId) {
- this.entityId = entityId;
- this.definitionId = definitionId;
-
- // Should this not also set H+W=100?
- }
-
- public AbstractMetricGraphView(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- this.entityId = entityId;
- this.definition = def;
- this.data = data;
- setHeight100();
- setWidth100();
- }
-
- public abstract AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data);
-
- protected abstract void renderGraph();
-
- protected HTMLFlow getEntityTitle(){
- return resourceTitle;
- }
-
- public int getEntityId() {
- return this.entityId;
- }
-
- public void setEntityId(int entityId) {
- this.entityId = entityId;
- this.definition = null;
- }
-
- public int getDefinitionId() {
- return definitionId;
- }
-
- public void setDefinitionId(int definitionId) {
- this.definitionId = definitionId;
- this.definition = null;
- }
-
- public MeasurementDefinition getDefinition() {
- return definition;
- }
-
- public void setDefinition(MeasurementDefinition definition) {
- this.definition = definition;
- }
-
- public List<MeasurementDataNumericHighLowComposite> getData() {
- return data;
- }
-
- public void setData(List<MeasurementDataNumericHighLowComposite> data) {
- this.data = data;
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
- removeMembers(getMembers());
- renderGraph();
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- removeMembers(getMembers());
- renderGraph();
- }
-
- protected void drawGraph() {
-
- HLayout titleHLayout = new EnhancedHLayout();
-
- if (definition != null) {
- titleHLayout.setAutoHeight();
- titleHLayout.setWidth100();
-
- HTMLFlow entityTitle = getEntityTitle();
- if (null != entityTitle) {
- entityTitle.setWidth("*");
- titleHLayout.addMember(entityTitle);
- }
-
- if (supportsLiveGraphViewDialog()) {
- Img liveGraph = new Img("subsystems/monitor/Monitor_16.png", 16, 16);
- liveGraph.setTooltip(MSG.view_resource_monitor_graph_live_tooltip());
-
- liveGraph.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- displayLiveGraphViewDialog();
- }
- });
- titleHLayout.addMember(liveGraph);
- }
-
- addMember(titleHLayout);
-
- HTMLFlow title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
- title.setWidth100();
- title.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- displayAsDialog();
- }
- });
- addMember(title);
- }
-
- PlotModel model = new PlotModel();
- PlotOptions plotOptions = new PlotOptions();
- GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
- globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- globalSeriesOptions.setShadowSize(0);
- plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
-
- // You need make the grid hoverable <<<<<<<<<
- plotOptions
- .setGridOptions(new GridOptions().setHoverable(true).setMouseActiveRadius(10).setAutoHighlight(true));
-
- // create a series
- if (definition != null && data != null) {
- loadData(model, plotOptions);
- }
-
- // create the plot
- SimplePlot plot = new SimplePlot(model, plotOptions);
- plot.setSize(String.valueOf(getInnerContentWidth()),
- String.valueOf(getInnerContentHeight() - titleHLayout.getHeight() - 50));
- // "80%","80%");
-
- // add hover listener
- plot.addHoverListener(new PlotHoverListener() {
- public void onPlotHover(Plot plot, PlotPosition position, PlotItem item) {
- if (position != null) {
- positionLabel.setContents("position: (" + position.getX() + "," + position.getY() + ")");
- }
- if (item != null) {
- hoverLabel.setContents(getHover(item));
-
- hoverLabel.animateShow(AnimationEffect.FADE);
- if (hoverLabel.getLeft() > 0 || hoverLabel.getTop() > 0) {
- hoverLabel.animateMove(item.getPageX() + 10, item.getPageY() - 35);
- } else {
- hoverLabel.moveTo(item.getPageX() + 10, item.getPageY() - 35);
- }
- hoverLabel.redraw();
-
- selectedPointLabel.setContents("x: " + item.getDataPoint().getX() + ", y: "
- + item.getDataPoint().getY());
- } else {
- hoverLabel.animateHide(AnimationEffect.FADE);
- selectedPointLabel.setContents(INSTRUCTIONS);
- }
- }
- }, false);
-
- addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- hoverLabel.animateHide(AnimationEffect.FADE);
- }
- });
-
- hoverLabel.setOpacity(80);
- hoverLabel.setWrap(false);
- hoverLabel.setHeight(25);
- hoverLabel.setBackgroundColor("yellow");
- hoverLabel.setBorder("1px solid orange");
- hoverLabel.hide();
-
- if (hoverLabel.isDrawn())
- hoverLabel.redraw();
- else
- hoverLabel.draw();
-
- // put it on a panel
-
- addMember(new WidgetCanvas(plot));
-
- plot.setSize(String.valueOf(getInnerContentWidth()),
- String.valueOf(getInnerContentHeight() - titleHLayout.getHeight() - 50));
-
- }
-
- protected boolean supportsLiveGraphViewDialog() {
- return false;
- }
-
- protected void displayLiveGraphViewDialog() {
- return;
- }
-
- @Override
- public void destroy() {
- hoverLabel.destroy();
- super.destroy();
- }
-
- @Override
- public void hide() {
- super.hide();
- hoverLabel.hide();
- }
-
- protected String getHover(PlotItem item) {
- if (definition != null) {
- com.google.gwt.i18n.client.DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return definition.getDisplayName() + ": "
- + MeasurementConverterClient.format(item.getDataPoint().getY(), definition.getUnits(), true) + "<br/>"
- + df.format(new Date((long) item.getDataPoint().getX()));
- } else {
- return "x: " + item.getDataPoint().getX() + ", y: " + item.getDataPoint().getY();
- }
- }
-
- protected void loadData(PlotModel model, PlotOptions plotOptions) {
- SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
-
- for (MeasurementDataNumericHighLowComposite d : data) {
- if (!Double.isNaN(d.getValue())) {
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
- }
- }
-
- plotOptions.addYAxisOptions(new AxisOptions().setTicks(5).setLabelWidth(70)
- .setTickFormatter(new TickFormatter() {
- public String formatTickValue(double v, Axis axis) {
- return MeasurementConverterClient.format(v, definition.getUnits(), true);
- }
- }));
-
- int xTicks = getDefaultWidth() / 140;
-
- plotOptions.addXAxisOptions(new AxisOptions().setTicks(xTicks).setTickFormatter(new TickFormatter() {
- public String formatTickValue(double tickValue, Axis axis) {
- com.google.gwt.i18n.client.DateTimeFormat dateFormat = DateTimeFormat
- .getFormat(PredefinedFormat.DATE_TIME_SHORT);
- return dateFormat.format(new Date((long) tickValue));
- // return String.valueOf(new Date((long) tickValue));
- // return MONTH_NAMES[(int) (tickValue - 1)];
- }
- }));
-
- }
-
- private void displayAsDialog() {
- AbstractMetricGraphView graph = getInstance(entityId, definition, data);
- Window graphPopup = new Window();
- graphPopup.setTitle(MSG.view_resource_monitor_detailed_graph_label());
- graphPopup.setWidth(800);
- graphPopup.setHeight(400);
- graphPopup.setIsModal(true);
- graphPopup.setShowModalMask(true);
- graphPopup.setCanDragResize(true);
- graphPopup.centerInPage();
- graphPopup.addItem(graph);
- graphPopup.show();
- }
-
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
index ca6d9f1..87c73c2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupContextMenu.java
@@ -59,7 +59,7 @@ import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupGraphPortlet;
+import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.groups.graph.ResourceGroupD3GraphPortlet;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceDetailView;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.ResourceTreeDatasource.AutoGroupTreeNode;
@@ -248,69 +248,8 @@ public class ResourceGroupContextMenu extends Menu {
// Metric graph addition menu
addItem(buildMetricsMenu(resourceType));
-
- /* TODO: We don't support group factory create
- // Create Menu
- MenuItem createChildMenu = new MenuItem("Create Child");
- Menu createChildSubMenu = new Menu();
- for (final ResourceType childType : resourceType.getChildResourceTypes()) {
- if (childType.isCreatable()) {
- MenuItem createItem = new MenuItem(childType.getName());
- createChildSubMenu.addItem(createItem);
- createItem.addClickHandler(new ClickHandler() {
- public void onClick(MenuItemClickEvent event) {
- ResourceFactoryCreateWizard.showCreateWizard(resource, childType);
- }
- });
-
- }
- }
- createChildMenu.setSubmenu(createChildSubMenu);
- createChildMenu.setEnabled(createChildSubMenu.getItems().length > 0);
- contextMenu.addItem(createChildMenu);*/
-
- /*
- // TODO We don't group manual import
- // Manually Add Menu
- MenuItem importChildMenu = new MenuItem("Import");
- Menu importChildSubMenu = new Menu();
- for (ResourceType childType : resourceType.getChildResourceTypes()) {
- if (childType.isSupportsManualAdd()) {
- importChildSubMenu.addItem(new MenuItem(childType.getName()));
- }
- }
- if (resourceType.getCategory() == ResourceCategory.PLATFORM) {
- loadManuallyAddServersToPlatforms(importChildSubMenu);
- }
- importChildMenu.setSubmenu(importChildSubMenu);
- importChildMenu.setEnabled(importChildSubMenu.getItems().length > 0);
- addItem(importChildMenu);
- */
}
- /*
- private void loadManuallyAddServersToPlatforms(final Menu manuallyAddMenu) {
- ResourceTypeGWTServiceAsync rts = GWTServiceLookup.getResourceTypeGWTService();
-
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterSupportsManualAdd(true);
- criteria.fetchParentResourceTypes(true);
- rts.findResourceTypesByCriteria(criteria, new AsyncCallback<PageList<ResourceType>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_contextMenu_loadFail_children(), caught);
- }
-
- public void onSuccess(PageList<ResourceType> result) {
- for (ResourceType type : result) {
- if (type.getParentResourceTypes() == null || type.getParentResourceTypes().isEmpty()) {
- MenuItem item = new MenuItem(type.getName());
- manuallyAddMenu.addItem(item);
- }
- }
- }
- });
- }
- */
private MenuItem buildMetricsMenu(final ResourceType type) {
MenuItem measurements = new MenuItem(MSG.view_tree_common_contextMenu_measurements());
@@ -354,12 +293,12 @@ public class ResourceGroupContextMenu extends Menu {
DashboardPortlet p = new DashboardPortlet(MSG
.view_tree_common_contextMenu_groupGraph(),
- ResourceGroupGraphPortlet.KEY, 250);
+ ResourceGroupD3GraphPortlet.KEY, 250);
p.getConfiguration().put(
- new PropertySimple(ResourceGroupGraphPortlet.CFG_RESOURCE_GROUP_ID,
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_RESOURCE_GROUP_ID,
group.getId()));
p.getConfiguration().put(
- new PropertySimple(ResourceGroupGraphPortlet.CFG_DEFINITION_ID, def
+ new PropertySimple(ResourceGroupD3GraphPortlet.CFG_DEFINITION_ID, def
.getId()));
d.addPortlet(p);
@@ -388,7 +327,7 @@ public class ResourceGroupContextMenu extends Menu {
//add new menu item for adding current graphable element to view if on Monitor/Graphs tab
String currentViewPath = History.getToken();
- if (currentViewPath.indexOf("Monitoring/Graphs") > -1) {
+ if (currentViewPath.indexOf("Monitoring/NewGraphs") > -1) {
MenuItem addGraphItem = new MenuItem(MSG.common_title_add_graph_to_view());
defSubItem.addItem(addGraphItem);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
index b695b4f..07622e3 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/ResourceGroupDetailView.java
@@ -55,7 +55,6 @@ import org.rhq.enterprise.gui.coregui.client.components.view.ViewName;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.InventoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.AbstractTwoLevelTabSetView;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.detail.monitoring.IFrameWithMeasurementRangeEditorView;
import org.rhq.enterprise.gui.coregui.client.inventory.common.event.EventCompositeHistoryView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration.GroupResourceConfigurationEditView;
import org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configuration.HistoryGroupResourceConfigurationView;
@@ -101,7 +100,6 @@ public class ResourceGroupDetailView extends
// subtabs
private SubTab summaryActivity;
private SubTab summaryTimeline;
- private SubTab monitorGraphs;
private SubTab monitorNewGraphs;
private SubTab monitorTables;
private SubTab monitorTraits;
@@ -193,14 +191,13 @@ public class ResourceGroupDetailView extends
monitoringTab = new TwoLevelTab(new ViewName("Monitoring", MSG.view_tabs_common_monitoring()),
IconEnum.SUSPECT_METRICS);
- monitorGraphs = new SubTab(monitoringTab, new ViewName("Graphs", MSG.view_tabs_common_graphs()), null);
- monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", "d3 Graphs"), null);
+ monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorGraphs, monitorNewGraphs, monitorTables, monitorTraits, monitorSched,
+ monitoringTab.registerSubTabs( monitorNewGraphs, monitorTables, monitorTraits, monitorSched,
monitorCallTime);
tabs.add(monitoringTab);
@@ -273,25 +270,19 @@ public class ResourceGroupDetailView extends
if (updateTab(this.monitoringTab, visible, true)) {
final EntityContext groupContext = EntityContext.forGroup(groupComposite.getResourceGroup());
visible = hasMetricsOfType(this.groupComposite, DataType.MEASUREMENT);
- viewFactory = (!visible) ? null : new ViewFactory() {
- @Override
- public Canvas createView() {
- String url = "/rhq/group/monitor/graphs-plain.xhtml?groupId=" + groupId;
-
- if (groupContext.isAutoGroup()) {
- url += "&parent=" + groupContext.parentResourceId + "&type=" + groupContext.resourceTypeId
- + "&groupType=auto";
- } else if (groupContext.isAutoCluster()) {
- url += "&groupType=cluster";
- }
- return new IFrameWithMeasurementRangeEditorView(url);
+ boolean showOnPage;
+
+ if(BrowserUtility.isBrowserPreIE9()){
+ showOnPage = false;
+ }else{
+ if(visible) {
+ showOnPage = true;
+ }else {
+ showOnPage = false;
}
- };
- updateSubTab(this.monitoringTab, this.monitorGraphs, visible, true, viewFactory);
-
- boolean visibleToIE8 = BrowserUtility.isBrowserPreIE9();
+ }
- viewFactory = (!visibleToIE8) ? null : new ViewFactory() {
+ viewFactory = (!showOnPage) ? null : new ViewFactory() {
@Override
public Canvas createView() {
return createD3GraphListView();
@@ -493,10 +484,8 @@ public class ResourceGroupDetailView extends
@Override
public void onSuccess(Subject result) {
- if (Log.isDebugEnabled()) {
- Log.debug("Updated recently viewed resource groups for " + result
+ Log.debug("Updated recently viewed resource groups for " + result
+ " with resourceGroupId [" + groupId + "]");
- }
}
});
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java
deleted file mode 100644
index 4fa0164..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/ResourceGroupMetricGraphView.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring;
-
-import java.util.EnumSet;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.core.domain.criteria.ResourceGroupCriteria;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.group.ResourceGroup;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility;
-
-/**
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- * @deprecated see ResourceGroupD3MetricGraphView
- */
-@Deprecated
-public class ResourceGroupMetricGraphView extends AbstractMetricGraphView {
-
- private HTMLFlow resourceGroupTitle;
-
- public ResourceGroupMetricGraphView() {
- super();
- }
-
- public ResourceGroupMetricGraphView(int groupId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- super(groupId, def, data);
- }
-
- @Override
- protected HTMLFlow getEntityTitle() {
- return resourceGroupTitle;
- }
-
- @Override
- protected void renderGraph() {
- if (null == getDefinition()) {
- ResourceGroupGWTServiceAsync groupService = GWTServiceLookup.getResourceGroupService();
-
- ResourceGroupCriteria criteria = new ResourceGroupCriteria();
- criteria.addFilterId(getEntityId());
- criteria.fetchResourceType(true);
- groupService.findResourceGroupsByCriteria(criteria, new AsyncCallback<PageList<ResourceGroup>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_lookupFailed(), caught);
- }
-
- @Override
- public void onSuccess(PageList<ResourceGroup> result) {
- if (result.isEmpty()) {
- return;
- }
-
- final ResourceGroup group = result.get(0);
- String url = LinkManager.getResourceGroupLink(group);
- resourceGroupTitle = new HTMLFlow(LinkManager.getHref(url, group.getName()));
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(group.getResourceType().getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(final ResourceType type) {
-
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getId() == getDefinitionId()) {
- setDefinition(def);
-
- GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroupForLast(
- getEntityId(), new int[] { getDefinitionId() }, 8,
- MeasurementUtility.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(
- List<List<MeasurementDataNumericHighLowComposite>> result) {
- setData(result.get(0));
-
- drawGraph();
- }
- });
- }
- }
- }
- });
- }
- });
-
- } else {
-
- drawGraph();
- }
- }
-
- @Override
- public AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- return new ResourceGroupMetricGraphView(entityId, def, data);
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
index 824e201..46e51c0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/monitoring/table/CompositeGroupMultiLineGraphListView.java
@@ -40,7 +40,6 @@ public final class CompositeGroupMultiLineGraphListView extends CompositeGroupD3
var chartId = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getChartId()(),
chartHandle = "#mChart-"+chartId,
chartSelection = chartHandle + " svg",
- // yAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getYAxisTitle()(),
yAxisUnits = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getYAxisUnits()(),
xAxisLabel = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::getXAxisTitle()(),
displayDayOfWeek = this.@org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.monitoring.table.CompositeGroupD3GraphListView::shouldDisplayDayOfWeekInXAxisLabel()(),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
index 0b67c63..a68170a 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java
@@ -102,8 +102,6 @@ public class ResourceDetailView extends
}
public static class DriftSubTab {
- //public static final String HISTORY = "History";
- //public static final String SNAPSHOTS = "Snapshots";
public static final String DEFINITIONS = "Definitions";
}
@@ -130,7 +128,6 @@ public class ResourceDetailView extends
private SubTab summaryActivity;
private SubTab summaryTimeline;
- private SubTab monitorGraphs;
private SubTab monitorNewGraphs;
private SubTab monitorTables;
private SubTab monitorTraits;
@@ -150,7 +147,6 @@ public class ResourceDetailView extends
private SubTab configCurrent;
private SubTab configHistory;
private SubTab eventHistory;
- //private SubTab driftHistory;
private SubTab driftDefinitions;
private SubTab contentDeployed;
private SubTab contentNew;
@@ -198,9 +194,8 @@ public class ResourceDetailView extends
monitoringTab = new TwoLevelTab(new ViewName("Monitoring", MSG.view_tabs_common_monitoring()),
IconEnum.SUSPECT_METRICS);
- monitorGraphs = new SubTab(monitoringTab, new ViewName("Graphs", MSG.view_tabs_common_graphs()), null);
- monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", "d3 Graphs"), null);
+ monitorNewGraphs = new SubTab(monitoringTab, new ViewName("NewGraphs", MSG.view_tabs_common_graphs()), null);
monitorTables = new SubTab(monitoringTab, new ViewName("Tables", MSG.view_tabs_common_tables()), null);
monitorTraits = new SubTab(monitoringTab, new ViewName("Traits", MSG.view_tabs_common_traits()), null);
@@ -208,7 +203,7 @@ public class ResourceDetailView extends
null);
monitorSched = new SubTab(monitoringTab, new ViewName("Schedules", MSG.view_tabs_common_schedules()), null);
monitorCallTime = new SubTab(monitoringTab, new ViewName("CallTime", MSG.view_tabs_common_calltime()), null);
- monitoringTab.registerSubTabs(monitorTables, monitorGraphs, monitorNewGraphs, monitorTraits, monitorAvail,
+ monitoringTab.registerSubTabs(monitorTables, monitorNewGraphs, monitorTraits, monitorAvail,
monitorSched, monitorCallTime);
tabs.add(monitoringTab);
@@ -393,16 +388,7 @@ public class ResourceDetailView extends
private void updateMonitoringTabContent(final Resource resource, Set<ResourceTypeFacet> facets) {
boolean visible = hasMetricsOfType(this.resourceComposite, DataType.MEASUREMENT);
-
- ViewFactory viewFactory = (!visible) ? null : new ViewFactory() {
- @Override
- public Canvas createView() {
- return new IFrameWithMeasurementRangeEditorView("/rhq/resource/monitor/graphs-plain.xhtml?id="
- + resource.getId());
- }
-
- };
- updateSubTab(this.monitoringTab, this.monitorGraphs, visible, true, viewFactory);
+ ViewFactory viewFactory;
boolean visibleToIE8 = !BrowserUtility.isBrowserPreIE9();
@@ -520,15 +506,6 @@ public class ResourceDetailView extends
private void updateDriftTabContent(final ResourceComposite resourceComposite, Set<ResourceTypeFacet> facets) {
if (updateTab(this.driftTab, facets.contains(ResourceTypeFacet.DRIFT), true)) {
- // TODO: Experimenting with not shoing a drift history tab and having all resource level drift viewing
- // go through the comprehensive drift carousel view. Leave it in, but commented, in case we want it back.
- //updateSubTab(this.driftTab, this.driftHistory, true, true, new ViewFactory() {
- // @Override
- // public Canvas createView() {
- // return ResourceDriftHistoryView.get(resourceComposite);
- // }
- //});
-
updateSubTab(this.driftTab, this.driftDefinitions, true, true, new ViewFactory() {
@Override
public Canvas createView() {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
index fa5d904..72a46a8 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java
@@ -87,7 +87,6 @@ import org.rhq.enterprise.gui.coregui.client.ViewId;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.components.tree.EnhancedTreeNode;
import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceD3GraphPortlet;
-import org.rhq.enterprise.gui.coregui.client.dashboard.portlets.inventory.resource.graph.ResourceGraphPortlet;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGroupGWTServiceAsync;
@@ -797,46 +796,7 @@ public class ResourceTreeView extends EnhancedVLayout {
}
});
- //@todo: Remove once we have verified the charts
- // now add the old menu items
- MenuItem addOldItemToDBItem = new MenuItem(MSG
- .view_tree_common_contextMenu_addChartToDashboard(d.getName()));
- defSubItem.addItem(addOldItemToDBItem);
- addOldItemToDBItem.addClickHandler(new ClickHandler() {
-
- public void onClick(MenuItemClickEvent menuItemClickEvent) {
- DashboardPortlet p = new DashboardPortlet(MSG
- .view_tree_common_contextMenu_resourceGraph(), ResourceGraphPortlet.KEY,
- 250);
- p.getConfiguration().put(
- new PropertySimple(ResourceGraphPortlet.CFG_RESOURCE_ID, resource.getId()));
- p.getConfiguration().put(
- new PropertySimple(ResourceGraphPortlet.CFG_DEFINITION_ID, def.getId()));
-
- d.addPortlet(p);
-
- GWTServiceLookup.getDashboardService().storeDashboard(d,
- new AsyncCallback<Dashboard>() {
-
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_tree_common_contextMenu_saveChartToDashboardFailure(),
- caught);
- }
-
- public void onSuccess(Dashboard result) {
- CoreGUI
- .getMessageCenter()
- .notify(
- new Message(
- MSG.view_tree_common_contextMenu_saveChartToDashboardSuccessful(result
- .getName()), Message.Severity.Info));
- }
- });
-
- }
- });
}//end dashboard iteration
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java
deleted file mode 100644
index 9e93072..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/GraphListView.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.List;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.Overflow;
-import com.smartgwt.client.widgets.Label;
-
-import org.rhq.core.domain.measurement.DataType;
-import org.rhq.core.domain.measurement.DisplayType;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.resource.composite.ResourceComposite;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.components.measurement.UserPreferencesMeasurementRangeEditor;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.ResourceSelectListener;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityBarView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
-
-/**
- * @author Greg Hinkle
- */
-@Deprecated
-public class GraphListView extends EnhancedVLayout implements ResourceSelectListener {
-
- private Resource resource;
- private Label loadingLabel = new Label(MSG.common_msg_loading());
-
- public GraphListView(Resource resource) {
- super();
-
- this.resource = resource;
- setOverflow(Overflow.AUTO);
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
-
- destroyMembers();
-
- addMember(new AvailabilityBarView(resource));
-
- // addMember(loadingLabel);
-
- addMember(new UserPreferencesMeasurementRangeEditor());
-
- if (resource != null) {
- buildGraphs();
- }
- }
-
- private void buildGraphs() {
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(resource.getResourceType().getId(),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypeLoadedCallback() {
- public void onTypesLoaded(final ResourceType type) {
-
- final ArrayList<MeasurementDefinition> measurementDefinitions = new ArrayList<MeasurementDefinition>();
-
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getDataType() == DataType.MEASUREMENT && def.getDisplayType() == DisplayType.SUMMARY) {
- measurementDefinitions.add(def);
- }
- }
-
- Collections.sort(measurementDefinitions, new Comparator<MeasurementDefinition>() {
- public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
- return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
- }
- });
-
- int[] measDefIdArray = new int[measurementDefinitions.size()];
- for (int i = 0; i < measDefIdArray.length; i++) {
- measDefIdArray[i] = measurementDefinitions.get(i).getId();
- }
-
- GWTServiceLookup.getMeasurementDataService().findDataForResourceForLast(resource.getId(),
- measDefIdArray, 8, MeasurementUtils.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_loadFailed(),
- caught);
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_loadFailed());
- }
-
- public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> result) {
- if (result.isEmpty()) {
- loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
- } else {
- loadingLabel.hide();
- int i = 0;
- for (List<MeasurementDataNumericHighLowComposite> data : result) {
- buildGraph(measurementDefinitions.get(i++), data);
- }
- }
- }
- });
-
- }
- });
- }
-
- private void buildGraph(MeasurementDefinition def, List<MeasurementDataNumericHighLowComposite> data) {
- ResourceMetricGraphView graph = new ResourceMetricGraphView(resource.getId(), def, data);
- graph.setWidth("95%");
- graph.setHeight(220);
-
- addMember(graph);
- }
-
- public void onResourceSelected(ResourceComposite resourceComposite) {
- this.resource = resourceComposite.getResource();
-
- buildGraphs();
- markForRedraw();
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
deleted file mode 100644
index f71e307..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/LiveGraphView.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Set;
-
-import ca.nanometrics.gflot.client.Axis;
-import ca.nanometrics.gflot.client.DataPoint;
-import ca.nanometrics.gflot.client.PlotModel;
-import ca.nanometrics.gflot.client.PlotModelStrategy;
-import ca.nanometrics.gflot.client.SeriesHandler;
-import ca.nanometrics.gflot.client.SimplePlot;
-import ca.nanometrics.gflot.client.event.PlotHoverListener;
-import ca.nanometrics.gflot.client.event.PlotItem;
-import ca.nanometrics.gflot.client.event.PlotPosition;
-import ca.nanometrics.gflot.client.jsni.Plot;
-import ca.nanometrics.gflot.client.options.AxisOptions;
-import ca.nanometrics.gflot.client.options.GlobalSeriesOptions;
-import ca.nanometrics.gflot.client.options.GridOptions;
-import ca.nanometrics.gflot.client.options.LineSeriesOptions;
-import ca.nanometrics.gflot.client.options.PlotOptions;
-import ca.nanometrics.gflot.client.options.PointsSeriesOptions;
-import ca.nanometrics.gflot.client.options.TickFormatter;
-
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.types.AnimationEffect;
-import com.smartgwt.client.widgets.Canvas;
-import com.smartgwt.client.widgets.HTMLFlow;
-import com.smartgwt.client.widgets.Label;
-import com.smartgwt.client.widgets.WidgetCanvas;
-import com.smartgwt.client.widgets.Window;
-import com.smartgwt.client.widgets.events.ClickEvent;
-import com.smartgwt.client.widgets.events.ClickHandler;
-import com.smartgwt.client.widgets.events.CloseClickEvent;
-import com.smartgwt.client.widgets.events.CloseClickHandler;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-
-import org.rhq.core.domain.measurement.MeasurementData;
-import org.rhq.core.domain.measurement.MeasurementDataNumeric;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.MeasurementDataGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
-
-/**
- * @author Greg Hinkle
- */
-@Deprecated
-public class LiveGraphView extends EnhancedVLayout {
-
- private static final String INSTRUCTIONS = MSG.view_resource_monitor_graph_instructions();
-
- private final Label selectedPointLabel = new Label(INSTRUCTIONS);
- private final Label positionLabel = new Label();
-
- private final Label hoverLabel = new Label();
-
- private int resourceId;
- private MeasurementDefinition definition;
-
- private SimplePlot plot;
- private Timer dataLoader;
- @SuppressWarnings("unused")
- private long min, max;
-
- public LiveGraphView() {
- super();
- }
-
- public LiveGraphView(int resourceId, MeasurementDefinition def) {
- super();
- this.resourceId = resourceId;
- this.definition = def;
- setHeight100();
- setWidth100();
- }
-
- public String getName() {
- return "PlotHoverListener";
- }
-
- @Override
- protected void onDraw() {
- super.onDraw();
-
- for (Canvas c : getChildren()) {
- c.destroy();
- }
-
- drawGraph();
- }
-
- @Override
- protected void onDetach() {
- super.onDetach(); // TODO: Implement this method.
- }
-
- @Override
- protected void onUnload() {
- super.onUnload(); // TODO: Implement this method.
- }
-
- @Override
- public void parentResized() {
- super.parentResized();
- onDraw();
- }
-
- private void drawGraph() {
-
- PlotModel model = new PlotModel();
- PlotOptions plotOptions = new PlotOptions();
- GlobalSeriesOptions globalSeriesOptions = new GlobalSeriesOptions();
- globalSeriesOptions.setLineSeriesOptions(new LineSeriesOptions().setLineWidth(1).setShow(true));
- globalSeriesOptions.setPointsOptions(new PointsSeriesOptions().setRadius(2).setShow(true));
- globalSeriesOptions.setShadowSize(0);
- plotOptions.setGlobalSeriesOptions(globalSeriesOptions);
-
- // You need make the grid hoverable <<<<<<<<<
- plotOptions
- .setGridOptions(new GridOptions().setHoverable(true).setMouseActiveRadius(10).setAutoHighlight(true));
-
- // create a series
- loadData(model, plotOptions);
-
- // create the plot
- plot = new SimplePlot(model, plotOptions);
- plot.setSize(String.valueOf(getInnerContentWidth()), String.valueOf(getInnerContentHeight() - 20));
-
- // add hover listener
- plot.addHoverListener(new PlotHoverListener() {
- public void onPlotHover(Plot plot, PlotPosition position, PlotItem item) {
- if (position != null) {
- positionLabel.setContents("position: (" + position.getX() + "," + position.getY() + ")");
- }
- if (item != null) {
- hoverLabel.setContents(getHover(item));
-
- hoverLabel.animateShow(AnimationEffect.FADE);
- if (hoverLabel.getLeft() > 0 || hoverLabel.getTop() > 0) {
- hoverLabel.animateMove(item.getPageX() + 5, item.getPageY() + 5);
- } else {
- hoverLabel.moveTo(item.getPageX() + 5, item.getPageY() + 5);
- }
- hoverLabel.redraw();
-
- selectedPointLabel.setContents("x: " + item.getDataPoint().getX() + ", y: "
- + item.getDataPoint().getY());
- } else {
- hoverLabel.animateHide(AnimationEffect.FADE);
- selectedPointLabel.setContents(INSTRUCTIONS);
- }
- }
- }, false);
-
- addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- hoverLabel.animateHide(AnimationEffect.FADE);
- }
- });
-
- hoverLabel.setOpacity(80);
- hoverLabel.setWrap(false);
- hoverLabel.setHeight(25);
- hoverLabel.setBackgroundColor("yellow");
- hoverLabel.setBorder("1px solid orange");
- hoverLabel.hide();
-
- hoverLabel.draw();
-
- // put it on a panel
-
- if (definition != null) {
-
- HTMLFlow title = new HTMLFlow("<b>" + definition.getDisplayName() + "</b> " + definition.getDescription());
- title.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- // displayAsDialog();
- }
- });
-
- addMember(title);
- }
-
- addMember(new WidgetCanvas(plot));
- }
-
- private String getHover(PlotItem item) {
- if (definition != null) {
- DateTimeFormat df = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return definition.getDisplayName() + ": "
- + MeasurementConverterClient.format(item.getDataPoint().getY(), definition.getUnits(), true) + "<br/>"
- + df.format(new Date((long) item.getDataPoint().getX()));
- } else {
- return "x: " + item.getDataPoint().getX() + ", y: " + item.getDataPoint().getY();
- }
- }
-
- private void loadData(final PlotModel model, final PlotOptions plotOptions) {
- final SeriesHandler handler = model.addSeries(definition.getDisplayName(), "#007f00");
-
- model.setStrategy(PlotModelStrategy.slidingWindowStrategy(60));
- final MeasurementDataGWTServiceAsync dataService = GWTServiceLookup.getMeasurementDataService();
-
- dataLoader = new Timer() {
- @Override
- public void run() {
- dataService.findLiveData(resourceId, new int[] { definition.getId() },
- new AsyncCallback<Set<MeasurementData>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler()
- .handleError(MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- public void onSuccess(Set<MeasurementData> result) {
- Iterator<MeasurementData> i = result.iterator();
- if (!i.hasNext()) {
- return;
- }
-
- MeasurementDataNumeric d = (MeasurementDataNumeric) i.next();
-
- handler.add(new DataPoint(d.getTimestamp(), d.getValue()));
- plot.redraw();
- }
- });
- }
- };
-
- dataLoader.scheduleRepeating(1000);
-
- plotOptions.addYAxisOptions(new AxisOptions().setLabelWidth(70).setTicks(5)
- .setTickFormatter(new TickFormatter() {
- public String formatTickValue(double v, Axis axis) {
- return MeasurementConverterClient.format(v, definition.getUnits(), true);
- }
- }));
-
- plotOptions.addXAxisOptions(new AxisOptions().setTicks(8).setTickFormatter(new TickFormatter() {
- public String formatTickValue(double tickValue, Axis axis) {
- DateTimeFormat dateFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM);
- return dateFormat.format(new Date((long) tickValue));
- }
- }));
-
- }
-
- public static void displayAsDialog(int resourceId, MeasurementDefinition def) {
- final LiveGraphView graph = new LiveGraphView(resourceId, def);
- final Window graphPopup = new Window();
- graphPopup.setTitle(MSG.view_resource_monitor_detailed_graph_label());
- graphPopup.setWidth(800);
- graphPopup.setHeight(400);
- graphPopup.setIsModal(true);
- graphPopup.setShowModalMask(true);
- graphPopup.setCanDragResize(true);
- graphPopup.centerInPage();
- graphPopup.addItem(graph);
- graphPopup.show();
-
- graphPopup.addCloseClickHandler(new CloseClickHandler() {
- public void onCloseClick(CloseClickEvent closeClientEvent) {
- graph.stop();
- graphPopup.destroy();
- }
- });
- }
-
- protected void stop() {
- hoverLabel.destroy();
- dataLoader.cancel();
- }
-
- @Override
- protected void onDestroy() {
- stop();
- super.onDestroy();
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java
deleted file mode 100644
index 6db0d56..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/ResourceMetricGraphView.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.HTMLFlow;
-
-import org.rhq.core.domain.criteria.ResourceCriteria;
-import org.rhq.core.domain.measurement.MeasurementDefinition;
-import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.LinkManager;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.gwt.ResourceGWTServiceAsync;
-import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractMetricGraphView;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.server.measurement.util.MeasurementUtils;
-
-/**
- * @deprecated should be replaced with new d3 graph views
- * @author Greg Hinkle
- * @author Jay Shaughnessy
- */
-@Deprecated
-public class ResourceMetricGraphView extends AbstractMetricGraphView {
-
- private HTMLFlow resourceTitle;
-
- public ResourceMetricGraphView() {
- super();
- }
-
- public ResourceMetricGraphView(int resourceId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- super(resourceId, def, data);
- }
-
- @Override
- protected HTMLFlow getEntityTitle() {
- return resourceTitle;
- }
-
- @Override
- protected void renderGraph() {
- if (null == getDefinition()) {
-
- ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService();
-
- ResourceCriteria resourceCriteria = new ResourceCriteria();
- resourceCriteria.addFilterId(getEntityId());
- resourceService.findResourcesByCriteria(resourceCriteria, new AsyncCallback<PageList<Resource>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_lookupFailed(), caught);
- }
-
- @Override
- public void onSuccess(PageList<Resource> result) {
- if (result.isEmpty()) {
- return;
- }
-
- final Resource resource = result.get(0);
- HashSet<Integer> typesSet = new HashSet<Integer>();
- typesSet.add(resource.getResourceType().getId());
- HashSet<String> ancestries = new HashSet<String>();
- ancestries.add(resource.getAncestry());
- // In addition to the types of the result resources, get the types of their ancestry
- typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
-
- ResourceTypeRepository.Cache.getInstance().getResourceTypes(
- typesSet.toArray(new Integer[typesSet.size()]),
- EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
- new ResourceTypeRepository.TypesLoadedCallback() {
-
- public void onTypesLoaded(Map<Integer, ResourceType> types) {
- String url = LinkManager.getResourceLink(resource.getId());
- resourceTitle = new HTMLFlow(LinkManager.getHref(url, resource.getName()));
- resourceTitle.setTooltip(AncestryUtil.getAncestryHoverHTMLForResource(resource, types,
- 0));
-
- ResourceType type = types.get(resource.getResourceType().getId());
- for (MeasurementDefinition def : type.getMetricDefinitions()) {
- if (def.getId() == getDefinitionId()) {
- setDefinition(def);
-
- GWTServiceLookup.getMeasurementDataService().findDataForResourceForLast(
- getEntityId(), new int[] { getDefinitionId() }, 8,
- MeasurementUtils.UNIT_HOURS, 60,
- new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
- @Override
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(
- MSG.view_resource_monitor_graphs_loadFailed(), caught);
- }
-
- @Override
- public void onSuccess(
- List<List<MeasurementDataNumericHighLowComposite>> result) {
- setData(result.get(0));
-
- drawGraph();
- }
- });
- }
- }
- }
- });
- }
- });
-
- } else {
- drawGraph();
- }
- }
-
- @Override
- protected boolean supportsLiveGraphViewDialog() {
- return true;
- }
-
- @Override
- protected void displayLiveGraphViewDialog() {
- LiveGraphView.displayAsDialog(getEntityId(), getDefinition());
- }
-
- @Override
- public AbstractMetricGraphView getInstance(int entityId, MeasurementDefinition def,
- List<MeasurementDataNumericHighLowComposite> data) {
-
- return new ResourceMetricGraphView(entityId, def, data);
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java
deleted file mode 100644
index 5d40b1b..0000000
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityBarView.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitoring.avail;
-
-import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.widgets.Img;
-import com.smartgwt.client.widgets.events.MouseOutEvent;
-import com.smartgwt.client.widgets.events.MouseOutHandler;
-import com.smartgwt.client.widgets.events.MouseOverEvent;
-import com.smartgwt.client.widgets.events.MouseOverHandler;
-import com.smartgwt.client.widgets.layout.HLayout;
-
-import org.rhq.core.domain.criteria.AvailabilityCriteria;
-import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.MeasurementUnits;
-import org.rhq.core.domain.resource.Resource;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.core.domain.util.PageOrdering;
-import org.rhq.enterprise.gui.coregui.client.CoreGUI;
-import org.rhq.enterprise.gui.coregui.client.ImageManager;
-import org.rhq.enterprise.gui.coregui.client.Messages;
-import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
-import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient;
-
-/**
- * This is a potential replacement to the JSF "Christmas Tree". Unused at the moment but something to
- * consider when we replace JSF completely.
- *
- * @author Greg Hinkle
- */
-@Deprecated
-public class AvailabilityBarView extends HLayout {
-
- Messages MSG = CoreGUI.getMessages();
-
- private Resource resource;
-
- public AvailabilityBarView(Resource resource) {
- this.resource = resource;
- setHeight(28);
- setWidth100();
- setMargin(10);
- }
-
- @Override
- protected void onInit() {
- super.onInit();
-
- AvailabilityCriteria c = new AvailabilityCriteria();
- c.addFilterResourceId(resource.getId());
- c.addSortStartTime(PageOrdering.ASC);
- GWTServiceLookup.getAvailabilityService().findAvailabilityByCriteria(c,
- new AsyncCallback<PageList<Availability>>() {
- public void onFailure(Throwable caught) {
- CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_availability_loadFailed(), caught);
- }
-
- public void onSuccess(PageList<Availability> result) {
- update(result);
- }
- });
- }
-
- private void update(PageList<Availability> result) {
-
- long start = result.get(0).getStartTime();
- long end = result.get(result.size() - 1).getEndTime() != null ? result.get(result.size() - 1).getEndTime()
- : System.currentTimeMillis();
-
- long diff = end - start;
-
- Img leftCap = new Img("availBar/leftCap.png", 8, 28);
- addMember(leftCap);
-
- for (Availability a : result) {
-
- long endTime = a.getEndTime() != null ? a.getEndTime() : System.currentTimeMillis();
-
- double width = (((double) (endTime - a.getStartTime()) / diff) * 100);
- String widthString = width + "%";
- if (width == 0) {
- widthString = "2px";
- }
-
- String imagePath = ImageManager.getAvailBarImagePath(a.getAvailabilityType());
-
- final Img section = new Img(imagePath);
- section.setHeight(28);
- section.setOpacity(60);
- section.setWidth(widthString);
-
- section.addMouseOverHandler(new MouseOverHandler() {
- public void onMouseOver(MouseOverEvent mouseOverEvent) {
- section.animateFade(100);
- }
- });
- section.addMouseOutHandler(new MouseOutHandler() {
- public void onMouseOut(MouseOutEvent mouseOutEvent) {
- section.animateFade(60);
- }
- });
-
- long duration = endTime - a.getStartTime();
-
- String durationString = MeasurementConverterClient.format((double) duration, MeasurementUnits.MILLISECONDS,
- true);
-
- section.setTooltip("<div style=\"white-space: nowrap;\"><b>" + MSG.common_title_availability() + ": </b>"
- + a.getAvailabilityType().name() + "<br/><b>" + MSG.common_title_start() + ": </b>" + a.getStartTime()
- + "<br/><b>" + MSG.common_title_end() + ": </b>" + a.getEndTime() + "<br/><b>"
- + MSG.common_title_duration() + ": </b>" + durationString);
-
- addMember(section);
-
- }
- Img rightCap = new Img("availBar/rightCap.png", 8, 28);
- addMember(rightCap);
-
- }
-}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
index 3a39c2e..c6ad891 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MeasurementTableView.java
@@ -146,55 +146,8 @@ public class MeasurementTableView extends Table<MeasurementTableDataSource> {
}
});
- //@todo: delete once satisfied with d3 chart verification
- //add chart selected metric action
- addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
- @Override
- public boolean isEnabled(ListGridRecord[] selection) {
- return selection != null && selection.length > 0;
- }
-
- @Override
- public void executeAction(ListGridRecord[] selection, Object actionValue) {
- if (selection == null || selection.length == 0) {
- return;
- }
- // keyed on metric name - string[0] is the metric label, [1] is the units
- final HashMap<String, String[]> scheduleNamesAndUnits = new HashMap<String, String[]>();
- int[] definitionIds = new int[selection.length];
- int i = 0;
- for (ListGridRecord record : selection) {
- Integer defId = record.getAttributeAsInt(MeasurementTableDataSource.FIELD_METRIC_DEF_ID);
- definitionIds[i++] = defId.intValue();
- String name = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_NAME);
- String label = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_LABEL);
- String units = record.getAttribute(MeasurementTableDataSource.FIELD_METRIC_UNITS);
- if (units == null || units.length() < 1) {
- units = MeasurementUnits.NONE.name();
- }
-
- scheduleNamesAndUnits.put(name, new String[] { label, units });
- }
-
- //build portal.war chart page to iFrame
- String destination = "/resource/common/monitor/Visibility.do?mode=chartMultiMetricSingleResource&id="
- + resourceId;
- for (int mId : definitionIds) {
- destination += "&m=" + mId;
- }
- ChartViewWindow window = new ChartViewWindow("");
- //generate and include iframed content
- FullHTMLPane iframe = new FullHTMLPane(destination);
- window.addItem(iframe);
- window.show();
- refreshTableInfo();
- }
- });
-
- // new d3 chart selection
- //@todo: i18n when we remove gflot graphs
- addTableAction("d3 Chart Selection", new TableAction() {
+ addTableAction(MSG.view_measureTable_chartMetricValues(), new TableAction() {
@Override
public boolean isEnabled(ListGridRecord[] selection) {
return selection != null && selection.length > 0;
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
index 0cd10cb..3d5ae84 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/CoreGUI.gwt.xml
@@ -11,11 +11,6 @@
<inherits name='com.smartgwt.SmartGwt' />
<inherits name="com.smartgwt.tools.SmartGwtTools"/>
-
- <!-- @todo: take out GFlot once we have d3 graphing in place -->
- <inherits name='ca.nanometrics.gflot.GFlot'/>
- <set-property name="gflot.load.jquery" value="EXTERNAL" />
-
<!-- ============================ gwt logging ============================= -->
<set-property name="gwt.logging.enabled" value="TRUE"/>
<!-- FINE ~= DEBUG in gwt-log -->
commit ca17805e57e131a9b1972987827d54a63d5b8fb0
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 17:04:34 2013 -0400
BZ 951121 - tell the user the server is still starting if they attempt to login during startup
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
index 46ea7f2..d896e63 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LoginView.java
@@ -67,11 +67,10 @@ import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
-import org.rhq.enterprise.gui.coregui.client.util.BrowserUtility;
import org.rhq.enterprise.gui.coregui.client.util.Log;
-import org.rhq.enterprise.gui.coregui.client.util.message.Message;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton;
import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/**
* @author Greg Hinkle
@@ -572,6 +571,8 @@ public class LoginView extends Canvas {
private void handleError(int statusCode) {
if (statusCode == 401) {
form.setFieldErrors("login", MSG.view_login_noUser(), true);
+ } else if (statusCode == 503) {
+ form.setFieldErrors("login", MSG.view_core_serverInitializing(), true);
} else {
form.setFieldErrors("login", MSG.view_login_noBackend(), true);
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
index f803b24..6995e4f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/UserSessionManager.java
@@ -154,6 +154,12 @@ public class UserSessionManager {
Log.info("response text = " + response.getText());
String sessionIdString = response.getText();
+ if (sessionIdString.startsWith("booting")) {
+ // "booting" is the string we get back from SessionAccessServlet if StartupBean hasn't finished
+ new LoginView().showLoginDialog(MSG.view_core_serverInitializing());
+ return;
+ }
+
// If a session is active it will return valid session strings
if (sessionIdString != null && sessionIdString.length() > 0) {
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 0b75e4f..0c5af20 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -1357,6 +1357,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = The following connection
view_core_loggedOut = Logged out
view_core_noRecentAlerts = There are no recent alerts to report
view_core_recentAlerts = There are [{0}] recent alerts - click to go to the recent alerts report
+view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = Globally uncaught exception
view_dashboardManager_deleteFail = Failed to delete dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
index bd735d0..42405aa 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties
@@ -1372,6 +1372,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = Následující položky m
view_core_loggedOut = Odhlášeno
view_core_noRecentAlerts = Nejsou žádné nedávné výstrahy k hlášení
view_core_recentAlerts = Je [{0}] nedávných výstrah - klikněte pro přechod na hlášení
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = Server je nedosažitelný, možná spadl
view_core_uncaught = Globálné nezachycená výjimka
view_dashboardManager_deleteFail = Nepodařilo se smazat dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
index 0ad2504..8185e7f 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties
@@ -1226,6 +1226,7 @@ view_configurationHistoryList_title = Konfigurationsänderungen
view_core_loggedOut = Ausgeloggt
view_core_noRecentAlerts = Es liegen keine frischen Alarme vor
view_core_recentAlerts = [{0}] frische Alarme
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = Kann den Server nicht erreichen. Er abgeschaltet sein.
view_core_uncaught = Es ist eine nicht abgefangene Ausnahme aufgetreten.
view_dashboardManager_deleteFail = Konnte das Dashboard nicht löschen.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
index ef42475..c15e129 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties
@@ -1352,6 +1352,7 @@ view_core_loggedInAs = {0} としてログイン
view_core_loggedOut = ログアウト
view_core_noRecentAlerts = レポートすべき最近のアラートは存在しません
view_core_recentAlerts = [{0}] 個の最近のアラートがありました - 最近のアラートレポートへクリックしてください
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = サーバーに到達できません。ダウンしている可能性があります。
view_core_uncaught = グローバルにキャッチされない例外
view_dashboardManager_deleteFail = ダッシュボードの削除に失敗しました
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
index 1d3530e..8105460 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties
@@ -1163,6 +1163,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = 다음 연결 설정은
view_core_loggedOut = 로그 아웃
view_core_noRecentAlerts = 리포트에서 최근 알림이 없습니다
view_core_recentAlerts = [{0}] 최근 경고가 있습니다 - 최근 경고 리포트를 클릭하십시오
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
view_core_serverUnreachable = 서버에 접근할 수 없거나 다운되었을 수 있습니다
view_core_uncaught = 글로벌 캐치되지 않은 예외
view_dashboardManager_deleteFail = 대시 보드의 제거에 실패했습니다.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
index b7cab71..d50a54e 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties
@@ -1363,6 +1363,7 @@ view_core_loggedInAs = Logado como {0}
view_core_loggedOut = Desconectado
view_core_noRecentAlerts = N�o existem alertas recentes
view_core_recentAlerts = [{0}] alertas recentes
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = Exce\u00E7\u00E3o n\u00E3o capturada
view_dashboardManager_deleteFail = Falha ao excluir o dashboard.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
index 56cf3e6..fb45e35 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties
@@ -2675,6 +2675,7 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль
##view_configEdit_property = Vlastnost
##view_configEdit_unset = Unset?
##view_configEdit_value = Value
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_dashboardsManager_message_title_details = <h1>Welcome to {0}</h1>\n<p>This dashboard can be edited by clicking the (Edit Mode) button above.</p>\n<p>What would you like to do?</p>\n<p> <a href=\"{1}\">Import newly discovered resources.</a></p>\n<p> <a href=\"{2}\">Search for resources.</a></p>\n<p> <a href=\"{3}\">See help and documentation.</a></p>
##view_dynagroup_exprBuilder_groupBy = Group by
##view_dynagroup_exprBuilder_groupBy_tooltip = groupby will cause the system to pivot on the values from the entered expressions creating a separate group for each value. For example, groupby on the cluster name to create a group for each cluster with all cluster members in it.
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
index 5e6afec..e929386 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties
@@ -1345,6 +1345,7 @@ view_connectionSettingsDetails_somePropertiesInvalid = \u4e0b\u9762\u7684\u8fde\
view_core_loggedOut = \u9000\u51fa\u767b\u5f55
view_core_noRecentAlerts = \u6ca1\u6709\u65b0\u4ea7\u751f\u7684\u544a\u8b66\u4fe1\u606f
view_core_recentAlerts = \u65b0\u4ea7\u751f [{0}] \u6761\u544a\u8b66 - \u70b9\u51fb\u8df3\u8f6c\u5230\u65b0\u544a\u8b66\u62a5\u8868\u754c\u9762
+##view_core_serverInitializing = The server is currently starting up. Please wait for it to fully initialize before attempting to log in.
##view_core_serverUnreachable = The server is unreachable and may be down
view_core_uncaught = \u5168\u5c40\u672a\u6355\u6349\u7684\u5f02\u5e38
view_dashboardManager_deleteFail = \u5220\u9664\u7edf\u8ba1\u8868\u76d8\u5931\u8d25.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
index caf4ab5..f7cca42 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/authentication/SessionAccessServlet.java
@@ -38,6 +38,7 @@ import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SessionNotFoundException;
import org.rhq.enterprise.server.auth.SessionTimeoutException;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* @author Greg Hinkle
@@ -59,6 +60,20 @@ public class SessionAccessServlet extends HttpServlet {
// some date in the past
response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
+ // do not go any further unless we know the server has been fully initialized
+ boolean serverInitialized;
+ try {
+ serverInitialized = LookupUtil.getStartupLocal().isInitialized();
+ } catch (Throwable t) {
+ serverInitialized = false; // this probably means we are still starting up and app server hasn't made EJBs available yet
+ }
+
+ if (!serverInitialized) {
+ response.setHeader("Retry-After", "30");
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Server is not ready - still booting up");
+ return;
+ }
+
//if a session does not already exist this call will create one
HttpSession session = request.getSession();
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
index 8743a33..c80e517 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/AuthenticationFilter.java
@@ -38,6 +38,7 @@ import org.rhq.enterprise.gui.legacy.util.SessionUtils;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.SessionNotFoundException;
import org.rhq.enterprise.server.auth.SessionTimeoutException;
+import org.rhq.enterprise.server.util.LookupUtil;
public final class AuthenticationFilter extends BaseFilter {
@@ -49,6 +50,20 @@ public final class AuthenticationFilter extends BaseFilter {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
+ // do not go any further unless we know the server has been fully initialized
+ boolean serverInitialized;
+ try {
+ serverInitialized = LookupUtil.getStartupLocal().isInitialized();
+ } catch (Throwable t) {
+ serverInitialized = false; // this probably means we are still starting up and app server hasn't made EJBs available yet
+ }
+
+ if (!serverInitialized) {
+ response.setHeader("Retry-After", "30");
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Server is not ready - still booting up");
+ return;
+ }
+
//if a session does not already exist this call will create one
HttpSession session = request.getSession();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
index de4f6fe..5b5aa8c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBean.java
@@ -100,7 +100,7 @@ import org.rhq.enterprise.server.util.concurrent.AvailabilityReportSerializer;
*/
@Singleton
//@Startup // when AS7-5530 is fixed, uncomment this and remove class StartupBeanToWorkaroundAS7_5530
-public class StartupBean {
+public class StartupBean implements StartupLocal {
private Log log = LogFactory.getLog(this.getClass());
private boolean initialized = false;
@@ -138,6 +138,12 @@ public class StartupBean {
@Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
private DataSource dataSource;
+ @Override
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public boolean isInitialized() {
+ return this.initialized;
+ }
+
/**
* Modifies the naming subsystem to be able to check for Java security permissions on JNDI lookup.
* <p>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
index 88790d5..c66d328 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupBeanPreparation.java
@@ -43,7 +43,7 @@ public class StartupBeanPreparation {
private Log log = LogFactory.getLog(this.getClass());
@EJB
- private StartupBean startupBean;
+ private StartupLocal startupBean;
@Resource
private TimerService timerService; // needed to schedule our startup bean init call
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java
new file mode 100644
index 0000000..bc98bbf
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/StartupLocal.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package org.rhq.enterprise.server.core;
+
+import javax.ejb.Local;
+
+@Local
+public interface StartupLocal {
+ /**
+ * When false is returned, it means the startup bean has not finished initializing the server.
+ * Only when true is returned can we be assured that the server has been fully started and initialized, ready to accept
+ * agent requests and user requests from browser/remote clients.
+ *
+ * @return true if the startup bean has fully initialized the server
+ */
+ boolean isInitialized();
+
+ /**
+ * Tells the startup bean to do its work. This will finish the initialization of the server.
+ */
+ void init();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 112a590..698ec85 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -103,6 +103,8 @@ import org.rhq.enterprise.server.core.EmailManagerBean;
import org.rhq.enterprise.server.core.EmailManagerLocal;
import org.rhq.enterprise.server.core.RemoteClientManagerBean;
import org.rhq.enterprise.server.core.RemoteClientManagerLocal;
+import org.rhq.enterprise.server.core.StartupBean;
+import org.rhq.enterprise.server.core.StartupLocal;
import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.dashboard.DashboardManagerBean;
import org.rhq.enterprise.server.dashboard.DashboardManagerLocal;
@@ -589,6 +591,10 @@ public final class LookupUtil {
return lookupLocal(SubjectPreferencesCacheBean.class);
}
+ public static StartupLocal getStartupLocal() {
+ return lookupLocal(StartupBean.class);
+ }
+
public static CoreServerMBean getCoreServer() {
MBeanServer mbs = getJBossMBeanServer();
CoreServerMBean rhqServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class,
commit 58e3a41e18d47c955129d97c68a4149bea01a983
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 13:14:10 2013 -0400
BZ 951382 - in agent-configuration.xml, use "conf" instead to make it clear the user should probably put their certs in the conf/ directory.
diff --git a/modules/enterprise/agent/src/main/resources/agent-configuration.xml b/modules/enterprise/agent/src/main/resources/agent-configuration.xml
index 61339fe..d59fe71 100644
--- a/modules/enterprise/agent/src/main/resources/agent-configuration.xml
+++ b/modules/enterprise/agent/src/main/resources/agent-configuration.xml
@@ -1014,36 +1014,35 @@ commands named "config", "setconfig" and "setup" and the command line options
rhq.agent.client.security.server-auth-mode-enabled
These are the settings that are used if SSL is to be used for
- either the server or client communications. These can be left
- unset since the defaults will normally suffice. These
- properties are here just in case some use case occurs that
- require one or more of these settings to be customized.
+ either the server-side or client-side communications (that is,
+ for incoming messages into the agent and for outgoing messages
+ getting sent by the agent).
Note that if client-auth-mode is specified, it must be one of:
"none", "want", "need".
-->
<!--
<entry key="rhq.communications.connector.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.communications.connector.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.communications.connector.security.keystore.file" value="conf/keystore.dat" />
<entry key="rhq.communications.connector.security.keystore.algorithm" value="SunX509" />
<entry key="rhq.communications.connector.security.keystore.type" value="JKS" />
<entry key="rhq.communications.connector.security.keystore.password" value="rhqpwd" />
<entry key="rhq.communications.connector.security.keystore.key-password" value="rhqpwd" />
<entry key="rhq.communications.connector.security.keystore.alias" value="rhq" />
- <entry key="rhq.communications.connector.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.communications.connector.security.truststore.file" value="conf/truststore.dat" />
<entry key="rhq.communications.connector.security.truststore.algorithm" value="SunX509" />
<entry key="rhq.communications.connector.security.truststore.type" value="JKS" />
<entry key="rhq.communications.connector.security.truststore.password" value="" />
<entry key="rhq.communications.connector.security.client-auth-mode" value="none" />
<entry key="rhq.agent.client.security.secure-socket-protocol" value="TLS" />
- <entry key="rhq.agent.client.security.keystore.file" value="data/keystore.dat" />
+ <entry key="rhq.agent.client.security.keystore.file" value="conf/keystore.dat" />
<entry key="rhq.agent.client.security.keystore.algorithm" value="SunX509" />
<entry key="rhq.agent.client.security.keystore.type" value="JKS" />
<entry key="rhq.agent.client.security.keystore.password" value="rhqpwd" />
<entry key="rhq.agent.client.security.keystore.key-password" value="rhqpwd" />
<entry key="rhq.agent.client.security.keystore.alias" value="rhq" />
- <entry key="rhq.agent.client.security.truststore.file" value="data/truststore.dat" />
+ <entry key="rhq.agent.client.security.truststore.file" value="conf/truststore.dat" />
<entry key="rhq.agent.client.security.truststore.algorithm" value="SunX509" />
<entry key="rhq.agent.client.security.truststore.type" value="JKS" />
<entry key="rhq.agent.client.security.truststore.password" value="" />
commit 00be4f6ba09fd8f6a1cf55a99a4fd1f6f25130d6
Author: Thomas Segismont <tsegismo(a)redhat.com>
Date: Tue Apr 16 22:04:50 2013 +0200
Bug 593932 - (PRODMGT-355) Allow Trap OID for SNMP notification to be overridden per-alert definition
Snmp trap OID is set on v2c and v3 traps as the second variable binding.
In the past, users had been confused by the name of the SNMP notification parameter 'oid'. This parameter actually defines a variable binding prefix for the RHQ alert bindings.
Added tests for this server plugin
Added documentation to the plugin descriptor
diff --git a/modules/enterprise/server/plugins/alert-snmp/pom.xml b/modules/enterprise/server/plugins/alert-snmp/pom.xml
index 909053a..b09ed2a 100644
--- a/modules/enterprise/server/plugins/alert-snmp/pom.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/pom.xml
@@ -13,12 +13,32 @@
<name>RHQ Enterprise Server SNMP Alert Plugin</name>
+ <properties>
+ <alert.snmp.test.port>35162</alert.snmp.test.port>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.snmp4j</groupId>
<artifactId>snmp4j</artifactId>
<version>1.8.2</version>
</dependency>
+
+ <!-- Test dependencies -->
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>test-utils</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ <version>1.9.5</version>
+ </dependency>
+
</dependencies>
<build>
@@ -27,10 +47,14 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!--
- <argLine>${jacoco.unit-test.args} -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+ <properties>
+ <property>
+ <name>listener</name>
+ <value>org.rhq.test.testng.StdoutReporter</value>
+ </property>
+ </properties>
+ <useSystemClassLoader>false</useSystemClassLoader>
+ <argLine>${jacoco.unit-test.args}</argLine>
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
index 082e706..c92daae 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfo.java
@@ -1,19 +1,55 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
package org.rhq.enterprise.server.plugins.alertSnmp;
import org.rhq.core.domain.configuration.Configuration;
+/**
+ * Utility class giving a view of SNMP alert notification parameters.
+ *
+ * @deprecated as of 4.7. It's an internal utility class and should not have been made public.
+ */
+@Deprecated
public class SnmpInfo {
+ // SNMP Alert Notification parameter names
+ static final String PARAM_HOST = "host";
+ static final String PARAM_PORT = "port";
+ static final String PARAM_VARIABLE_BINDING_PREFIX = "oid";
+ static final String PARAM_TRAP_OID = "trapOid";
+
+ // Default remote port for SNMP trap
+ static final String DEFAULT_PORT = "162";
+
final public String host;
final public String port;
final public String oid;
+ final public String trapOid;
final public String error;
- private SnmpInfo(String host, String port, String oid) {
+ private SnmpInfo(String host, String port, String oid, String trapOid) {
this.host = host;
this.port = port;
this.oid = oid;
+ this.trapOid = trapOid;
String error = null;
if (oid == null) {
@@ -29,17 +65,26 @@ public class SnmpInfo {
this.error = error;
}
+ /**
+ * Creates an instance of {@link SnmpInfo} from alert definition parameters.
+ *
+ * @param configuration SNMP notification parameters in a {@link Configuration} object
+ * @return instance of {@link SnmpInfo}
+ */
public static SnmpInfo load(Configuration configuration) {
- String host = configuration.getSimpleValue("host", null); // required
- String port = configuration.getSimpleValue("port", "162");
- String oid = configuration.getSimpleValue("oid", null); // required
-
- return new SnmpInfo(host, port, oid);
+ String host = configuration.getSimpleValue(PARAM_HOST, null); // required
+ String port = configuration.getSimpleValue(PARAM_PORT, DEFAULT_PORT);
+ String oid = configuration.getSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, null); // required
+ String trapOid = configuration.getSimpleValue(PARAM_TRAP_OID, null);
+ return new SnmpInfo(host, port, oid, trapOid);
}
+ @Override
public String toString() {
String hostString = (host == null ? "UnknownHost" : host);
String oidString = (oid == null ? "UnknownOID" : oid);
- return hostString + ":" + port + " (" + oidString + ")";
+ String trapOidString = (trapOid == null ? "DefaultTrapOID" : trapOid);
+ return hostString + ":" + port + " (" + oidString + ") (" + trapOidString + ")";
}
+
}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
index 1ea5e0b..5c6d1e7 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.plugins.alertSnmp;
@@ -38,7 +38,23 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
public class SnmpSender extends AlertSender {
- private final Log log = LogFactory.getLog(SnmpSender.class);
+ private static final Log LOG = LogFactory.getLog(SnmpSender.class);
+
+ private ResourceManagerLocal resourceManager;
+
+ private AlertManagerLocal alertManager;
+
+ /**
+ * Default constructor needed for instanciation by server plugin container
+ */
+ public SnmpSender() {
+ this(LookupUtil.getResourceManager(), LookupUtil.getAlertManager());
+ }
+
+ public SnmpSender(ResourceManagerLocal resourceManager, AlertManagerLocal alertManager) {
+ this.resourceManager = resourceManager;
+ this.alertManager = alertManager;
+ }
@Override
public SenderResult send(Alert alert) {
@@ -47,12 +63,11 @@ public class SnmpSender extends AlertSender {
if (info.error != null) {
return SenderResult.getSimpleFailure(info.error);
}
- log.debug("Sending SNMP trap to: " + info);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Sending SNMP trap to: " + info);
+ }
try {
- AlertManagerLocal alertManager = LookupUtil.getAlertManager();
- ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
-
SnmpTrapSender snmpTrapSender = new SnmpTrapSender(preferences);
List<Resource> lineage = resourceManager.getResourceLineage(alert.getAlertDefinition().getResource()
@@ -69,6 +84,7 @@ public class SnmpSender extends AlertSender {
alertUrl, hierarchy);
return SenderResult.getSimpleSuccess(result);
} catch (Throwable t) {
+ LOG.error("Could not send SNMP trap to " + info, t);
return SenderResult.getSimpleFailure("failed - cause: " + t);
}
}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
index 92fc838..2556b38 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2013 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.plugins.alertSnmp;
@@ -72,6 +72,7 @@ import org.snmp4j.util.PDUFactory;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.util.StringUtil;
/**
* @author Ian Springer
@@ -135,12 +136,13 @@ public class SnmpTrapSender implements PDUFactory {
}
private void checkTrapVariables(List<VariableBinding> vbs) {
-
+ // Only on SNMP v2c or v3 trap
if ((pduType == PDU.INFORM) || (pduType == PDU.TRAP)) {
+ // Insert sysUpTime OID if not already present
if ((vbs.size() == 0) || ((vbs.size() >= 1) && (!(vbs.get(0)).getOid().equals(SnmpConstants.sysUpTime)))) {
vbs.add(0, new VariableBinding(SnmpConstants.sysUpTime, sysUpTime));
}
-
+ // Insert trap OID if not already present
if ((vbs.size() == 1) || ((vbs.size() >= 2) && (!(vbs.get(1)).getOid().equals(SnmpConstants.snmpTrapOID)))) {
vbs.add(1, new VariableBinding(SnmpConstants.snmpTrapOID, trapOID));
}
@@ -469,27 +471,28 @@ public class SnmpTrapSender implements PDUFactory {
return "SNMP is not enabled.";
}
- String baseOid = alertParameters.getSimpleValue("oid",null);
+ String variableBindingPrefix = alertParameters.getSimpleValue(SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX, null);
// TODO add a request id and a timestamp
this.address = createAddress(alertParameters);
// bind the alert definitions name on the oid set in the alert
- getVariableBindings(baseOid + ".1" + "={s}" + alert.getAlertDefinition().getName());
+ getVariableBindings(variableBindingPrefix + ".1" + "={s}" + alert.getAlertDefinition().getName());
// the resource the alert was defined on
- getVariableBindings(baseOid + ".2" + "={s}" + alert.getAlertDefinition().getResource().getName());
+ getVariableBindings(variableBindingPrefix + ".2" + "={s}" + alert.getAlertDefinition().getResource().getName());
// the platform this resource is on
- getVariableBindings(baseOid + ".3" + "={s}" + platformName);
+ getVariableBindings(variableBindingPrefix + ".3" + "={s}" + platformName);
// the conditions of this alert
- getVariableBindings(baseOid + ".4" + "={s}" + conditions);
+ getVariableBindings(variableBindingPrefix + ".4" + "={s}" + conditions);
// severity of the alert
- getVariableBindings(baseOid + ".5" + "={s}" + alert.getAlertDefinition().getPriority().toString().toLowerCase());
+ getVariableBindings(variableBindingPrefix + ".5" + "={s}" + alert.getAlertDefinition().getPriority().toString().toLowerCase());
// url of the alert detail
- getVariableBindings(baseOid + ".6" + "={s}" + alertUrl);
+ getVariableBindings(variableBindingPrefix + ".6" + "={s}" + alertUrl);
// hierarchy of the resource on alert
- getVariableBindings(baseOid + ".7" + "={s}" + hierarchy);
+ getVariableBindings(variableBindingPrefix + ".7" + "={s}" + hierarchy);
setSysUpTimeFromBootTime(bootTime); // needs to be called before checkTrapVariables();
+ setTrapOIDFromAlertParameters(alertParameters); // needs to be called before checkTrapVariables();
checkTrapVariables(this.vbs);
try {
PDU response = send();
@@ -533,6 +536,13 @@ public class SnmpTrapSender implements PDUFactory {
}
+ private void setTrapOIDFromAlertParameters(Configuration alertParameters) {
+ String trapOid = alertParameters.getSimpleValue(SnmpInfo.PARAM_TRAP_OID, null);
+ if (StringUtil.isNotBlank(trapOid)) {
+ setTrapOID(new OID(trapOid));
+ }
+ }
+
private boolean init() {
String snmpVersion = systemConfig.getSimpleValue("snmpVersion",null);
@@ -795,4 +805,4 @@ public class SnmpTrapSender implements PDUFactory {
public void setPduType(int pduType) {
this.pduType = pduType;
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
index 32ec521..83a55e9 100644
--- a/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/modules/enterprise/server/plugins/alert-snmp/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<alert-plugin
+<a:alert-plugin
name="alert-snmp"
displayName="Alert:SNMP"
- xmlns="urn:xmlns:rhq-serverplugin.alert"
+ xmlns:a="urn:xmlns:rhq-serverplugin.alert"
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
package="org.rhq.enterprise.server.plugins.alertSnmp"
@@ -65,15 +65,33 @@
</serverplugin:plugin-configuration>
<!-- How does this sender show up in drop downs etc -->
- <short-name>SNMP Traps</short-name>
+ <a:short-name>SNMP Traps</a:short-name>
<!-- Class that does the actual sending -->
- <plugin-class>SnmpSender</plugin-class>
+ <a:plugin-class>SnmpSender</a:plugin-class>
- <alert-configuration>
+ <a:alert-configuration>
<c:simple-property name="host" type="string" required="true" description="Trap target host"/>
<c:simple-property name="port" type="integer" required="false" default="162" description="Trap target port"/>
- <c:simple-property name="oid" type="string" required="true" description="OID of the trap sent"/>
-
- </alert-configuration>
-</alert-plugin>
+ <c:simple-property name="oid" displayName="Variable bindings prefix" type="string" required="true">
+ <c:description>
+ <![CDATA[
+ <p>RHQ will send alert notification details as a list of variable bindings in the
+ SNMP trap PDU.</p>
+ <p><strong>Do not confuse this paramater with 'Trap Oid'.</strong></p>
+ ]]>
+ </c:description>
+ </c:simple-property>
+ <c:simple-property name="trapOid" required="false">
+ <c:description>
+ <![CDATA[
+ <p>If set, the value of this paramater will override the value of the Trap Oid parameter defined globally
+ in the server plugin configuration. The Trap OID is sent as the second variable binding in the SNMP trap
+ PDU.</p>
+ <p><strong>Only applicable to v2c and v3 traps.</strong></p>
+ <p><strong>Do not confuse this paramater with 'Variable bindings prefix'.</strong></p>
+ ]]>
+ </c:description>
+ </c:simple-property>
+ </a:alert-configuration>
+</a:alert-plugin>
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java
new file mode 100644
index 0000000..c46c8b6
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpInfoTest.java
@@ -0,0 +1,106 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.plugins.alertSnmp;
+
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.DEFAULT_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_HOST;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_TRAP_OID;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX;
+import static org.testng.Assert.*;
+
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.configuration.Configuration;
+
+/**
+ * @author Thomas Segismont
+ */
+public class SnmpInfoTest {
+
+ @Test
+ public void shouldDetectMissingParams() throws Exception {
+ Configuration configuration = new Configuration();
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: OID, host");
+
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: OID");
+
+ configuration.remove(PARAM_HOST);
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ snmpInfo = SnmpInfo.load(configuration);
+ assertNotNull(snmpInfo.error, "SnmpInfo#load should have detected an error");
+ assertEquals(snmpInfo.error, "Missing: host");
+ }
+
+ @Test
+ public void shouldAssumeDefaultValues() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNull(snmpInfo.error, "SnmpInfo#load should not have detected an error");
+ assertEquals(snmpInfo.host, "pipo");
+ assertEquals(snmpInfo.oid, "molo");
+ assertEquals(snmpInfo.port, SnmpInfo.DEFAULT_PORT);
+ }
+
+ @Test
+ public void shouldExposeAllParams() throws Exception {
+ Configuration configuration = new Configuration();
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ configuration.setSimpleValue(PARAM_PORT, "123");
+ configuration.setSimpleValue(PARAM_TRAP_OID, "logo");
+
+ SnmpInfo snmpInfo = SnmpInfo.load(configuration);
+ assertNull(snmpInfo.error, "SnmpInfo#load should not have detected an error");
+ assertEquals(snmpInfo.host, "pipo");
+ assertEquals(snmpInfo.port, "123");
+ assertEquals(snmpInfo.oid, "molo");
+ assertEquals(snmpInfo.trapOid, "logo");
+ }
+
+ @Test
+ public void testStringRepresentation() {
+ // We are not testing something really tricky here...
+ // But the String representation of an SnmpInfo instance is used in the UI as a description in the alert
+ // definition notification list. So this test is here to remind us in the future that the format of the
+ // String representation is constrained (even not strongly).
+ Configuration configuration = new Configuration();
+ assertEquals(SnmpInfo.load(configuration).toString(), "UnknownHost:" + DEFAULT_PORT
+ + " (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_HOST, "pipo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:" + DEFAULT_PORT + " (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_PORT, "35162");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (UnknownOID) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, "molo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (molo) (DefaultTrapOID)");
+ configuration.setSimpleValue(PARAM_TRAP_OID, "logo");
+ assertEquals(SnmpInfo.load(configuration).toString(), "pipo:35162 (molo) (logo)");
+ }
+
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java
new file mode 100644
index 0000000..38b36d7
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSenderTest.java
@@ -0,0 +1,378 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+package org.rhq.enterprise.server.plugins.alertSnmp;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+import static org.rhq.core.domain.alert.AlertPriority.HIGH;
+import static org.rhq.core.domain.alert.notification.ResultState.FAILURE;
+import static org.rhq.core.domain.alert.notification.ResultState.SUCCESS;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_HOST;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_PORT;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_TRAP_OID;
+import static org.rhq.enterprise.server.plugins.alertSnmp.SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX;
+import static org.testng.Assert.*;
+
+import java.util.Arrays;
+import java.util.ListIterator;
+import java.util.Vector;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.snmp4j.CommandResponder;
+import org.snmp4j.CommandResponderEvent;
+import org.snmp4j.PDU;
+import org.snmp4j.Snmp;
+import org.snmp4j.mp.SnmpConstants;
+import org.snmp4j.smi.Address;
+import org.snmp4j.smi.OID;
+import org.snmp4j.smi.OctetString;
+import org.snmp4j.smi.SMIConstants;
+import org.snmp4j.smi.UdpAddress;
+import org.snmp4j.smi.VariableBinding;
+import org.snmp4j.transport.DefaultUdpTransportMapping;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.core.domain.alert.AlertDefinition;
+import org.rhq.core.domain.alert.AlertPriority;
+import org.rhq.core.domain.alert.notification.SenderResult;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.util.StringUtil;
+import org.rhq.enterprise.server.alert.AlertManagerLocal;
+import org.rhq.enterprise.server.resource.ResourceManagerLocal;
+
+/**
+ * @author Thomas Segismont
+ */
+public class SnmpSenderTest {
+
+ private static final Log LOG = LogFactory.getLog(SnmpSenderTest.class);
+
+ private static final String TEST_TRAP_OID_PLUGIN_CONFIG = "1.3.6.1.4.1.18017";
+
+ private static final String TEST_TRAP_OID_ALERT_PARAM = "1.3.6.1.4.1.18018";
+
+ private static final String TEST_VARIABLE_BINDING_PREFIX = "1.3.6.1.4.1.18019";
+
+ private static final String TEST_HOST = "127.0.0.1";
+
+ private static final int TEST_PORT = 35162;
+
+ private static final String TEST_PORT_VARIABLE = "alert.snmp.test.port";
+
+ private ConcurrentLinkedQueue<PDU> receivedTraps;
+
+ private Snmp snmp;
+
+ @Mock
+ private ResourceManagerLocal resourceManager;
+
+ @Mock
+ private AlertManagerLocal alertManager;
+
+ private TestSnmpSender snmpSender;
+
+ @BeforeMethod
+ public void setUp() throws Exception {
+ receivedTraps = new ConcurrentLinkedQueue<PDU>();
+
+ snmp = new Snmp(new DefaultUdpTransportMapping());
+ Address targetAddress = new UdpAddress(getTestPort());
+ boolean installedTrapListener = snmp.addNotificationListener(targetAddress, new CommandResponder() {
+ @Override
+ public void processPdu(CommandResponderEvent event) {
+ receivedTraps.offer(event.getPDU());
+ }
+ });
+ if (!installedTrapListener) {
+ throw new RuntimeException("Could not install trap listener");
+ }
+
+ MockitoAnnotations.initMocks(this);
+
+ Configuration pluginConfiguration = new Configuration();
+ pluginConfiguration.setSimpleValue("snmpVersion", "2c");
+ pluginConfiguration.setSimpleValue("trapOid", TEST_TRAP_OID_PLUGIN_CONFIG);
+ pluginConfiguration.setSimpleValue("community", "public");
+ snmpSender = new TestSnmpSender(resourceManager, alertManager, pluginConfiguration);
+ }
+
+ private static int getTestPort() {
+ String testPortVariable = System.getProperty(TEST_PORT_VARIABLE);
+ if (StringUtil.isNotBlank(testPortVariable)) {
+ try {
+ int port = Integer.parseInt(testPortVariable);
+ LOG.info("Using port " + testPortVariable + " for SNMP traps");
+ return port;
+ } catch (NumberFormatException e) {
+ LOG.warn("Invalid port variable: " + testPortVariable);
+ }
+ }
+ LOG.info("Using default port " + TEST_PORT + " for SNMP traps");
+ return TEST_PORT;
+ }
+
+ @AfterMethod
+ public void tearDown() throws Exception {
+ if (snmp != null) {
+ snmp.close();
+ }
+ }
+
+ @Test
+ public void shouldReturnSimpleFailureForInvalidNotificationParameters() {
+ Configuration alertParameters = new Configuration();
+ snmpSender.setAlertParameters(alertParameters);
+
+ SenderResult result = snmpSender.send(createAlertForResourceWithId(13004, "", "", HIGH));
+
+ assertNotNull(result);
+ assertEquals(result.getState(), FAILURE);
+ assertEquals(result.getFailureMessages().size(), 1);
+ String expectedError = SnmpInfo.load(alertParameters).error;
+ assertNotNull(expectedError);
+ assertEquals(result.getFailureMessages().get(0), expectedError);
+ }
+
+ @Test
+ public void shouldReturnSimpleFailureWhenErrorOccurs() {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ snmpSender.setAlertParameters(alertParameters);
+
+ int resourceId = 13004;
+ Alert alert = createAlertForResourceWithId(resourceId, "", "", HIGH);
+ String exceptionMessage = "Test Error";
+ when(resourceManager.getResourceLineage(eq(resourceId))).thenThrow(new RuntimeException(exceptionMessage));
+
+ SenderResult result = snmpSender.send(alert);
+
+ assertNotNull(result);
+ assertEquals(result.getState(), FAILURE);
+ assertEquals(result.getFailureMessages().size(), 1);
+ String actualErrorMessage = result.getFailureMessages().get(0);
+ assertTrue(actualErrorMessage.endsWith(exceptionMessage), "Unexpected error message: " + actualErrorMessage);
+ }
+
+ @Test(timeOut = 1000 * 60)
+ public void testSendWithDefaultSnmpTrapOid() throws Exception {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ snmpSender.setAlertParameters(alertParameters);
+
+ testSendWithSnmpTrapOid(new OID(TEST_TRAP_OID_PLUGIN_CONFIG));
+ }
+
+ @Test(timeOut = 1000 * 60)
+ public void testSendWithSpecificSnmpTrapOid() throws Exception {
+ Configuration alertParameters = new Configuration();
+ alertParameters.setSimpleValue(PARAM_HOST, TEST_HOST);
+ alertParameters.setSimpleValue(PARAM_VARIABLE_BINDING_PREFIX, TEST_VARIABLE_BINDING_PREFIX);
+ alertParameters.setSimpleValue(PARAM_PORT, String.valueOf(getTestPort()));
+ alertParameters.setSimpleValue(PARAM_TRAP_OID, TEST_TRAP_OID_ALERT_PARAM);
+ snmpSender.setAlertParameters(alertParameters);
+
+ testSendWithSnmpTrapOid(new OID(TEST_TRAP_OID_ALERT_PARAM));
+ }
+
+ private void testSendWithSnmpTrapOid(OID snmpTrapOid) throws InterruptedException {
+ int resourceId = 13004;
+ String resourceName = "Resource " + resourceId;
+ String alertDefinitionName = "Alert Definition " + resourceId;
+ AlertPriority alertPriority = HIGH;
+ Alert alert = createAlertForResourceWithId(resourceId, resourceName, alertDefinitionName, alertPriority);
+ Resource platformResouce = new Resource();
+ String platformName = "Platform Resource " + resourceId;
+ platformResouce.setName(platformName);
+
+ when(resourceManager.getResourceLineage(eq(resourceId))).thenReturn(
+ Arrays.asList(platformResouce, alert.getAlertDefinition().getResource()));
+ String alertConditions = "Alert Conditions " + resourceId;
+ when(alertManager.prettyPrintAlertConditions(eq(alert), eq(false))).thenReturn(alertConditions);
+ String alertUrl = "https://www.rhq.com/alert/" + resourceId;
+ when(alertManager.prettyPrintAlertURL(eq(alert))).thenReturn(alertUrl);
+
+ assertNull(receivedTraps.peek(), "Something sent a trap before on our test port");
+
+ SenderResult result = snmpSender.send(alert);
+
+ assertEquals(result.getState(), SUCCESS, result.getFailureMessages().toString());
+ while (receivedTraps.peek() == null) {
+ Thread.sleep(1000);
+ }
+ PDU pdu = receivedTraps.poll();
+ assertNull(receivedTraps.peek(), "Only one trap should have been received");
+
+ assertExpectedPdu(pdu, new PduExpectedValues(snmpTrapOid, resourceName, alertDefinitionName, alertPriority,
+ platformName, alertConditions, alertUrl));
+ }
+
+ private void assertExpectedPdu(PDU pdu, PduExpectedValues expectedValues) {
+ Vector variableBindings = pdu.getVariableBindings();
+
+ assertTrue(variableBindings.size() == 9, "Variable bindings should contain 9 variable bindings and not "
+ + variableBindings.size() + ": " + variableBindings);
+
+ @SuppressWarnings("unchecked")
+ ListIterator<VariableBinding> variableBindingsIterator = variableBindings.listIterator();
+
+ VariableBinding variableBinding = variableBindingsIterator.next();
+ assertEquals(variableBinding.getOid(), SnmpConstants.sysUpTime);
+
+ variableBinding = variableBindingsIterator.next();
+ assertEquals(variableBinding.getOid(), SnmpConstants.snmpTrapOID);
+ assertEquals(variableBinding.getVariable(), expectedValues.getSnmpTrapOid());
+
+ OID oidPrefix = new OID(TEST_VARIABLE_BINDING_PREFIX);
+ while (variableBindingsIterator.hasNext()) {
+ variableBinding = variableBindingsIterator.next();
+
+ assertVariableBindingIsPrefixed(variableBinding, oidPrefix);
+ assertVariableBindingHasStringValue(variableBinding);
+
+ switch (variableBindingsIterator.previousIndex()) {
+ case 2:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertDefinitionName()));
+ break;
+ case 3:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getResourceName()));
+ break;
+ case 4:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getPlatformName()));
+ break;
+ case 5:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertConditions()));
+ break;
+ case 6:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertPriority()
+ .toString().toLowerCase()));
+ break;
+ case 7:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getAlertUrl()));
+ break;
+ case 8:
+ assertEquals(variableBinding.getVariable(), new OctetString(expectedValues.getPlatformName() + "::"
+ + expectedValues.getResourceName() + "::"));
+ break;
+ default:
+ throw new RuntimeException("Unexpected index: " + variableBindingsIterator.previousIndex());
+ }
+ }
+ }
+
+ private void assertVariableBindingHasStringValue(VariableBinding variableBinding) {
+ assertEquals(variableBinding.getVariable().getSyntax(), SMIConstants.SYNTAX_OCTET_STRING,
+ "Variable binding value [" + variableBinding.getVariable() + "] has wrong type");
+ }
+
+ private void assertVariableBindingIsPrefixed(VariableBinding variableBinding, OID oidPrefix) {
+ assertTrue(variableBinding.getOid().startsWith(oidPrefix), "Variable binding OID [" + variableBinding.getOid()
+ + "] has wrong prefix");
+ }
+
+ private Alert createAlertForResourceWithId(int resourceId, String resourceName, String alertDefinitionName,
+ AlertPriority alertPriority) {
+ Resource resource = new Resource();
+ resource.setId(resourceId);
+ resource.setName(resourceName);
+ AlertDefinition alertDefinition = new AlertDefinition();
+ alertDefinition.setName(alertDefinitionName);
+ alertDefinition.setResource(resource);
+ alertDefinition.setPriority(alertPriority);
+ Alert alert = new Alert();
+ alert.setAlertDefinition(alertDefinition);
+ return alert;
+ }
+
+ private static final class TestSnmpSender extends SnmpSender {
+
+ TestSnmpSender(ResourceManagerLocal resourceManager, AlertManagerLocal alertManager,
+ Configuration pluginConfiguration) {
+ super(resourceManager, alertManager);
+ this.preferences = pluginConfiguration;
+ }
+
+ void setAlertParameters(Configuration alertParameters) {
+ this.alertParameters = alertParameters;
+ }
+
+ }
+
+ private static final class PduExpectedValues {
+
+ private final OID snmpTrapOid;
+ private final String resourceName;
+ private final String alertDefinitionName;
+ private final AlertPriority alertPriority;
+ private final String platformName;
+ private final String alertConditions;
+ private final String alertUrl;
+
+ private PduExpectedValues(OID snmpTrapOid, String resourceName, String alertDefinitionName,
+ AlertPriority alertPriority, String platformName, String alertConditions, String alertUrl) {
+ this.snmpTrapOid = snmpTrapOid;
+ this.resourceName = resourceName;
+ this.alertDefinitionName = alertDefinitionName;
+ this.alertPriority = alertPriority;
+ this.platformName = platformName;
+ this.alertConditions = alertConditions;
+ this.alertUrl = alertUrl;
+ }
+
+ public OID getSnmpTrapOid() {
+ return snmpTrapOid;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ public String getAlertDefinitionName() {
+ return alertDefinitionName;
+ }
+
+ public AlertPriority getAlertPriority() {
+ return alertPriority;
+ }
+
+ public String getPlatformName() {
+ return platformName;
+ }
+
+ public String getAlertConditions() {
+ return alertConditions;
+ }
+
+ public String getAlertUrl() {
+ return alertUrl;
+ }
+ }
+}
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml b/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml
new file mode 100644
index 0000000..73b2ae5
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-snmp/src/test/resources/log4j.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<!-- | For more configuration information and examples, see the Jakarta Log4j | website: http://jakarta.apache.org/log4j -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="ERROR"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) - %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <param name="File" value="target/test.log"/>
+ <param name="Append" value="false"/>
+ <param name="Threshold" value="DEBUG"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L) - %m%n"/>
+ </layout>
+ </appender>
+
+ <root>
+ <level value="DEBUG"/>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit fabce7666b08f73ea113807ec42b47a3d3eb5929
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Apr 29 11:15:34 2013 -0400
BZ 957282 957288 add bundle target of "Install Directory"
diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
index 5a30ec3..45f4e05 100644
--- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml
@@ -1333,6 +1333,10 @@
</drift-definition>
<bundle-target>
+ <destination-base-dir name="Install Directory" description="The top directory where the application server is installed. (i.e. the value found in the 'Home Directory' connection property)">
+ <value-context>pluginConfiguration</value-context>
+ <value-name>homeDir</value-name>
+ </destination-base-dir>
<destination-base-dir name="Deploy Directory" description="The deployment directory for a standalone server">
<value-context>measurementTrait</value-context>
<value-name>deployDir</value-name>
commit 8ae20bd510aa660e94f70cad95fc680fd0dedd47
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Apr 26 14:41:02 2013 -0400
BZ 917085 - allow for relative and absolute raw file paths to include ".."
diff --git a/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java b/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
index e81fbaa..c55c1bc 100644
--- a/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
+++ b/modules/core/util/src/main/java/org/rhq/core/util/updater/DeploymentData.java
@@ -30,6 +30,7 @@ import java.util.Set;
import java.util.regex.Pattern;
import org.rhq.core.template.TemplateEngine;
+import org.rhq.core.util.file.FileUtil;
/**
* Data that describes a particular deployment. In effect, this provides the
@@ -114,7 +115,7 @@ public class DeploymentData {
this.deploymentProps = deploymentProps;
this.zipFiles = zipFiles;
this.rawFiles = rawFiles;
- this.destinationDir = destinationDir;
+ this.destinationDir = getCanonicalFile(destinationDir);
this.sourceDir = sourceDir;
this.ignoreRegex = ignoreRegex;
this.manageRootDir = manageRootDir;
@@ -131,6 +132,69 @@ public class DeploymentData {
this.templateEngine = templateEngine;
}
+ // We need to "normalize" all raw file paths that have ".." in them to ensure everything works properly.
+ // Any raw file pathname (the values in this.rawFiles) that needs to be normalized will be converted to
+ // a canonical path. Note that any pathname that is relative but have ".." paths that end up taking the file
+ // above the destination directory needs to be normalized and will end up being an absolute path
+ // (so all log messages will indicate the full absolute path and if the file
+ // needs to be backed up it will be backed up as if it was an external file that was specified with an absolute path).
+ // If the relative path has ".." but does not take the file above the destination directory will simply have its ".."
+ // normalized out but will still be a relative path (relative to destination directory) (we can't make it absolute
+ // otherwise Deployer's update will run into errors while backing up and scanning for deleted files).
+ // See BZ 917085.
+ for (Map.Entry<File, File> entry : this.rawFiles.entrySet()) {
+ File rawFile = entry.getValue();
+ String rawFilePath = rawFile.getPath();
+
+ boolean doubledot = rawFilePath.replace('\\', '/').matches(".*((/\\.\\.)|(\\.\\./)).*"); // finds "/.." or "../" in the string
+
+ if (doubledot) {
+ File fileToCanonicalize;
+
+ if (rawFile.isAbsolute()) {
+ fileToCanonicalize = rawFile;
+ } else {
+ boolean isWindows = (File.separatorChar == '\\');
+ if (isWindows) {
+ // of course, Windows has to make it enormously difficult to do this right...
+
+ // determine if the windows rawFile relative path specified a drive (e.g. C:foobar.txt)
+ StringBuilder rawFilePathBuilder = new StringBuilder(rawFilePath);
+ String rawFileDriveLetter = FileUtil.stripDriveLetter(rawFilePathBuilder); // rawFilePathBuilder now has drive letter stripped
+
+ // determine what, if any, drive letter is specified in the destination directory
+ StringBuilder destDirAbsPathBuilder = new StringBuilder(this.destinationDir.getAbsolutePath());
+ String destDirDriveLetter = FileUtil.stripDriveLetter(destDirAbsPathBuilder);
+
+ // figure out what the absolute, normalized path is for the raw file
+ if ((destDirDriveLetter == null || rawFileDriveLetter == null)
+ || rawFileDriveLetter.equals(destDirDriveLetter)) {
+ fileToCanonicalize = new File(this.destinationDir, rawFilePathBuilder.toString());
+ } else {
+ throw new IllegalArgumentException("Cannot normalize relative path [" + rawFilePath
+ + "]; its drive letter is different than the destination directory ["
+ + this.destinationDir.getAbsolutePath() + "]");
+ }
+ } else {
+ fileToCanonicalize = new File(this.destinationDir, rawFilePath);
+ }
+ }
+
+ fileToCanonicalize = getCanonicalFile(fileToCanonicalize);
+
+ if (isPathUnderBaseDir(this.destinationDir, fileToCanonicalize)) {
+ // we can keep rawFile path relative, but we need to normalize out the ".." paths
+ String baseDir = this.destinationDir.getAbsolutePath();
+ String absRawFilePath = fileToCanonicalize.getAbsolutePath();
+ String canonicalRelativePath = absRawFilePath.substring(baseDir.length() + 1); // should always return a valid path; if not, let it throw exception (which likely means there is a bug here)
+ entry.setValue(new File(canonicalRelativePath));
+ } else {
+ // raw file path has ".." such that the file is really above destination dir - use an absolute, canonical path
+ entry.setValue(fileToCanonicalize);
+ }
+ }
+ }
+
return;
}
@@ -177,4 +241,30 @@ public class DeploymentData {
public Map<File, Boolean> getZipsExploded() {
return zipsExploded;
}
+
+ private File getCanonicalFile(File file) {
+ try {
+ file = file.getCanonicalFile();
+ } catch (Exception e) {
+ // ignore this - this really should never happen, but if it does,
+ // we want to continue and hope using the non-normalized file is ok;
+ file = file.getAbsoluteFile();
+ }
+ return file;
+ }
+
+ private boolean isPathUnderBaseDir(File base, File path) {
+ // this method assumes base and path are absolute and canonical
+ if (base == null) {
+ return false;
+ }
+
+ while (path != null) {
+ if (base.equals(path)) {
+ return true;
+ }
+ path = path.getParentFile();
+ }
+ return false;
+ }
}
diff --git a/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java b/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java
new file mode 100644
index 0000000..7a62bf0
--- /dev/null
+++ b/modules/core/util/src/test/java/org/rhq/core/util/updater/DeployerCanonicalPathTest.java
@@ -0,0 +1,275 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2013 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.core.util.updater;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.template.TemplateEngine;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.core.util.stream.StreamUtil;
+
+/**
+ * Tests deploying raw files to deployment locations specified with ".." in the path.
+ * This will require the deployer code to transform the paths to canonical paths.
+ *
+ * @author John Mazzitelli
+ */
+@Test
+public class DeployerCanonicalPathTest {
+ private TemplateEngine templateEngine;
+
+ @BeforeClass
+ public void beforeClass() {
+ Map<String, String> tokens = new HashMap<String, String>();
+ tokens.put("rhq.system.hostname", "localhost");
+ tokens.put("rhq.system.sysprop.java.version", System.getProperty("java.version"));
+
+ templateEngine = new TemplateEngine(tokens);
+ }
+
+ @BeforeMethod
+ public void beforeMethod() {
+ System.out.println("\n\n=============== START OF NEW TEST ===============\n");
+ }
+
+ // any raw file path (absolute or relative) that contains ".." will be converted to an absolute, canonical path - this is what we test
+ public void testInitialDeployRawFilesWithCanonicalPaths() throws Exception {
+ File tmpDirDest = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".dest", null);
+ File tmpDirSrc = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".src", null);
+ File rawFileRelativeDest = new File("dir-does-not-existA/../rawA.txt"); // relative to "tmpDirDest" that we just created above
+ File rawFileRelativeDest2 = new File("dir-does-not-existA/../../rawA.txt"); // relative to "tmpDirDest" but it takes us above it
+ File rawFileAbsoluteDest = new File(System.getProperty("java.io.tmpdir"), "dir-does-not-existB/../rawB.txt");
+
+ try {
+ // put some source files in our tmpDirSrc location
+ File testRawFileA = new File(tmpDirSrc, "updater-testA.txt");
+ File testRawFileA2 = new File(tmpDirSrc, "updater-testA2.txt");
+ File testRawFileB = new File(tmpDirSrc, "updater-testB.txt");
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA);
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA2);
+ FileUtil.copyFile(new File("target/test-classes/updater-testB.txt"), testRawFileB);
+
+ DeploymentProperties deploymentProps = new DeploymentProperties(0, "testbundle", "1.0.test", null);
+ Set<File> zipFiles = null;
+ Map<File, File> rawFiles = new HashMap<File, File>(3);
+ rawFiles.put(testRawFileA, rawFileRelativeDest); // we will realize this one ...
+ rawFiles.put(testRawFileA2, rawFileRelativeDest2); // and this one ...
+ rawFiles.put(testRawFileB, rawFileAbsoluteDest); // and we will realize this one, too
+ File destDir = tmpDirDest;
+ Pattern ignoreRegex = null;
+ Set<File> realizeRawFiles = new HashSet<File>(3);
+ realizeRawFiles.add(testRawFileA);
+ realizeRawFiles.add(testRawFileA2);
+ realizeRawFiles.add(testRawFileB);
+ DeploymentData dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null,
+ realizeRawFiles, templateEngine, ignoreRegex, true, null);
+ Deployer deployer = new Deployer(dd);
+ DeployDifferences diff = new DeployDifferences();
+ FileHashcodeMap map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+
+ String rawFileRelativeDestCanonical = new File(tmpDirDest, rawFileRelativeDest.getPath()).getCanonicalPath();
+ String rawFileRelativeDestCanonical2 = new File(tmpDirDest, rawFileRelativeDest2.getPath())
+ .getCanonicalPath();
+ String rawFileAbsoluteDestCanonical = rawFileAbsoluteDest.getCanonicalPath();
+
+ assert map.size() == 3 : map;
+
+ assert map.containsKey("rawA.txt") : map;
+ assert new File(rawFileRelativeDestCanonical).exists();
+ assert new File(rawFileRelativeDestCanonical2).exists();
+ assert MessageDigestGenerator.getDigestString(new File(rawFileRelativeDestCanonical)).equals(
+ map.get("rawA.txt"));
+
+ // rawFileRelativeDestCanonical2 should be treated just like an absolute, external file
+ assert MessageDigestGenerator.getDigestString(new File(rawFileRelativeDestCanonical2)).equals(
+ map.get(rawFileRelativeDestCanonical2));
+ assert !MessageDigestGenerator.getDigestString(testRawFileA).equals(map.get("rawA.txt")) : "should have different hash, we realize this one!";
+
+ assert map.containsKey(rawFileAbsoluteDestCanonical) : map;
+ assert new File(rawFileAbsoluteDestCanonical).exists();
+ assert MessageDigestGenerator.getDigestString(new File(rawFileAbsoluteDestCanonical)).equals(
+ map.get(rawFileAbsoluteDestCanonical));
+ assert !MessageDigestGenerator.getDigestString(testRawFileB).equals(map.get(rawFileAbsoluteDestCanonical)) : "should have different hash, we realized this one";
+
+ assert diff.getAddedFiles().size() == 3 : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getAddedFiles().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ assert diff.getRealizedFiles().size() == 3 : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getRealizedFiles().keySet().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ } finally {
+ FileUtil.purge(tmpDirDest, true);
+ FileUtil.purge(tmpDirSrc, true);
+ rawFileAbsoluteDest.getCanonicalFile().delete();
+ }
+ }
+
+ public void testUpdateDeployRawFileWithRelativePath() throws Exception {
+ File tmpDirDest = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".dest", null);
+ File tmpDirSrc = FileUtil.createTempDirectory("DeployerCanonicalPathTest", ".src", null);
+ File rawFileRelativeDest = new File("dir-does-not-existA/../rawA.txt"); // relative to "tmpDirDest" that we just created above
+ File rawFileRelativeDest2 = new File("dir-does-not-existA/../../rawA.txt"); // relative to "tmpDirDest" but it takes us above it
+ File rawFileAbsoluteDest = new File(System.getProperty("java.io.tmpdir"), "dir-does-not-existB/../rawB.txt");
+
+ try {
+ // put some source files in our tmpDirSrc location
+ File testRawFileA = new File(tmpDirSrc, "updater-testA.txt");
+ File testRawFileA2 = new File(tmpDirSrc, "updater-testA2.txt");
+ File testRawFileB = new File(tmpDirSrc, "updater-testB.txt");
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA);
+ FileUtil.copyFile(new File("target/test-classes/updater-testA.txt"), testRawFileA2);
+ FileUtil.copyFile(new File("target/test-classes/updater-testB.txt"), testRawFileB);
+
+ DeploymentProperties deploymentProps = new DeploymentProperties(0, "testbundle", "1.0.test", null);
+ Set<File> zipFiles = null;
+ Map<File, File> rawFiles = new HashMap<File, File>(3);
+ rawFiles.put(testRawFileA, rawFileRelativeDest);
+ rawFiles.put(testRawFileA2, rawFileRelativeDest2);
+ rawFiles.put(testRawFileB, rawFileAbsoluteDest);
+ File destDir = tmpDirDest;
+ Pattern ignoreRegex = null;
+ DeploymentData dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null, null,
+ templateEngine, ignoreRegex, true, null);
+ Deployer deployer = new Deployer(dd);
+ DeployDifferences diff = new DeployDifferences();
+ FileHashcodeMap map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+ assert map.size() == 3 : map;
+
+ // make sure the first raw file is in the dest dir
+ String f = rawFileRelativeDest.getPath();
+ File destFile = new File(tmpDirDest, f).getCanonicalFile(); // notice f is assumed relative to tmpDirDest, must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedR".getBytes()), destFile); // change the file so we back it up during update
+
+ // make sure the second raw file, though specified originally as a relative file, is in the external location
+ f = rawFileRelativeDest2.getPath();
+ destFile = new File(tmpDirDest, f).getCanonicalFile(); // must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedR2".getBytes()), destFile); // change the file so we back it up during update
+
+ // make sure the third raw file is in the external location
+ destFile = rawFileAbsoluteDest.getCanonicalFile(); // must convert to canonical path
+ assert destFile.exists() : destFile;
+ FileUtil.writeFile(new ByteArrayInputStream("modifiedA".getBytes()), destFile); // change the file so we back it up during update
+
+ // UPDATE
+ // alter the src files so we backup our changed files
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedR".getBytes()), testRawFileA);
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedR2".getBytes()), testRawFileA2);
+ FileUtil.writeFile(new ByteArrayInputStream("src.modifiedA".getBytes()), testRawFileB);
+
+ deploymentProps = new DeploymentProperties(1, "testbundle", "2.0.test", null);
+ dd = new DeploymentData(deploymentProps, zipFiles, rawFiles, tmpDirSrc, destDir, null, null,
+ templateEngine, ignoreRegex, true, null);
+ deployer = new Deployer(dd);
+ diff = new DeployDifferences();
+ map = deployer.deploy(diff);
+ System.out.println("map-->\n" + map);
+ System.out.println("diff->\n" + diff);
+
+ String rawFileRelativeDestCanonical = new File(tmpDirDest, rawFileRelativeDest.getPath())
+ .getCanonicalPath();
+ String rawFileRelativeDestCanonical2 = new File(tmpDirDest, rawFileRelativeDest2.getPath())
+ .getCanonicalPath();
+ String rawFileAbsoluteDestCanonical = rawFileAbsoluteDest.getCanonicalPath();
+
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileRelativeDestCanonical))))
+ .equals("src.modifiedR");
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileRelativeDestCanonical2))))
+ .equals("src.modifiedR2");
+ assert new String(StreamUtil.slurp(new FileInputStream(new File(rawFileAbsoluteDestCanonical))))
+ .equals("src.modifiedA");
+
+ boolean isWindows = File.separatorChar == '\\';
+ final File metadir = new File(tmpDirDest, ".rhqdeployments");
+ File backupRel = new File(metadir, "1/backup/rawA.txt");
+ File backupRel2;
+ // test the second raw file, the one that was specified originally as a relative file but took us out of the dest dir
+ if (!isWindows) {
+ backupRel2 = new File(metadir, "1/ext-backup/" + rawFileRelativeDestCanonical2);
+ } else {
+ StringBuilder str = new StringBuilder(rawFileRelativeDestCanonical2);
+ String driveLetter = FileUtil.stripDriveLetter(str);
+ if (driveLetter != null) {
+ driveLetter = "_" + driveLetter + '/';
+ } else {
+ driveLetter = "";
+ }
+ backupRel2 = new File(metadir, "1/ext-backup/" + driveLetter + str.toString());
+ }
+ // test the third raw file, the one that was specified originally as an absolute, external file
+ File backupAbs;
+ if (!isWindows) {
+ backupAbs = new File(metadir, "1/ext-backup/" + rawFileAbsoluteDestCanonical);
+ } else {
+ StringBuilder str = new StringBuilder(rawFileAbsoluteDestCanonical);
+ String driveLetter = FileUtil.stripDriveLetter(str);
+ if (driveLetter != null) {
+ driveLetter = "_" + driveLetter + '/';
+ } else {
+ driveLetter = "";
+ }
+ backupAbs = new File(metadir, "1/ext-backup/" + driveLetter + str.toString());
+ }
+
+ // the backup files should exist
+ assert backupRel.exists() : backupRel;
+ assert backupRel2.exists() : backupRel2;
+ assert backupAbs.exists() : backupAbs;
+
+ assert map.size() == 3 : map;
+ assert diff.getChangedFiles().size() == 3 : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getChangedFiles().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ assert diff.getDeletedFiles().isEmpty() : diff;
+ assert diff.getBackedUpFiles().size() == 3 : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath("rawA.txt")) : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath(rawFileRelativeDestCanonical2)) : diff;
+ assert diff.getBackedUpFiles().keySet().contains(diff.convertPath(rawFileAbsoluteDestCanonical)) : diff;
+ } finally {
+ FileUtil.purge(tmpDirDest, true);
+ FileUtil.purge(tmpDirSrc, true);
+ rawFileAbsoluteDest.getCanonicalFile().delete();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
index daf5463..f0605a2 100644
--- a/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
+++ b/modules/plugins/ant-bundle/src/test/java/org/rhq/plugins/ant/AntBundlePluginComponentTest.java
@@ -26,10 +26,12 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
@@ -70,20 +72,25 @@ import org.rhq.core.util.updater.DeploymentsMetadata;
@Test
public class AntBundlePluginComponentTest {
+ private static final boolean ENABLE_TESTS = true;
+
private static final String DEST_BASE_DIR_NAME = "Root File System"; // just mimics the real platform plugin types' name
private AntBundlePluginComponent plugin;
+ private File testFilesBaseDir; // under here will go all our test files: tmpDir, bundleFilesDir and destDir
private File tmpDir;
private File bundleFilesDir;
private File destDir;
@BeforeClass
public void initDirs() throws Exception {
- this.tmpDir = new File("target/antbundletest/tmp");
+ this.testFilesBaseDir = new File("target/antbundletest");
+
+ this.tmpDir = new File(this.testFilesBaseDir, "tmp");
FileUtil.purge(this.tmpDir, true);
- this.bundleFilesDir = new File("target/antbundletest/bundlefiles");
+ this.bundleFilesDir = new File(this.testFilesBaseDir, "bundlefiles");
FileUtil.purge(this.bundleFilesDir, true);
- this.destDir = new File("target/antbundletest/destination");
+ this.destDir = new File(this.testFilesBaseDir, "destination");
FileUtil.purge(this.destDir, true);
}
@@ -117,7 +124,7 @@ public class AntBundlePluginComponentTest {
FileUtil.purge(this.destDir, true);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleRevert() throws Exception {
// install then upgrade a bundle first
testAntBundleUpgrade();
@@ -227,17 +234,17 @@ public class AntBundlePluginComponentTest {
assert previousProps.getBundleVersion().equals("3.0"); // testAntBundleUpgrade deployed version 3.0
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleUpgrade() throws Exception {
upgrade(false);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleCleanUpgrade() throws Exception {
upgrade(true);
}
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleInitialInstall() throws Exception {
doAntBundleInitialInstall(true);
}
@@ -348,7 +355,7 @@ public class AntBundlePluginComponentTest {
/**
* Test deployment of an RHQ bundle recipe.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundle() throws Exception {
ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
@@ -412,9 +419,149 @@ public class AntBundlePluginComponentTest {
}
/**
+ * Test raw files whose destination locations have ".." in their paths.
+ */
+ @Test(enabled = ENABLE_TESTS)
+ public void testRawFilesWithDotDotPaths() throws Exception {
+ // our test bundle's relative raw file paths that resolve above dest dir will resolve to here
+ final File externalDir = new File(this.testFilesBaseDir, "ext");
+
+ ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
+ BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
+ Repo repo = new Repo("testSimpleBundle");
+ PackageType packageType = new PackageType("testSimpleBundle", resourceType);
+ Bundle bundle = new Bundle("testSimpleBundle", bundleType, repo, packageType);
+ BundleVersion bundleVersion = new BundleVersion("testSimpleBundle", "1.0", bundle,
+ getRecipeFromFile("test-bundle-dotdot.xml"));
+ BundleDestination destination = new BundleDestination(bundle, "testSimpleBundle", new ResourceGroup(
+ "testSimpleBundle"), DEST_BASE_DIR_NAME, this.destDir.getAbsolutePath());
+ Configuration config = new Configuration();
+
+ BundleDeployment deployment = new BundleDeployment();
+ deployment.setId(0);
+ deployment.setName("test bundle deployment name");
+ deployment.setBundleVersion(bundleVersion);
+ deployment.setConfiguration(config);
+ deployment.setDestination(destination);
+
+ // create test files (see bundle recipe for why these files are created)
+ final String TEST1 = "test1.txt";
+ File file1 = new File(this.bundleFilesDir, TEST1);
+ writeFile(TEST1, file1);
+
+ final String TEST2 = "test2.txt";
+ File file2 = new File(this.bundleFilesDir, TEST2);
+ writeFile(TEST2, file2);
+
+ final String TEST3 = "test3.txt";
+ File file3 = new File(this.bundleFilesDir, TEST3);
+ writeFile(TEST3, file3);
+
+ final String TEST4 = "test4.txt";
+ File file4 = new File(this.bundleFilesDir, TEST4);
+ writeFile(TEST4, file4);
+
+ // ----- initial deployment -----
+ BundleDeployRequest request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ BundleDeployResult results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // test that the files were put where we expected them to be
+ File file1Dest = new File(this.destDir, "subdir/" + TEST1);
+ File file2Dest = new File(this.destDir, TEST2);
+ File file3Dest = new File(externalDir, TEST3);
+ File file4Dest = new File(externalDir, TEST4);
+ assert TEST1.equals(readFile(file1Dest)); // inside dest dir
+ assert TEST2.equals(readFile(file2Dest)); // inside dest dir
+ assert TEST3.equals(readFile(file3Dest)); // outside dest dir
+ assert TEST4.equals(readFile(file4Dest)); // outside dest dir
+
+ // ----- prepare to update the bundle ----
+ cleanPluginDirs(); // clean everything but the dest dir - we want to keep the metadata (this should not purge ext/ dir)
+ prepareBeforeTestMethod(); // prepare for our new test
+ // our src files will have different content for this bundle deployment compared to the initial deployment
+ writeFile(TEST1 + "update", file1);
+ writeFile(TEST2 + "update", file2);
+ writeFile(TEST3 + "update", file3);
+ writeFile(TEST4 + "update", file4);
+ // change our initial deployment files, RHQ should see the changes and back these files up
+ writeFile(TEST1 + "modified", file1Dest);
+ writeFile(TEST2 + "modified", file2Dest);
+ writeFile(TEST3 + "modified", file3Dest);
+ writeFile(TEST4 + "modified", file4Dest);
+
+ // ----- update deployment -----
+ deployment.setId(1);
+ request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // test that all files were updated
+ assert (TEST1 + "update").equals(readFile(file1Dest)); // inside dest dir
+ assert (TEST2 + "update").equals(readFile(file2Dest)); // inside dest dir
+ assert (TEST3 + "update").equals(readFile(file3Dest)); // outside dest dir
+ assert (TEST4 + "update").equals(readFile(file4Dest)); // outside dest dir
+
+ // test that our changed files that were under dest dir were properly backed up
+ DeploymentsMetadata metadata = new DeploymentsMetadata(this.destDir);
+ File backupDir = metadata.getDeploymentBackupDirectory(deployment.getId());
+ File file1Backup = new File(backupDir, "subdir/" + TEST1);
+ File file2Backup = new File(backupDir, TEST2);
+ assert file1Backup.isFile() : "should have been backed up: " + file1Backup;
+ assert file2Backup.isFile() : "should have been backed up: " + file2Backup;
+ assert (TEST1 + "modified").equals(readFile(file1Backup)) : "bad backup file: " + file1Backup;
+ assert (TEST2 + "modified").equals(readFile(file2Backup)) : "bad backup file: " + file2Backup;
+
+ // test that our changed files that were above dest dir were properly backed up
+ Map<String, File> winDirs = metadata.getDeploymentExternalBackupDirectoriesForWindows(deployment.getId());
+ if (winDirs == null) {
+ // we are running on non-windows platform
+ backupDir = metadata.getDeploymentExternalBackupDirectory(deployment.getId());
+ } else {
+ // we are on windows, our test only uses a single drive root, so we can grab the only item in the map
+ assert winDirs.size() == 1 : "should only have 1 ext backup dir on windows: " + winDirs;
+ backupDir = winDirs.values().iterator().next().getAbsoluteFile();
+ }
+ File file3Backup = new File(backupDir, file3Dest.getAbsolutePath());
+ File file4Backup = new File(backupDir, file4Dest.getAbsolutePath());
+ assert file3Backup.isFile() : "should have been backed up: " + file3Backup;
+ assert file4Backup.isFile() : "should have been backed up: " + file4Backup;
+ assert (TEST3 + "modified").equals(readFile(file3Backup)) : "bad backup file: " + file3Backup;
+ assert (TEST4 + "modified").equals(readFile(file4Backup)) : "bad backup file: " + file4Backup;
+
+ // ----- revert to last deployment, restoring backed up files
+ deployment.setId(2);
+ request = new BundleDeployRequest();
+ request.setBundleFilesLocation(this.bundleFilesDir);
+ request.setResourceDeployment(createNewBundleDeployment(deployment));
+ request.setBundleManagerProvider(new MockBundleManagerProvider());
+ request.setAbsoluteDestinationDirectory(this.destDir);
+ request.setRevert(true);
+ results = plugin.deployBundle(request);
+ assertResultsSuccess(results);
+
+ // make sure our files were reverted, giving us back the files that were backed up
+ assert readFile(file1Backup).equals(readFile(file1Dest)); // inside dest dir
+ assert readFile(file2Backup).equals(readFile(file2Dest)); // inside dest dir
+ assert readFile(file3Backup).equals(readFile(file3Dest)); // outside dest dir
+ assert readFile(file4Backup).equals(readFile(file4Dest)); // outside dest dir
+
+ // ----- clean up our test -----
+ FileUtil.purge(externalDir, true);
+ }
+
+ /**
* Test realizing of replacement tokens of resource tags.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testTags() throws Exception {
ResourceType resourceType = new ResourceType("testSimpleBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testSimpleBundle", resourceType);
@@ -484,7 +631,7 @@ public class AntBundlePluginComponentTest {
/**
* Test deployment of an RHQ bundle recipe where the deploy directory is not to be fully managed.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleNoManageRootDir() throws Exception {
ResourceType resourceType = new ResourceType("testNoManageRootDirBundle", "plugin", ResourceCategory.SERVER,
null);
@@ -618,7 +765,7 @@ public class AntBundlePluginComponentTest {
* Test deployment of an RHQ bundle recipe where the deploy directory is to be fully managed.
* This is the typical use-case and the default behavior.
*/
- @Test(enabled = true)
+ @Test(enabled = ENABLE_TESTS)
public void testAntBundleManageRootDir() throws Exception {
ResourceType resourceType = new ResourceType("testManageRootDirBundle", "plugin", ResourceCategory.SERVER, null);
BundleType bundleType = new BundleType("testManageRootDirBundle", resourceType);
@@ -878,6 +1025,10 @@ public class AntBundlePluginComponentTest {
return new String(StreamUtil.slurp(new FileInputStream(file)));
}
+ private void writeFile(final String content, final File file) throws IOException {
+ FileUtil.writeFile(new ByteArrayInputStream(content.getBytes()), file);
+ }
+
private void loadProperties(Properties realizedProps, FileInputStream fileInputStream) throws Exception {
try {
realizedProps.load(fileInputStream);
diff --git a/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml b/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml
new file mode 100644
index 0000000..f96b241
--- /dev/null
+++ b/modules/plugins/ant-bundle/src/test/resources/test-bundle-dotdot.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<project name="bundle-dotdot" default="main" xmlns:rhq="antlib:org.rhq.bundle">
+
+ <rhq:bundle name="bundle-dotdot" version="1.0"
+ description="testing raw files with .. in their destination paths">
+
+ <rhq:deployment-unit name="bundle">
+ <rhq:file name="test1.txt" destinationFile="nothere/../phantom/../subdir/test1.txt" /> <!-- still under dest dir -->
+ <rhq:file name="test2.txt" destinationDir="nothere/../" /> <!-- still under dest dir -->
+ <rhq:file name="test3.txt" destinationFile="../ext/test3.txt" /> <!-- external location outside dest dir-->
+ <rhq:file name="test4.txt" destinationDir="../ext" /> <!-- external location outside dest dir-->
+ </rhq:deployment-unit>
+
+ </rhq:bundle>
+
+ <target name="main"/>
+
+</project>
\ No newline at end of file
commit 06da5f05ae6b970dd16db61226626c45530655f5
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Apr 26 10:39:32 2013 +0200
Don't test the TagManager if it is not enabled.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
index 0195603..aa0ebd4 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/client/security/test/ScriptingAPIServerTest.java
@@ -88,6 +88,10 @@ public class ScriptingAPIServerTest extends ScriptableAbstractEJB3Test {
for (RhqManager m : RhqManager.values()) {
String name = m.name();
+ // Only check for the TagManager if it is enabled at all
+ if (name.contains("TagManager") && !RhqManager.TagManager.enabled()) {
+ continue;
+ }
Object scriptedManager = engine.eval(name);
assertNotNull(scriptedManager);
commit 24ca08b47b9c9b9f23b5c993ec1f04b158c9be43
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Fri Apr 26 10:17:45 2013 +0200
Get the jndi-access test to work with JBoss EAP 6.1alpha1
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
index 03dfcc9..f83573d 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/pom.xml
@@ -15,7 +15,7 @@
<properties>
<jboss.zip>${settings.localRepository}/org/jboss/as/jboss-as-dist/${jboss.version}/jboss-as-dist-${jboss.version}.zip</jboss.zip>
- <jboss.unzip.location>${basedir}/target/jboss-as-${jboss.version}</jboss.unzip.location>
+ <jboss.unzip.location>${basedir}/target/${jboss.eap.version}</jboss.unzip.location>
<jnp.port>54987</jnp.port>
<jnp.rmiPort>54988</jnp.rmiPort>
</properties>
@@ -26,21 +26,21 @@
<artifactId>log4j</artifactId>
<scope>runtime</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-dist</artifactId>
<type>zip</type>
<scope>provided</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-ejb3</artifactId>
<version>${jboss.version}</version>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-scripting-api</artifactId>
@@ -54,7 +54,7 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-scripting-python</artifactId>
@@ -69,7 +69,7 @@
<scope>test</scope>
</dependency>
- <!-- We need to pull some classes from the server jar and itests-2 - namely the naming hack to be able to test
+ <!-- We need to pull some classes from the server jar and itests-2 - namely the naming hack to be able to test
that it actually works -->
<dependency>
<groupId>org.rhq</groupId>
@@ -84,20 +84,20 @@
<artifactId>arquillian-testng-container</artifactId>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<scope>provided</scope>
</dependency>
-
+
<dependency>
<groupId>org.jboss.shrinkwrap.resolver</groupId>
<artifactId>shrinkwrap-resolver-depchain</artifactId>
<type>pom</type>
<scope>test</scope>
</dependency>
-
+
<!-- We'll try remote connections using JNP -->
<dependency>
<groupId>jboss</groupId>
@@ -105,7 +105,7 @@
<version>4.2.2.GA</version>
<scope>test</scope>
</dependency>
-
+
<!-- This is here only to ensure the build order and HAS TO COME AS LAST to avoid any classpath
collisions. -->
<dependency>
@@ -148,6 +148,12 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.jboss.xnio</groupId>
+ <artifactId>xnio-api</artifactId>
+ <version>${xnio.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</profile>
@@ -158,13 +164,13 @@
<name>!remote-test-server</name>
</property>
</activation>
-
+
<dependencies>
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-managed</artifactId>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
</profile>
@@ -175,7 +181,7 @@
<name>remote-test-server</name>
</property>
</activation>
-
+
<dependencies>
<dependency>
<groupId>org.jboss.spec</groupId>
@@ -187,13 +193,12 @@
<dependency>
<groupId>org.jboss.as</groupId>
<artifactId>jboss-as-arquillian-container-remote</artifactId>
- <version>${jboss.version}</version>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
</profile>
</profiles>
-
+
<build>
<testResources>
<testResource>
@@ -211,8 +216,8 @@
<phase>process-test-resources</phase>
<configuration>
<target>
- <unzip src="${jboss.zip}" dest="${jboss.unzip.location}/.." />
- <copy file="src/test/resources/security.policy" toDir="${jboss.unzip.location}"/>
+ <unzip src="${jboss.zip}" dest="${jboss.unzip.location}/.." />
+ <copy file="src/test/resources/security.policy" toDir="${jboss.unzip.location}"/>
</target>
</configuration>
<goals>
@@ -221,10 +226,10 @@
</execution>
</executions>
</plugin>
-
+
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
- <!-- Everything but the web service tests, this is the standard
+ <!-- Everything but the web service tests, this is the standard
test execution -->
<configuration>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
@@ -237,7 +242,7 @@
</systemPropertyVariables>
<argLine>${jacoco.unit-test.args} -Djava.security.manager -Djava.security.policy==${basedir}/target/test-classes/security.policy</argLine>
<additionalClasspathElements>
- <!-- The below is required for tests to run against
+ <!-- The below is required for tests to run against
Oracle. -->
<additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc6/${ojdbc6.version}/ojdbc6-${ojdbc6.version}.jar</additionalClasspathElement>
</additionalClasspathElements>
diff --git a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
index 8bee491..1783f59 100644
--- a/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
+++ b/modules/integration-tests/jndi-access/jndi-access-test/src/test/resources/arquillian.xml
@@ -1,7 +1,7 @@
<arquillian xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
-
+
<defaultProtocol type="Servlet 3.0" />
<container qualifier="as7" default="true">
<configuration>
diff --git a/pom.xml b/pom.xml
index d6489ef..da1506f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -153,6 +153,7 @@
<arquillian.version>1.0.3.Final</arquillian.version>
<arquillian.jboss.container.version>7.2.0.Final</arquillian.jboss.container.version>
<shrinkwrap-resolver.version>2.0.0-alpha-7</shrinkwrap-resolver.version>
+ <xnio.version>3.0.7.GA</xnio.version> <!-- needed in jndi-access tests to talk to the managed AS -->
<xercesImpl.version>2.9.1-jbossas-2</xercesImpl.version> <!-- see BZ-820629 and CVE-2009-2625 -->
<opencsv.version>1.8</opencsv.version>
<commons-httpclient.version>3.0.1</commons-httpclient.version>
@@ -725,6 +726,12 @@
</dependency>
<dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-arquillian-container-remote</artifactId>
+ <version>${arquillian.jboss.container.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<version>${jacoco.version}</version>
commit 2f656dc37a45c5ccdb14dbb173f55dec830acb88
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 12:20:55 2013 -0400
add API to get the data directory for the app server
diff --git a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
index 5078d08..9a766f4 100644
--- a/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
+++ b/modules/common/jboss-as-dmr-client/src/main/java/org/rhq/common/jbossas/client/controller/CoreJBossASClient.java
@@ -126,6 +126,12 @@ public class CoreJBossASClient extends JBossASClient {
return dir;
}
+ public String getAppServerDataDir() throws Exception {
+ final String[] address = { CORE_SERVICE, SERVER_ENVIRONMENT };
+ final String dir = getStringAttribute(true, "data-dir", Address.root().add(address));
+ return dir;
+ }
+
/**
* Enabled or disables the default deployment scanner.
* @param enabled the new status to be set
commit 06071e1f7f1562e86c364e0a03835a39fb241b22
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 10:40:10 2013 -0400
BZ 956388 - opps. forgot to commit this
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
index 7474b22..fe5dcf3 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
@@ -94,7 +94,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public BundleAgentService getBundleAgentService(long timeout) {
+ public BundleAgentService getBundleAgentService(Long timeout) {
return getBundleAgentService();
}
@@ -104,7 +104,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ContentAgentService getContentAgentService(long timeout) {
+ public ContentAgentService getContentAgentService(Long timeout) {
return getContentAgentService();
}
@@ -114,7 +114,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ResourceFactoryAgentService getResourceFactoryAgentService(long timeout) {
+ public ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout) {
return getResourceFactoryAgentService();
}
@@ -124,7 +124,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public ConfigurationAgentService getConfigurationAgentService(long timeout) {
+ public ConfigurationAgentService getConfigurationAgentService(Long timeout) {
return getConfigurationAgentService();
}
@@ -134,7 +134,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public DiscoveryAgentService getDiscoveryAgentService(long timeout) {
+ public DiscoveryAgentService getDiscoveryAgentService(Long timeout) {
return getDiscoveryAgentService();
}
@@ -144,7 +144,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public MeasurementAgentService getMeasurementAgentService(long timeout) {
+ public MeasurementAgentService getMeasurementAgentService(Long timeout) {
return getMeasurementAgentService();
}
@@ -154,7 +154,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public OperationAgentService getOperationAgentService(long timeout) {
+ public OperationAgentService getOperationAgentService(Long timeout) {
return getOperationAgentService();
}
@@ -164,7 +164,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public SupportAgentService getSupportAgentService(long timeout) {
+ public SupportAgentService getSupportAgentService(Long timeout) {
return getSupportAgentService();
}
@@ -174,7 +174,7 @@ public class TestAgentClient implements AgentClient, BundleAgentService, DriftAg
}
@Override
- public DriftAgentService getDriftAgentService(long timeout) {
+ public DriftAgentService getDriftAgentService(Long timeout) {
return getDriftAgentService();
}
commit 9159de1ad8c1055dfb05fe8cb1aed1f2d73d63a3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Apr 25 10:20:45 2013 -0400
BZ 956388 - autboxing got us. the API should allow for Long (not long) to allow for code to pass in long numbers or null to pick up the default
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
index c91c0a9..1f86df3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/AgentClient.java
@@ -72,37 +72,37 @@ public interface AgentClient {
BundleAgentService getBundleAgentService();
- BundleAgentService getBundleAgentService(long timeout);
+ BundleAgentService getBundleAgentService(Long timeout);
ContentAgentService getContentAgentService();
- ContentAgentService getContentAgentService(long timeout);
+ ContentAgentService getContentAgentService(Long timeout);
ResourceFactoryAgentService getResourceFactoryAgentService();
- ResourceFactoryAgentService getResourceFactoryAgentService(long timeout);
+ ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout);
DiscoveryAgentService getDiscoveryAgentService();
- DiscoveryAgentService getDiscoveryAgentService(long timeout);
+ DiscoveryAgentService getDiscoveryAgentService(Long timeout);
MeasurementAgentService getMeasurementAgentService();
- MeasurementAgentService getMeasurementAgentService(long timeout);
+ MeasurementAgentService getMeasurementAgentService(Long timeout);
OperationAgentService getOperationAgentService();
- OperationAgentService getOperationAgentService(long timeout);
+ OperationAgentService getOperationAgentService(Long timeout);
ConfigurationAgentService getConfigurationAgentService();
- ConfigurationAgentService getConfigurationAgentService(long timeout);
+ ConfigurationAgentService getConfigurationAgentService(Long timeout);
SupportAgentService getSupportAgentService();
- SupportAgentService getSupportAgentService(long timeout);
+ SupportAgentService getSupportAgentService(Long timeout);
DriftAgentService getDriftAgentService();
- DriftAgentService getDriftAgentService(long timeout);
+ DriftAgentService getDriftAgentService(Long timeout);
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
index 5ef22e6..c2d4049 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/agentclient/impl/AgentClientImpl.java
@@ -137,7 +137,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public BundleAgentService getBundleAgentService(long timeout) {
+ public BundleAgentService getBundleAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(BundleAgentService.class, timeout);
}
@@ -147,7 +147,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ContentAgentService getContentAgentService(long timeout) {
+ public ContentAgentService getContentAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ContentAgentService.class, timeout);
}
@@ -157,7 +157,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ResourceFactoryAgentService getResourceFactoryAgentService(long timeout) {
+ public ResourceFactoryAgentService getResourceFactoryAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ResourceFactoryAgentService.class, timeout);
}
@@ -167,7 +167,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public DiscoveryAgentService getDiscoveryAgentService(long timeout) {
+ public DiscoveryAgentService getDiscoveryAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(DiscoveryAgentService.class, timeout);
}
@@ -177,7 +177,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public MeasurementAgentService getMeasurementAgentService(long timeout) {
+ public MeasurementAgentService getMeasurementAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(MeasurementAgentService.class, timeout);
}
@@ -187,7 +187,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public OperationAgentService getOperationAgentService(long timeout) {
+ public OperationAgentService getOperationAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(OperationAgentService.class, timeout);
}
@@ -197,7 +197,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public ConfigurationAgentService getConfigurationAgentService(long timeout) {
+ public ConfigurationAgentService getConfigurationAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(ConfigurationAgentService.class, timeout);
}
@@ -207,7 +207,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public SupportAgentService getSupportAgentService(long timeout) {
+ public SupportAgentService getSupportAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(SupportAgentService.class, timeout);
}
@@ -217,7 +217,7 @@ public class AgentClientImpl implements AgentClient {
}
@Override
- public DriftAgentService getDriftAgentService(long timeout) {
+ public DriftAgentService getDriftAgentService(Long timeout) {
return clientRemotePojoFactory.getRemotePojo(DriftAgentService.class, timeout);
}
commit d2330a2d819b5ad2855fe1f32dc3005ab31f8543
Author: Heiko W. Rupp <hwr(a)redhat.com>
Date: Thu Apr 25 14:52:06 2013 +0200
Discover WildFly servers as such.
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
index fb328a3..9a4d5bd 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/BaseProcessDiscovery.java
@@ -70,6 +70,7 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
private static final String JBOSS_AS_PREFIX = "jboss-as-";
private static final String JBOSS_EAP_PREFIX = "jboss-eap-";
+ private static final String WILDFLY_PREFIX = "wildfly-";
private static final String HOME_DIR_SYSPROP = "jboss.home.dir";
@@ -467,14 +468,14 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
return detail;
}
- private String getServerAttribute(ASConnection connection, String attributeName) {
+ private <T>T getServerAttribute(ASConnection connection, String attributeName) {
Operation op = new ReadAttribute(null, attributeName);
Result res = connection.execute(op);
if (!res.isSuccess()) {
throw new InvalidPluginConfigurationException("Could not connect to remote server ["
+ res.getFailureDescription() + "]. Did you enable management?");
}
- return (String) res.getResult();
+ return (T) res.getResult();
}
// never returns null
@@ -563,7 +564,9 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
protected String determineServerVersionFromHomeDir(File homeDir) {
String version;
String homeDirName = homeDir.getName();
- if (homeDirName.startsWith(JBOSS_AS_PREFIX)) {
+ if (homeDirName.startsWith(WILDFLY_PREFIX)) {
+ version = homeDirName.substring(WILDFLY_PREFIX.length());
+ } else if (homeDirName.startsWith(JBOSS_AS_PREFIX)) {
version = homeDirName.substring(JBOSS_AS_PREFIX.length());
} else if (homeDirName.startsWith(JBOSS_EAP_PREFIX)) {
version = homeDirName.substring(JBOSS_EAP_PREFIX.length());
@@ -606,8 +609,17 @@ public abstract class BaseProcessDiscovery implements ResourceDiscoveryComponent
ASConnection connection = new ASConnection(hostname, port, user, pass);
try {
String productName = getServerAttribute(connection, "product-name");
- productType = ((productName != null) && !productName.isEmpty()) ?
- JBossProductType.getValueByProductName(productName) : JBossProductType.AS;
+ if ((productName != null) && !productName.isEmpty())
+ productType = JBossProductType.getValueByProductName(productName);
+ else {
+ Integer apiVersion = getServerAttribute(connection,"management-major-version");
+ if (apiVersion==1) {
+ productType = JBossProductType.AS;
+ } else {
+ // In the future also check for other versions of WildFly via the release-version
+ productType = JBossProductType.WILDFLY8;
+ }
+ }
releaseVersion = getServerAttribute(connection, "release-version");
releaseCodeName = getServerAttribute(connection, "release-codename");
serverName = getServerAttribute(connection, "name");
diff --git a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
index eb86f0b..9edfb2f 100644
--- a/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
+++ b/modules/plugins/jboss-as-7/src/main/java/org/rhq/modules/plugins/jbossas7/JBossProductType.java
@@ -36,7 +36,8 @@ public enum JBossProductType {
EPP("EPP", "JBoss EAP 6", "JBoss Enterprise Portal Platform 6", "Portal Platform"),
JPP("JPP", "JBoss EAP 6", "JBoss Portal Platform 6", "Portal Platform"),
// EWP("EWP", "JBoss EWP 6", "JBoss Enterprise Web Platform 6", "EWP"),
- SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP");
+ SOA("SOA-P", "JBoss SOA-P 6", "JBoss Enterprise SOA Platform (ESB)", "SOAP"),
+ WILDFLY8("WildFly","WildFly 8" ,"WildFly Appliction Server 8" , "WildFly");
public final String SHORT_NAME;
public final String NAME;
@@ -98,7 +99,7 @@ public enum JBossProductType {
productType = JBossProductType.EAP;
} else if (slot.equals("jdg")) {
productType = JBossProductType.JDG;
- } else if (slot.equals("epp")) {//old EPP
+ } else if (slot.equals("epp")) {//old EPP
productType = JBossProductType.EPP;
} else if (slot.equals("jpp")) {//new EPP->JPP plugin
productType = JBossProductType.JPP;
@@ -108,7 +109,9 @@ public enum JBossProductType {
throw new RuntimeException("Unknown product type: " + slot);
}
} else {
- productType = JBossProductType.AS;
+ // Wildfly and The Server Formerly Known AS JBossAS share the same absence of a slot
+ // so we need another way to distinguish them
+ productType = determineJBossProductTypeViaHomeDirName(homeDir);
}
return productType;
@@ -119,6 +122,8 @@ public enum JBossProductType {
String homeDirName = homeDir.getName();
if (homeDirName.contains("-as-")) {
productType = JBossProductType.AS;
+ } else if (homeDirName.contains("wildfly")) {
+ productType = JBossProductType.WILDFLY8;
} else if (homeDirName.contains("-eap-")) {
productType = JBossProductType.EAP;
} else if (homeDirName.contains("-jdg-")||(homeDirName.contains("datagrid-server"))) {
10 years, 11 months
[rhq] modules/enterprise
by mazz
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java | 6 +-
modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/ServiceContainerConfigurationConstants.java | 6 +-
modules/enterprise/gui/remoting-war/src/main/webapp/WEB-INF/web.xml | 2
modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java | 3 -
modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml | 16 +++--
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java | 8 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java | 28 +++++++++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerConfiguration.java | 8 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerI18NResourceKeys.java | 6 ++
modules/enterprise/server/sars/services-sar/src/main/resources/server-comm-configuration-overrides.properties | 8 +-
10 files changed, 70 insertions(+), 21 deletions(-)
New commits:
commit 32e712e4da7a4ba93babb7e41c67c71aa1a838f7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu May 30 10:02:07 2013 -0400
BZ 968357 535831 get IBM JRE to run on both server and agent with SSL/certs
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
index 3f9a89b..c5cf4a8 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentConfigurationConstants.java
@@ -412,7 +412,8 @@ public interface AgentConfigurationConstants {
/**
* Default algorithm for the keystore.
*/
- String DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_ALGORITHM = "SunX509";
+ String DEFAULT_CLIENT_SENDER_SECURITY_KEYSTORE_ALGORITHM = (System.getProperty("java.vendor", "").contains("IBM") ? "IbmX509"
+ : "SunX509");
/**
* The type of keystore file.
@@ -454,7 +455,8 @@ public interface AgentConfigurationConstants {
/**
* Default algorithm for the truststore.
*/
- String DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_ALGORITHM = "SunX509";
+ String DEFAULT_CLIENT_SENDER_SECURITY_TRUSTSTORE_ALGORITHM = (System.getProperty("java.vendor", "").contains("IBM") ? "IbmX509"
+ : "SunX509");
/**
* The type of truststore file.
diff --git a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/ServiceContainerConfigurationConstants.java b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/ServiceContainerConfigurationConstants.java
index 8edf251..d157775 100644
--- a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/ServiceContainerConfigurationConstants.java
+++ b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/ServiceContainerConfigurationConstants.java
@@ -195,7 +195,8 @@ public interface ServiceContainerConfigurationConstants {
/**
* Default algorithm for the keystore.
*/
- String DEFAULT_CONNECTOR_SECURITY_KEYSTORE_ALGORITHM = "SunX509";
+ String DEFAULT_CONNECTOR_SECURITY_KEYSTORE_ALGORITHM = (System.getProperty("java.vendor", "").contains("IBM") ? "IbmX509"
+ : "SunX509");
/**
* The type of keystore which defines the keystore file format.
@@ -246,7 +247,8 @@ public interface ServiceContainerConfigurationConstants {
/**
* Default algorithm for the truststore.
*/
- String DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_ALGORITHM = "SunX509";
+ String DEFAULT_CONNECTOR_SECURITY_TRUSTSTORE_ALGORITHM = (System.getProperty("java.vendor", "").contains("IBM") ? "IbmX509"
+ : "SunX509");
/**
* The type of truststore file.
diff --git a/modules/enterprise/gui/remoting-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/remoting-war/src/main/webapp/WEB-INF/web.xml
index cd278c0..38881c7 100644
--- a/modules/enterprise/gui/remoting-war/src/main/webapp/WEB-INF/web.xml
+++ b/modules/enterprise/gui/remoting-war/src/main/webapp/WEB-INF/web.xml
@@ -20,7 +20,7 @@
</init-param>
<init-param>
<param-name>invokerName</param-name>
- <param-value>jboss.remoting:service=invoker,transport=servlet,rhq.communications.connector.rhqtype=server,*</param-value>
+ <param-value>jboss.remoting:service=invoker,rhq.communications.connector.rhqtype=server,*</param-value>
<description>The servlet server invoker - in RHQ's impl of the servlet, this is a query ObjectName that must find 1 bean</description>
</init-param>
<load-on-startup>-1</load-on-startup>
diff --git a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
index 199dd5c..95c00ae 100644
--- a/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
+++ b/modules/enterprise/remoting/client-api/src/main/java/org/rhq/enterprise/clientapi/RemoteClient.java
@@ -421,7 +421,8 @@ public class RemoteClient implements RhqFacade {
Map<String, String> config = new HashMap<String, String>();
if (SecurityUtil.isTransportSecure(locatorURI)) {
setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_FILE_PATH, "data/keystore.dat");
- setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_ALGORITHM, "SunX509");
+ setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_ALGORITHM, (System.getProperty("java.vendor", "")
+ .contains("IBM") ? "IbmX509" : "SunX509"));
setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_TYPE, "JKS");
setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_STORE_PASSWORD, "password");
setConfigProp(config, SSLSocketBuilder.REMOTING_KEY_PASSWORD, "password");
diff --git a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
index e9f3bbe..aeeb949 100644
--- a/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/appserver/src/main/scripts/rhq-container.build.xml
@@ -14,7 +14,7 @@
<property name="default.rhq.server.database.port" value="5432" />
<property name="default.rhq.server.database.db-name" value="rhq" />
<property name="default.rhq.server.quartz.driverDelegateClass" value="org.quartz.impl.jdbcjobstore.PostgreSQLDelegate" />
- <property name="default.rhq.server.quartz.selectWithLockSQL" value="SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE" />
+ <property name="default.rhq.server.quartz.selectWithLockSQL" value="SELECT * FROM {0}LOCKS ROWLOCK WHERE LOCK_NAME = ? FOR UPDATE" />
<property name="default.rhq.server.quartz.lockHandlerClass" value="org.quartz.impl.jdbcjobstore.StdRowLockSemaphore" />
<property name="rhq.sync.endpoint-address" value="false"/>
@@ -499,9 +499,13 @@ rhq.communications.multicast-detector.port=16162
# [Due to issue https://issues.jboss.org/browse/WFLY-1177, you cannot change
# rhq.server.tomcat.security.keystore.file or rhq.server.tomcat.security.truststore.file
# after you install RHQ. If you need to change those again, you must manually do so in standalone-full.xml.]
+# Note that security algorithm settings are commented out - the defaults will be determined at runtime
+# based on the JVM the server is running in (for IBM JVMs, the algorithm will default to "IbmX509",
+# for all other JVMs, the algorithm will default to "SunX509"). If you need a specific algorithm value,
+# you may hardcode it here in this file by uncommenting the lines and setting the values explicitly.
rhq.server.tomcat.security.client-auth-mode=false
rhq.server.tomcat.security.secure-socket-protocol=TLS
-rhq.server.tomcat.security.algorithm=SunX509
+#rhq.server.tomcat.security.algorithm=SunX509
rhq.server.tomcat.security.keystore.alias=RHQ
rhq.server.tomcat.security.keystore.file=${jboss.server.config.dir}/rhq.keystore
rhq.server.tomcat.security.keystore.password=RHQManagement
@@ -514,13 +518,13 @@ rhq.server.tomcat.security.truststore.type=JKS
# These are used when secure transports other than sslservlet are used
rhq.communications.connector.security.secure-socket-protocol=TLS
rhq.communications.connector.security.keystore.file=${jboss.server.config.dir}/rhq.keystore
-rhq.communications.connector.security.keystore.algorithm=SunX509
+#rhq.communications.connector.security.keystore.algorithm=SunX509
rhq.communications.connector.security.keystore.type=JKS
rhq.communications.connector.security.keystore.password=RHQManagement
rhq.communications.connector.security.keystore.key-password=RHQManagement
rhq.communications.connector.security.keystore.alias=RHQ
rhq.communications.connector.security.truststore.file=${jboss.server.config.dir}/rhq.truststore
-rhq.communications.connector.security.truststore.algorithm=SunX509
+#rhq.communications.connector.security.truststore.algorithm=SunX509
rhq.communications.connector.security.truststore.type=JKS
rhq.communications.connector.security.truststore.password=RHQManagement
rhq.communications.connector.security.client-auth-mode=none
@@ -528,13 +532,13 @@ rhq.communications.connector.security.client-auth-mode=none
# Client-side SSL Security Configuration (for outgoing messages to agents)
rhq.server.client.security.secure-socket-protocol=TLS
rhq.server.client.security.keystore.file=${jboss.server.config.dir}/rhq.keystore
-rhq.server.client.security.keystore.algorithm=SunX509
+#rhq.server.client.security.keystore.algorithm=SunX509
rhq.server.client.security.keystore.type=JKS
rhq.server.client.security.keystore.password=RHQManagement
rhq.server.client.security.keystore.key-password=RHQManagement
rhq.server.client.security.keystore.alias=RHQ
rhq.server.client.security.truststore.file=${jboss.server.config.dir}/rhq.truststore
-rhq.server.client.security.truststore.algorithm=SunX509
+#rhq.server.client.security.truststore.algorithm=SunX509
rhq.server.client.security.truststore.type=JKS
rhq.server.client.security.truststore.password=RHQManagement
rhq.server.client.security.server-auth-mode-enabled=false
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index bb42d4a..51bebff 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -550,11 +550,15 @@ public class InstallerServiceImpl implements InstallerService {
final PropertiesFileUpdate propsFile = new PropertiesFileUpdate(serverPropertiesFile.getAbsolutePath());
final Properties props = propsFile.loadExistingProperties();
- // force some hardcoded defaults for IBM JVMs that must have specific values
+ // the default algorithm that RHQ will use in the comm layer will be defined at runtime based on the VM
+ // but if the user mistakenly set the algorithm to the Sun value while using IBM JVM, then force
+ // some hardcoded defaults so it can more likely work for IBM JVMs.
final boolean isIBM = System.getProperty("java.vendor", "").contains("IBM");
if (isIBM) {
for (String algPropName : ServerProperties.IBM_ALGOROTHM_SETTINGS) {
- props.setProperty(algPropName, "IbmX509");
+ if (props.getProperty(algPropName, "").equalsIgnoreCase("SunX509")) {
+ props.setProperty(algPropName, "IbmX509");
+ }
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
index 0d88020..a609a55 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
@@ -820,6 +820,9 @@ public class ServerCommunicationsService implements ServerCommunicationsServiceM
// allow ${var} notation in the values so we can provide variable replacements in the values
value = replaceProperties(value);
+ // there are a few settings that normally aren't set but can be set at runtime - set them now
+ value = determineSecurityAlgorithm(value);
+
preferences_node.put(key, value);
LOG.debug(ServerI18NResourceKeys.CONFIG_PREFERENCE_OVERRIDE, key, value);
}
@@ -849,13 +852,19 @@ public class ServerCommunicationsService implements ServerCommunicationsServiceM
.valueOf(bindPort));
}
} catch (Exception e) {
- LOG.error("Unable to set explicit connector address/port, using defaults: ", e);
+ LOG.error(ServerI18NResourceKeys.ERROR_SETTING_CONNECTOR_COMM_PREFS, e);
ServiceContainerConfiguration scConfig = new ServiceContainerConfiguration(config.getPreferences());
preferences_node.put(ServiceContainerConfigurationConstants.CONNECTOR_BIND_ADDRESS, scConfig
.getConnectorBindAddress());
preferences_node.put(ServiceContainerConfigurationConstants.CONNECTOR_BIND_PORT, String.valueOf(scConfig
.getConnectorBindPort()));
+ } finally {
+ try {
+ preferences_node.flush();
+ } catch (Exception e) {
+ LOG.error(ServerI18NResourceKeys.ERROR_FLUSHING_SERVER_PREFS, e);
+ }
}
// let's make sure our configuration is upgraded to the latest schema
@@ -866,6 +875,23 @@ public class ServerCommunicationsService implements ServerCommunicationsServiceM
return config;
}
+ private String determineSecurityAlgorithm(String value) {
+ String[] algorithmPropNames = new String[] {
+ ServerConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_ALGORITHM,
+ ServerConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_ALGORITHM,
+ ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_KEYSTORE_ALGORITHM,
+ ServiceContainerConfigurationConstants.CONNECTOR_SECURITY_TRUSTSTORE_ALGORITHM };
+
+ for (String algorithmPropName : algorithmPropNames) {
+ // if the value is still the ${x} token, it means that setting was not set - let's set it now
+ if (value.startsWith("${" + algorithmPropName)) {
+ return System.getProperty("java.vendor", "").contains("IBM") ? "IbmX509" : "SunX509";
+ }
+ }
+
+ return value;
+ }
+
/**
* Loads the {@link #getConfigurationFile() configuration file}. The file location will first be checked for
* existence on the file system and then as a URL. If it cannot be found, it will be assumed the file location
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerConfiguration.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerConfiguration.java
index 5bd9bb5..41e7387 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerConfiguration.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerConfiguration.java
@@ -559,7 +559,7 @@ public class ServerConfiguration {
*/
public String getClientSenderSecurityKeystoreAlgorithm() {
String value = m_preferences.get(ServerConfigurationConstants.CLIENT_SENDER_SECURITY_KEYSTORE_ALGORITHM,
- "SunX509");
+ (isIBM() ? "IbmX509" : "SunX509"));
return value;
}
@@ -623,7 +623,7 @@ public class ServerConfiguration {
*/
public String getClientSenderSecurityTruststoreAlgorithm() {
String value = m_preferences.get(ServerConfigurationConstants.CLIENT_SENDER_SECURITY_TRUSTSTORE_ALGORITHM,
- "SunX509");
+ (isIBM() ? "IbmX509" : "SunX509"));
return value;
}
@@ -693,4 +693,8 @@ public class ServerConfiguration {
return buf.toString();
}
+
+ private boolean isIBM() {
+ return System.getProperty("java.vendor", "").contains("IBM");
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerI18NResourceKeys.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerI18NResourceKeys.java
index 2d742cf..3e0c2ae 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerI18NResourceKeys.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerI18NResourceKeys.java
@@ -29,6 +29,12 @@ import mazz.i18n.annotation.I18NResourceBundle;
*/
@I18NResourceBundle(baseName = "server-messages", defaultLocale = "en")
public interface ServerI18NResourceKeys {
+ @I18NMessages({ @I18NMessage("Failed to flush server preferences to backing store") })
+ String ERROR_FLUSHING_SERVER_PREFS = "ServerCommunicationsService.error-flushing-server-prefs";
+
+ @I18NMessages({ @I18NMessage("Unable to set explicit connector address/port, using defaults") })
+ String ERROR_SETTING_CONNECTOR_COMM_PREFS = "ServerCommunicationsService.error-setting-conn-comm-prefs";
+
@I18NMessages( { @I18NMessage("Failed to remove remote API invocation handler. Cause: {0}") })
String REMOTE_API_REMOVAL_FAILURE = "ServerCommunicationsService.remote-api-removal-failure";
diff --git a/modules/enterprise/server/sars/services-sar/src/main/resources/server-comm-configuration-overrides.properties b/modules/enterprise/server/sars/services-sar/src/main/resources/server-comm-configuration-overrides.properties
index 7a407cc..91ccc85 100644
--- a/modules/enterprise/server/sars/services-sar/src/main/resources/server-comm-configuration-overrides.properties
+++ b/modules/enterprise/server/sars/services-sar/src/main/resources/server-comm-configuration-overrides.properties
@@ -17,26 +17,26 @@ rhq.communications.multicast-detector.port=${rhq.communications.multicast-detect
# Server-side SSL Security Configuration (for incoming messages from agents)
rhq.communications.connector.security.secure-socket-protocol=${rhq.communications.connector.security.secure-socket-protocol:TLS}
rhq.communications.connector.security.keystore.file=${rhq.communications.connector.security.keystore.file}
-rhq.communications.connector.security.keystore.algorithm=${rhq.communications.connector.security.keystore.algorithm:SunX509}
+rhq.communications.connector.security.keystore.algorithm=${rhq.communications.connector.security.keystore.algorithm}
rhq.communications.connector.security.keystore.type=${rhq.communications.connector.security.keystore.type:JKS}
rhq.communications.connector.security.keystore.password=${rhq.communications.connector.security.keystore.password:rhqpwd}
rhq.communications.connector.security.keystore.key-password=${rhq.communications.connector.security.keystore.key-password:rhqpwd}
rhq.communications.connector.security.keystore.alias=${rhq.communications.connector.security.keystore.alias:rhq}
rhq.communications.connector.security.truststore.file=${rhq.communications.connector.security.truststore.file}
-rhq.communications.connector.security.truststore.algorithm=${rhq.communications.connector.security.truststore.algorithm:SunX509}
+rhq.communications.connector.security.truststore.algorithm=${rhq.communications.connector.security.truststore.algorithm}
rhq.communications.connector.security.truststore.type=${rhq.communications.connector.security.truststore.type:JKS}
rhq.communications.connector.security.truststore.password=${rhq.communications.connector.security.truststore.password}
rhq.communications.connector.security.client-auth-mode=${rhq.communications.connector.security.client-auth-mode:none}
# Client-side SSL Security Configuration (for outgoing messages to agents)
rhq.server.client.security.secure-socket-protocol=${rhq.server.client.security.secure-socket-protocol:TLS}
rhq.server.client.security.keystore.file=${rhq.server.client.security.keystore.file}
-rhq.server.client.security.keystore.algorithm=${rhq.server.client.security.keystore.algorithm:SunX509}
+rhq.server.client.security.keystore.algorithm=${rhq.server.client.security.keystore.algorithm}
rhq.server.client.security.keystore.type=${rhq.server.client.security.keystore.type:JKS}
rhq.server.client.security.keystore.password=${rhq.server.client.security.keystore.password:rhqpwd}
rhq.server.client.security.keystore.key-password=${rhq.server.client.security.keystore.key-password:rhqpwd}
rhq.server.client.security.keystore.alias=${rhq.server.client.security.keystore.alias:rhq}
rhq.server.client.security.truststore.file=${rhq.server.client.security.truststore.file}
-rhq.server.client.security.truststore.algorithm=${rhq.server.client.security.truststore.algorithm:SunX509}
+rhq.server.client.security.truststore.algorithm=${rhq.server.client.security.truststore.algorithm}
rhq.server.client.security.truststore.type=${rhq.server.client.security.truststore.type:JKS}
rhq.server.client.security.truststore.password=${rhq.server.client.security.truststore.password}
rhq.server.client.security.server-auth-mode-enabled=${rhq.server.client.security.server-auth-mode-enabled:false}
10 years, 11 months
[rhq] Branch 'feature/cassandra-backend' - modules/common modules/core modules/enterprise modules/helpers
by snegrea
modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java | 12
modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java | 8
modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java | 10
modules/common/cassandra-schema/pom.xml | 54 +
modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java | 457 ++++++----
modules/common/cassandra-schema/src/main/resources/changelog.xml | 51 -
modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml | 18
modules/common/cassandra-schema/src/main/resources/schema/drop/0001.xml | 10
modules/common/cassandra-schema/src/main/resources/schema/update/0001.xml | 49 +
modules/core/dbutils/pom.xml | 25
modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java | 26
modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java | 3
12 files changed, 458 insertions(+), 265 deletions(-)
New commits:
commit 73040236b009da40c391616b0ade88cbfdbf2960
Author: Stefan Negrea <snegrea(a)redhat.com>
Date: Thu May 30 08:55:25 2013 -0500
Cassandra schema manager.
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
index e6ac0cb..1ad3599 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java
@@ -90,7 +90,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
private Event<GenerateDeployment> generateDeploymentEvent;
@Inject
- // Active some form of ClassContext around our deployments due to assumption bug in AS7 extension.
+ // Active some form of ClassContext around our deployments due to assumption bug in AS7 extension.
private Instance<ClassContext> classContext;
public void startup(@Observes(precedence = -100)
@@ -152,11 +152,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
}
try {
- if (!schemaManager.schemaExists()) {
- schemaManager.createSchema();
- }
- schemaManager.updateSchema();
- schemaManager.shutdown();
+ schemaManager.install();
} catch (Exception e) {
if (null != ccm) {
@@ -212,7 +208,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
public void overrideBefore(@Observes
EventContext<BeforeClass> event) {
- // Don't continue TestClass's BeforeClass context as normal.
+ // Don't continue TestClass's BeforeClass context as normal.
// No DeploymentGeneration or Deploy will take place.
classDeploymentScenario.set(suiteDeploymentScenario);
@@ -220,7 +216,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
public void overrideAfter(@Observes
EventContext<AfterClass> event) {
- // Don't continue TestClass's AfterClass context as normal.
+ // Don't continue TestClass's AfterClass context as normal.
// No UnDeploy will take place.
}
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java b/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java
index 5cdff36..5f77ab6 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java
@@ -71,10 +71,12 @@ public class DeployMojo extends AbstractMojo {
getLog().info("Installing RHQ schema");
SchemaManager schemaManager = new SchemaManager(deploymentOptions.getUsername(),
deploymentOptions.getPassword(), nodes);
- if (!schemaManager.schemaExists()) {
- schemaManager.createSchema();
+
+ try {
+ schemaManager.install();
+ } catch (Exception e) {
+ throw new MojoExecutionException("Schema installation failed.", e);
}
- schemaManager.updateSchema();
long end = System.currentTimeMillis();
getLog().info("Finished cluster deployment in " + (end - start) + " ms");
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
index 4de7991..7f21fa8 100644
--- a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
+++ b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java
@@ -53,7 +53,7 @@ public class CCMTestNGListener implements IInvokedMethodListener {
if (method.isAnnotationPresent(DeployCluster.class)) {
try {
deployCluster(method.getAnnotation(DeployCluster.class));
- } catch (CassandraException e) {
+ } catch (Exception e) {
log.warn("Failed to deploy cluster", e);
}
}
@@ -75,7 +75,7 @@ public class CCMTestNGListener implements IInvokedMethodListener {
}
}
- private void deployCluster(DeployCluster annotation) throws CassandraException {
+ private void deployCluster(DeployCluster annotation) throws Exception {
boolean deploy = Boolean.valueOf(System.getProperty("rhq.cassandra.cluster.deploy", "true"));
if (!deploy) {
return;
@@ -123,11 +123,7 @@ public class CCMTestNGListener implements IInvokedMethodListener {
clusterInitService.waitForClusterToStart(nodes, nodes.size(), 1500, 20, 2);
SchemaManager schemaManager = new SchemaManager(annotation.username(), annotation.password(), nodes);
- if (!schemaManager.schemaExists()) {
- schemaManager.createSchema();
- schemaManager.updateSchema();
- }
- schemaManager.shutdown();
+ schemaManager.install();
if (annotation.waitForSchemaAgreement()) {
// TODO do not hard code cluster name
diff --git a/modules/common/cassandra-schema/pom.xml b/modules/common/cassandra-schema/pom.xml
index e4f735d..59a8ac5 100644
--- a/modules/common/cassandra-schema/pom.xml
+++ b/modules/common/cassandra-schema/pom.xml
@@ -26,12 +26,66 @@
</dependency>
<dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ <dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${cassandra.driver.version}</version>
</dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <configuration>
+ <mainClass>org.rhq.cassandra.schema.SchemaManager</mainClass>
+ <classpathScope>compile</classpathScope>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.rhq.cassandra.schema.SchemaManager</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id> <!-- this is used for inheritance merges -->
+ <phase>package</phase> <!-- bind to the packaging phase -->
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
<profiles>
<profile>
<id>dev</id>
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
index b888db0..a43d06c 100644
--- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
+++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java
@@ -25,17 +25,42 @@
package org.rhq.cassandra.schema;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.JarURLConnection;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Enumeration;
import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.PreparedStatement;
+import com.datastax.driver.core.ProtocolOptions.Compression;
import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import org.rhq.cassandra.util.ClusterBuilder;
import org.rhq.core.domain.cloud.StorageNode;
@@ -47,242 +72,344 @@ import org.rhq.core.util.StringUtil;
public class SchemaManager {
private static final String RHQ_KEYSPACE = "rhq";
+ private static final String SCHEMA_BASE_FOLDER = "schema";
+ private static final String UPDATE_PLAN_ELEMENT = "updatePlan";
+ private static final String STEP_ELEMENT = "step";
+
+ private static final String SCHEMA_EXISTS_QUERY = "SELECT * FROM system.schema_keyspaces WHERE keyspace_name = 'rhq';";
+ private static final String VERSION_COLUMNFAMILY_EXISTS_QUERY = "SELECT * from system.schema_columnfamilies WHERE keyspace_name='rhq' AND columnfamily_name='schema_version';";
+ private static final String VERSION_QUERY = "SELECT version FROM rhq.schema_version";
+ private static final String INSERT_VERSION_QUERY = "INSERT INTO rhq.schema_version (version, time ) VALUES ( ?, ?);";
+
private final Log log = LogFactory.getLog(SchemaManager.class);
- private Session session;
+ private enum Task {
+ Drop("drop"),
+ Create("create"),
+ Update("update");
- private String username;
+ private final String folder;
+
+ private Task(String folder){
+ this.folder = folder;
+ }
+ protected String getFolder() {
+ return "" + SCHEMA_BASE_FOLDER + "/" + this.folder + "/";
+ }
+ }
+
+ private Session session;
+ private String username;
private String password;
private List<StorageNode> nodes = new ArrayList<StorageNode>();
- private Integer systemAuthRF = null;
-
public SchemaManager(String username, String password, String... nodes) {
+ this(username, password, parseNodeInformation(nodes));
+ }
+
+ public SchemaManager(String username, String password, List<StorageNode> nodes) {
try {
this.username = username;
this.password = password;
+ this.nodes = nodes;
- for (String node : nodes) {
- StorageNode storageNode = new StorageNode();
- storageNode.parseNodeInformation(node);
+ this.initCluster();
+ this.shutdown();
+ } catch (NoHostAvailableException e) {
+ throw new RuntimeException("Unable create storage node session.", e);
+ }
+ }
- this.nodes.add(storageNode);
- }
+ public void install() throws Exception {
+ log.info("Preparing to install schema");
+ try {
initCluster();
+
+ if (!schemaExists()) {
+ this.executeTask(Task.Create);
+ } else {
+ log.info("RHQ schema already exists.");
+ }
+
+ this.executeTask(Task.Update);
} catch (NoHostAvailableException e) {
- throw new RuntimeException("Unable create session.", e);
+ throw new RuntimeException(e);
+ } finally {
+ shutdown();
}
}
- public SchemaManager(String username, String password, List<StorageNode> nodes) {
+ public void drop() throws Exception {
+ log.info("Preparing to drop RHQ schema");
try {
- this.username = username;
- this.password = password;
- this.nodes = nodes;
-
initCluster();
+
+ if (schemaExists()) {
+ this.executeTask(Task.Drop);
+ } else {
+ log.info("RHQ schema does not exist. Drop operation not required.");
+ }
} catch (NoHostAvailableException e) {
- throw new RuntimeException("Unable create session.", e);
+ throw new RuntimeException(e);
+ } finally {
+ shutdown();
}
}
- private void initCluster() throws NoHostAvailableException {
- String[] hostNames = new String[nodes.size()];
- for (int i = 0; i < hostNames.length; ++i) {
- hostNames[i] = nodes.get(i).getAddress();
+ private boolean schemaExists() {
+ try {
+ ResultSet resultSet = session.execute(SCHEMA_EXISTS_QUERY);
+ if (!resultSet.all().isEmpty()) {
+ resultSet = session.execute(VERSION_COLUMNFAMILY_EXISTS_QUERY);
+ return !resultSet.all().isEmpty();
+ }
+ return false;
+ } catch (Exception e) {
+ log.error(e);
+ throw new RuntimeException(e);
}
+ }
- if (log.isDebugEnabled()) {
- log.debug("Initializing session to connect to " + StringUtil.arrayToString(hostNames));
- } else {
- log.info("Initializing session");
+ private int getSchemaVersion() {
+ int maxVersion = 0;
+ try {
+ ResultSet resultSet = session.execute(VERSION_QUERY);
+ for (Row row : resultSet.all()) {
+ if (maxVersion < row.getInt(0)) {
+ maxVersion = row.getInt(0);
+ }
+ }
+ } catch (Exception e) {
+ log.error(e);
+ throw new RuntimeException(e);
}
- Cluster cluster = new ClusterBuilder()
- .addContactPoints(hostNames)
- .withCredentials("cassandra", "cassandra")
- .withPort(nodes.get(0).getCqlPort())
- .build();
- session = cluster.connect("system");
+ return maxVersion;
}
- public void createSchema() {
+ private void executeTask(Task task) throws Exception {
try {
- if (!schemaExists()) {
- log.info("Preparing to create schema");
- log.debug("Creating user [rhqadmin]");
- session.execute("CREATE USER rhqadmin WITH PASSWORD 'rhqadmin' SUPERUSER");
- log.debug("Creating keyspace [" + RHQ_KEYSPACE + "]");
-
- int replicationFactor = 1;
- if (nodes.size() == 1) {
- replicationFactor = 1;
- } else if (nodes.size() < 4) {
- replicationFactor = 2;
- } else {
- replicationFactor = 3;
+ log.info("Starting to execute " + task + " task.");
+
+ List<String> updateFiles = this.getUpdateFiles(task);
+
+ if (Task.Update.equals(task)) {
+ int currentSchemaVersion = this.getSchemaVersion();
+ log.info("Current schema version is " + currentSchemaVersion);
+ this.removeAppliedUpdates(updateFiles, currentSchemaVersion);
+ }
+
+ if (updateFiles.size() == 0 && Task.Update.equals(task)) {
+ log.info("RHQ schema is current! No updates applied.");
+ }
+
+ for (String updateFile : updateFiles) {
+ log.info("Applying file " + updateFile + " for " + task + " task.");
+ for (String step : getSteps(updateFile)) {
+ log.info("Statement: \n" + step);
+ session.execute(step);
}
- log.debug("Setting replication_factor to " + replicationFactor + " for rhq keyspace");
- session.execute("CREATE KEYSPACE rhq WITH replication = {'class': 'SimpleStrategy', " +
- "'replication_factor': " + replicationFactor + "};");
+ if (Task.Update.equals(task)) {
+ this.updateSchemaVersion(updateFile);
+ }
- // Note that once we have a schema management tool back in place, the call
- // to createTables will be moved back to the updateSchema method as it
- // previously was when we were using liquibase. We do NOT want to have
- // separate install/update schema changes. Treating everything as an update as
- // liquibase does dramatically simplifies things.
- createTables();
- } else {
- log.info("Ignoring createSchema, schema already exists.");
+ log.info("File " + updateFile + " applied for " + task + " task.");
}
- } catch (NoHostAvailableException e) {
+ } catch (Exception e) {
+ log.error(e);
throw new RuntimeException(e);
}
+
+ log.info("Successfully executed " + task + " task.");
}
- public void dropSchema() {
- try {
- if (schemaExists()) {
- log.info("Dropping keyspace [" + RHQ_KEYSPACE + "]");
- session.execute("DROP KEYSPACE rhq");
- session.execute("DROP USER rhqadmin");
+ private void updateSchemaVersion(String test) {
+ PreparedStatement preparedStatement = session.prepare(INSERT_VERSION_QUERY);
+ BoundStatement boundStatement = preparedStatement.bind(this.extractVersionFromUpdateFile(test), new Date());
+ session.execute(boundStatement);
+ }
+
+ private void removeAppliedUpdates(List<String> updateFiles, int currentSchemaVersion) {
+ while (!updateFiles.isEmpty()) {
+ int version = this.extractVersionFromUpdateFile(updateFiles.get(0));
+ if (version <= currentSchemaVersion) {
+ updateFiles.remove(0);
} else {
- log.info("Ignoring dropSchema, schema does not exist.");
+ break;
}
- } catch (NoHostAvailableException e) {
- throw new RuntimeException(e);
}
}
- public void resetSchema() {
+ private int extractVersionFromUpdateFile(String file) {
+ file = file.substring(file.lastIndexOf('/') + 1);
+ file = file.substring(0, file.indexOf('.'));
+ return Integer.parseInt(file);
+ }
+
+ private List<String> getSteps(String file) throws Exception {
+ List<String> steps = new ArrayList<String>();
+ InputStream stream = null;
try {
- dropSchema();
- createSchema();
- } catch (NoHostAvailableException e) {
- throw new RuntimeException(e);
+ stream = this.getClass().getClassLoader().getResourceAsStream(file);
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document doc = builder.parse(stream);
+
+ Node rootDocument = doc.getElementsByTagName(UPDATE_PLAN_ELEMENT).item(0);
+ NodeList updateStepElements = rootDocument.getChildNodes();
+
+ for (int index = 0; index < updateStepElements.getLength(); index++) {
+ Node updateStepElement = updateStepElements.item(index);
+ if (STEP_ELEMENT.equals(updateStepElement.getNodeName()) && updateStepElement.getTextContent() != null) {
+ steps.add(updateStepElement.getTextContent());
+ }
+ }
+ } catch (Exception e) {
+ log.error("Error reading the list of steps from " + file + " file.", e);
+ throw e;
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (Exception e) {
+ log.error("Error closing the stream with the list of steps from " + file + " file.", e);
+ throw e;
+ }
+ }
}
+
+ return steps;
}
- public boolean schemaExists() {
+ private List<String> getUpdateFiles(Task task) throws Exception {
+ List<String> files = new ArrayList<String>();
+ InputStream stream = null;
+
try {
- String cql = "SELECT keyspace_name FROM schema_keyspaces WHERE keyspace_name = 'rhq'";
- ResultSet resultSet = session.execute(cql);
- return !resultSet.all().isEmpty();
- } catch (NoHostAvailableException e) {
- throw new RuntimeException(e);
+ URL resourceFolderURL = this.getClass().getClassLoader().getResource(task.getFolder());
+
+ if (resourceFolderURL.getProtocol().equals("file")) {
+ stream = this.getClass().getResourceAsStream(task.getFolder());
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+
+ String updateFile;
+ while ((updateFile = reader.readLine()) != null) {
+ files.add(task.getFolder() + updateFile);
+ }
+ } else if (resourceFolderURL.getProtocol().equals("jar")) {
+ URL jarURL = this.getClass().getClassLoader().getResources(task.getFolder()).nextElement();
+ JarURLConnection jarURLCon = (JarURLConnection) (jarURL.openConnection());
+ JarFile jarFile = jarURLCon.getJarFile();
+ Enumeration<JarEntry> entries = jarFile.entries();
+ while (entries.hasMoreElements()) {
+ String entry = entries.nextElement().getName();
+ if (entry.startsWith(task.getFolder()) && !entry.equals(task.getFolder())) {
+ files.add(entry);
+ }
+ }
+ }
+
+ Collections.sort(files, new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return o1.compareTo(o2);
+ }
+ });
+ } catch (Exception e) {
+ log.error("Error reading the list of update files.", e);
+ throw e;
+ } finally {
+ if (stream != null) {
+ try{
+ stream.close();
+ } catch (Exception e) {
+ log.error("Error closing the stream with the list of update files.", e);
+ throw e;
+ }
+ }
}
- }
- public void updateSchema() {
- log.info("Applying schema updates");
- //createTables();
+ return files;
}
- private void createTables() {
- int gcGraceSeconds = 864000;
- if (nodes.size() == 1) {
- gcGraceSeconds = 0;
- } else {
- gcGraceSeconds = 691200; // 8 days
+ private static List<StorageNode> parseNodeInformation(String... nodes) {
+ List<StorageNode> parsedNodes = new ArrayList<StorageNode>();
+ for (String node : nodes) {
+ StorageNode storageNode = new StorageNode();
+ storageNode.parseNodeInformation(node);
+ parsedNodes.add(storageNode);
}
- try {
- // Update the system_auth RF from server code. That makes more sense since we
- // need run repair on each node after the schema change.
-
-// log.debug("Setting system_auth keyspace replication_factor to " + nodes.size());
-// session.execute(
-// "ALTER KEYSPACE system_auth WITH replication = " +
-// "{'class' : 'SimpleStrategy', 'replication_factor' : " + nodes.size() + "};"
-// );
-
- log.debug("Creating table raw_metrics");
- session.execute(
- "CREATE TABLE rhq.raw_metrics (" +
- "schedule_id int, " +
- "time timestamp, " +
- "value double, " +
- "PRIMARY KEY (schedule_id, time) " +
- ") WITH COMPACT STORAGE AND gc_grace_seconds = " + gcGraceSeconds + ";"
- );
- log.debug("Creating table one_hour_metrics");
- session.execute(
- "CREATE TABLE rhq.one_hour_metrics (" +
- "schedule_id int, " +
- "time timestamp, " +
- "type int, " +
- "value double, " +
- "PRIMARY KEY (schedule_id, time, type) " +
- ") WITH COMPACT STORAGE AND gc_grace_seconds = " + gcGraceSeconds + ";"
- );
- log.debug("Creating table six_hour_metrics");
- session.execute(
- "CREATE TABLE rhq.six_hour_metrics (" +
- "schedule_id int, " +
- "time timestamp, " +
- "type int, " +
- "value double, " +
- "PRIMARY KEY (schedule_id, time, type) " +
- ") WITH COMPACT STORAGE AND gc_grace_seconds = " + gcGraceSeconds + ";"
- );
- log.debug("Creating table twenty_four_hour_metrics");
- session.execute(
- "CREATE TABLE rhq.twenty_four_hour_metrics (" +
- "schedule_id int, " +
- "time timestamp, " +
- "type int, " +
- "value double, " +
- "PRIMARY KEY (schedule_id, time, type) " +
- ") WITH COMPACT STORAGE AND gc_grace_seconds = " + gcGraceSeconds + ";"
- );
- log.debug("Creating table metrics_index");
- session.execute(
- "CREATE TABLE rhq.metrics_index (" +
- "bucket varchar, " +
- "time timestamp, " +
- "schedule_id int, " +
- "PRIMARY KEY ((bucket, time), schedule_id) " +
- ") WITH COMPACT STORAGE AND gc_grace_seconds = " + gcGraceSeconds + ";"
- );
- } catch (NoHostAvailableException e) {
- throw new RuntimeException(e);
+ return parsedNodes;
+ }
+
+ private void initCluster() throws NoHostAvailableException {
+ String[] hostNames = new String[nodes.size()];
+ for (int i = 0; i < hostNames.length; ++i) {
+ hostNames[i] = nodes.get(i).getAddress();
}
+
+ log.info("Initializing session to connect to " + StringUtil.arrayToString(hostNames));
+
+ Cluster cluster = new ClusterBuilder().addContactPoints(hostNames).withCredentials(username, password)
+ .withPort(nodes.get(0).getCqlPort()).withCompression(Compression.NONE).build();
+
+ log.info("Cluster connection configured.");
+
+ session = cluster.connect("system");
+ log.info("Cluster connected.");
}
- public void shutdown() {
+ private void shutdown() {
log.info("Shutting down connections");
session.getCluster().shutdown();
}
- public static void main(String[] args) {
- if (args.length < 3) {
- System.out.println("Usage : command username password nodes...");
- System.out.println("\n");
- System.out.println("Commands : createSchema | dropSchema | resetSchema");
- System.out.println("Node format: hostname|thriftPort|nativeTransportPort");
+ public static void main(String[] args) throws Exception {
+ try {
+ Logger root = Logger.getRootLogger();
+ if (!root.getAllAppenders().hasMoreElements()) {
+ root.addAppender(new ConsoleAppender(new PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)));
+ }
+ Logger migratorLogging = root.getLoggerRepository().getLogger("org.rhq");
+ migratorLogging.setLevel(Level.ALL);
- return;
- }
+ if (args.length < 4) {
+ System.out.println("Usage : command username password nodes...");
+ System.out.println("\n");
+ System.out.println("Commands : install | drop ");
+ System.out.println("Node format: hostname|thriftPort|nativeTransportPort");
- String command = args[0];
- String username = args[1];
- String password = args[2];
+ return;
+ }
- SchemaManager schemaManager = new SchemaManager(username, password, Arrays.copyOfRange(args, 3, args.length));
+ String command = args[0];
+ String username = args[1];
+ String password = args[2];
- if ("createSchema".equalsIgnoreCase(command)) {
- schemaManager.createSchema();
+ System.out.println(args[3]);
- } else if ("dropSchema".equalsIgnoreCase(command)) {
- schemaManager.dropSchema();
+ SchemaManager schemaManager = new SchemaManager(username, password,
+ Arrays.copyOfRange(args, 3, args.length));
- } else if ("resetSchema".equalsIgnoreCase(command)) {
- schemaManager.resetSchema();
+ System.out.println(command);
+ if ("install".equalsIgnoreCase(command)) {
+ schemaManager.install();
+ } else if ("drop".equalsIgnoreCase(command)) {
+ schemaManager.drop();
+ } else {
+ throw new IllegalArgumentException(command + " not available.");
+ }
+ } catch (Exception e) {
+ System.err.println(e);
+ } finally {
+ System.exit(0);
}
}
diff --git a/modules/common/cassandra-schema/src/main/resources/changelog.xml b/modules/common/cassandra-schema/src/main/resources/changelog.xml
deleted file mode 100644
index b7171c2..0000000
--- a/modules/common/cassandra-schema/src/main/resources/changelog.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<databaseChangeLog
- xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
- xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
- http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.0.xsd">
-
- <changeSet id="1" author="jsanda" runInTransaction="false">
- <sql>
- CREATE TABLE rhq.raw_metrics (
- schedule_id int,
- time timestamp,
- value double,
- PRIMARY KEY (schedule_id, time)
- ) WITH COMPACT STORAGE;
-
- CREATE TABLE rhq.one_hour_metrics (
- schedule_id int,
- time timestamp,
- type int,
- value double,
- PRIMARY KEY (schedule_id, time, type)
- ) WITH COMPACT STORAGE;
-
- CREATE TABLE rhq.six_hour_metrics (
- schedule_id int,
- time timestamp,
- type int,
- value double,
- PRIMARY KEY (schedule_id, time, type)
- ) WITH COMPACT STORAGE;
-
- CREATE TABLE rhq.twenty_four_hour_metrics (
- schedule_id int,
- time timestamp,
- type int,
- value double,
- PRIMARY KEY (schedule_id, time, type)
- ) WITH COMPACT STORAGE;
-
- CREATE TABLE rhq.metrics_index (
- bucket varchar,
- time timestamp,
- schedule_id int,
- null_col boolean,
- PRIMARY KEY (bucket, time, schedule_id)
- ) WITH COMPACT STORAGE;
- </sql>
- </changeSet>
-
-</databaseChangeLog>
\ No newline at end of file
diff --git a/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml b/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml
new file mode 100644
index 0000000..744bf60
--- /dev/null
+++ b/modules/common/cassandra-schema/src/main/resources/schema/create/0001.xml
@@ -0,0 +1,18 @@
+<updatePlan>
+ <step>
+ CREATE USER rhqadmin WITH PASSWORD 'rhqadmin' SUPERUSER;
+ </step>
+
+ <step>
+ CREATE KEYSPACE rhq WITH
+ replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
+ </step>
+
+ <step>
+ CREATE TABLE rhq.schema_version (
+ version int,
+ time timestamp,
+ PRIMARY KEY (version, time)
+ ) WITH COMPACT STORAGE;
+ </step>
+</updatePlan>
\ No newline at end of file
diff --git a/modules/common/cassandra-schema/src/main/resources/schema/drop/0001.xml b/modules/common/cassandra-schema/src/main/resources/schema/drop/0001.xml
new file mode 100644
index 0000000..b826965
--- /dev/null
+++ b/modules/common/cassandra-schema/src/main/resources/schema/drop/0001.xml
@@ -0,0 +1,10 @@
+<updatePlan>
+ <step>
+ DROP KEYSPACE rhq;
+ </step>
+
+ <step>
+ DROP USER rhqadmin;
+ </step>
+
+</updatePlan>
\ No newline at end of file
diff --git a/modules/common/cassandra-schema/src/main/resources/schema/update/0001.xml b/modules/common/cassandra-schema/src/main/resources/schema/update/0001.xml
new file mode 100644
index 0000000..7fdca3a
--- /dev/null
+++ b/modules/common/cassandra-schema/src/main/resources/schema/update/0001.xml
@@ -0,0 +1,49 @@
+<updatePlan>
+ <step>
+ CREATE TABLE rhq.raw_metrics (
+ schedule_id int,
+ time timestamp,
+ value double,
+ PRIMARY KEY (schedule_id, time)
+ ) WITH COMPACT STORAGE;
+ </step>
+
+ <step>
+ CREATE TABLE rhq.one_hour_metrics (
+ schedule_id int,
+ time timestamp,
+ type int,
+ value double,
+ PRIMARY KEY (schedule_id, time, type)
+ ) WITH COMPACT STORAGE;
+ </step>
+
+ <step>
+ CREATE TABLE rhq.six_hour_metrics (
+ schedule_id int,
+ time timestamp,
+ type int,
+ value double,
+ PRIMARY KEY (schedule_id, time, type)
+ ) WITH COMPACT STORAGE;
+ </step>
+
+ <step>
+ CREATE TABLE rhq.twenty_four_hour_metrics (
+ schedule_id int,
+ time timestamp,
+ type int,
+ value double,
+ PRIMARY KEY (schedule_id, time, type)
+ ) WITH COMPACT STORAGE;
+ </step>
+
+ <step>
+ CREATE TABLE rhq.metrics_index (
+ bucket varchar,
+ time timestamp,
+ schedule_id int,
+ PRIMARY KEY ((bucket, time), schedule_id)
+ ) WITH COMPACT STORAGE;
+ </step>
+</updatePlan>
\ No newline at end of file
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 11eb831..06cf148 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -162,7 +162,7 @@
</plugin>
</plugins>
</build>
-
+
<profiles>
<profile>
<id>db.dev</id>
@@ -172,7 +172,7 @@
<value>dev</value>
</property>
</activation>
-
+
<!-- these are defined in the dev profile also - see below in that profile for why -->
<properties>
<rhq.ds.type-mapping>${rhq.dev.ds.type-mapping}</rhq.ds.type-mapping>
@@ -185,7 +185,7 @@
<rhq.ds.driver-class>${rhq.dev.ds.driver-class}</rhq.ds.driver-class>
</properties>
</profile>
-
+
<profile>
<id>latest</id>
<activation>
@@ -283,7 +283,14 @@
seeds = project.getProperty('rhq.dev.cassandra.seeds') ?: "127.0.0.1|7199|9142"
schemaManager = new SchemaManager(username, password, seeds)
- schemaManager.resetSchema()
+
+ if (project.getProperty('dbreset') == 'true') {
+ self.log('Dropping schema')
+ schemaManager.drop()
+ }
+
+ self.log('Install schema')
+ schemaManager.install()
} else {
self.log('SKIPPING SCHEMA SETUP FOR STORAGE NODE')
}
@@ -369,7 +376,7 @@
</plugins>
</build>
</profile>
-
+
<profile>
<id>jon.release</id>
<activation>
@@ -416,7 +423,7 @@
</plugins>
</build>
</profile>
-
+
<profile>
<id>dev</id>
<properties>
@@ -476,7 +483,7 @@
</plugins>
</build>
</profile>
-
+
<profile>
<id>ojdbc-driver</id>
<dependencies>
@@ -489,7 +496,7 @@
<scope>compile</scope>
</dependency>
</dependencies>
-
+
<!-- TODO: defer to root pom version when we can agree on a version -->
<build>
<plugins>
@@ -501,7 +508,7 @@
</build>
</profile>
</profiles>
-
+
<pluginRepositories>
<pluginRepository>
<id>codehaus-snapshots</id>
diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
index 45240ed..99b0c3c 100644
--- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
+++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java
@@ -479,23 +479,13 @@ public class InstallerServiceImpl implements InstallerService {
try {
cassandraSchemaManager = createCassandraSchemaManager(serverProperties);
if (ExistingSchemaOption.SKIP != existingSchemaOptionEnum) {
- if (cassandraSchemaManager.schemaExists()) {
- log("Cassandra schema exists.");
- if (ExistingSchemaOption.OVERWRITE == existingSchemaOptionEnum) {
- log("Cassandra schema exists but installer was told to overwrite it - a new schema will be "
- + "created now.");
- cassandraSchemaManager.dropSchema();
- cassandraSchemaManager.createSchema();
-
- }
- log("Updating Cassandra schema.");
- cassandraSchemaManager.updateSchema();
- } else {
- log("Cassandra schema does not exist. It will be created now.");
- cassandraSchemaManager.createSchema();
- log("Applying schema updates to Cassandra.");
- cassandraSchemaManager.updateSchema();
+ if (ExistingSchemaOption.OVERWRITE == existingSchemaOptionEnum) {
+ log("Cassandra schema exists but installer was told to overwrite it - a the existing schema will be "
+ + "created now.");
+ cassandraSchemaManager.drop();
}
+ log("Install RHQ schema along with updates to Cassandra.");
+ cassandraSchemaManager.install();
} else {
log("Ignoring Cassandra schema - installer will assume it exists and is already up-to-date.");
}
@@ -503,10 +493,6 @@ public class InstallerServiceImpl implements InstallerService {
String msg = "Could not complete Cassandra schema installation: " + ThrowableUtil.getRootMessage(e);
log.error(msg, e);
throw new Exception(msg, e);
- } finally {
- if (cassandraSchemaManager != null) {
- cassandraSchemaManager.shutdown();
- }
}
// ensure the server info is up to date and stored in the DB
diff --git a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
index 3dacf23..bbf0c3b 100644
--- a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
+++ b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java
@@ -219,8 +219,7 @@ public class Simulator implements ShutdownManager {
try {
log.info("Creating schema");
SchemaManager schemaManager = new SchemaManager("cassandra", "cassandra", nodes);
- schemaManager.createSchema();
- schemaManager.updateSchema();
+ schemaManager.install();
} catch (Exception e) {
throw new RuntimeException("Failed to start simulator. An error occurred during schema creation.", e);
}
10 years, 11 months
[rhq] Changes to 'mtho11/dual-slider-chart-control'
by mike thompson
New branch 'mtho11/dual-slider-chart-control' available with the following commits:
commit aa0c43d4eddfaee9c9db7570f202e9fbd98d47d0
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 29 14:23:29 2013 -0700
Bug fixes on d3 graph brushes.
commit 95829908b86a7481304ab0a1d590a00af9631522
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 29 13:41:38 2013 -0700
Graph d3 brush slider is now on Graph and date button bar resembles that of logstash (logstalgia) style operation.
commit 894f0bee57579b1b370868d39ca36b743374e244
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 24 14:54:40 2013 -0700
Pull d3 Date slider and place into actual graph instead. Decision was made in UXD meeting today.
commit fdc5aff4f8286b2f7598ea316eaef0fdebc0f093
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 24 10:50:03 2013 -0700
Replace brushable availability graph with pure date slider - DateSliderGraphType
commit 8aa31b54ef3b4db63de41b88cfaad943f670c8d7
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Thu May 23 12:38:25 2013 -0700
Replace brushable availability graph with pure date slider - DateSliderGraphType
commit fffbbfdd54914d2ebf3e73a830c63db22ce4c0ec
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 22 11:41:28 2013 -0700
Look and Feel Tweaks.
commit 72efda3b93360c6679747bf0d0876cb5f18dd3ea
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 18:56:04 2013 -0700
Fix various behaviours between d3 slider and graphs.
commit 33dd256a7b3009e526f88dad85d7afb512c5a88f
Merge: 08d93a3 e5d22ca
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 13:23:26 2013 -0700
Merge branch 'master' into mtho11/dual-slider-chart-control
commit 08d93a34720c2b5ff23670e8b227738088eb6b31
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 12:31:26 2013 -0700
i18n the Button bar.
commit 0377aa5396cff78cdb91bb4a05bc12f153805d9e
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Tue May 21 10:23:58 2013 -0700
Fix some of button behavior for d3 slider implementation.
commit 8597564b99aec88785c8f1bc637b0da386408ad1
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Sun May 19 13:50:59 2013 -0700
Refresh charts using new javascript date slider.
commit d107481bd1bbe076cb0301e949fd401132c44e03
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 17 17:06:29 2013 -0700
Change charttype package to graph and also graphtype sub package.
commit 823c35fa92bb7dcccbe26ef1a9e53273f69d577b
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Fri May 17 15:57:55 2013 -0700
Add AvailabilityGraphType Generics.
commit 373cb38207d522166b433c35e7a110ccc8099840
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Wed May 15 14:49:18 2013 -0700
Remove jquery ui and replace with bootstrap.
commit dfdc5e6125cf405b2f6e54318fab2d76ca0f4f08
Author: Mike Thompson <mithomps(a)redhat.com>
Date: Mon May 13 19:34:47 2013 -0700
Add new jQuery stuff.
10 years, 11 months
[rhq] Branch 'feature/cassandra-backend' - 2 commits - modules/enterprise
by Jay Shaughnessy
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java | 8 +++++++-
modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java | 9 +++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
New commits:
commit 8d0d67ac570468da3d31806b10b2e4fa09807207
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed May 29 17:53:52 2013 -0400
Make sure our injected cassandra vm alert template has its relevant
metric enabled and reported frequently.
diff --git a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
index 8704203..ff4ee43 100644
--- a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
+++ b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java
@@ -43,6 +43,7 @@ import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
import org.rhq.enterprise.server.alert.AlertTemplateManagerLocal;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.plugin.pc.ControlFacet;
import org.rhq.enterprise.server.plugin.pc.ControlResults;
import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
@@ -257,6 +258,14 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone
int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
resourceType.getId());
+ // additionally, we want to ensure that the metric is enabled and collecting at a more frequent interval than
+ // is set by default.
+ MeasurementScheduleManagerLocal measurementManager = LookupUtil.getMeasurementScheduleManager();
+ int[] measurementDefinitionIds = new int[1];
+ measurementDefinitionIds[0] = ac.getMeasurementDefinition().getId();
+ measurementManager.updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(
+ subjectManager.getOverlord(), measurementDefinitionIds, 60000L, true, true);
+
return newTemplateId;
}
commit 160a6fabeea18fd7410560a8f00206736997adb9
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed May 29 17:53:07 2013 -0400
Fix an issue with alert template application to discovered resources. The
root cause has to do with sending attached entities across Tx boundaries:
org.hibernate.HibernateException:
illegally attempted to associate a proxy with two open Sessions
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
index 1f8d4e9..2f13b24 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
@@ -48,6 +48,8 @@ import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.resource.ResourceTypeNotFoundException;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility;
+import org.rhq.enterprise.server.safeinvoker.HibernateDetachUtility.SerializationType;
/**
* @author Joseph Marques
@@ -183,12 +185,16 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
List<AlertDefinition> unappliedTemplates = query.getResultList();
for (AlertDefinition template : unappliedTemplates) {
- // construct the child
+ // construct the child, note that the proxy will pull in lazy data during the copy
AlertDefinition childAlertDefinition = new AlertDefinition(template);
childAlertDefinition.setParentId(template.getId());
// persist the child, user is known to be overlord at this point for this system side-effect
try {
+ // convert the childAlertDef to a pojo, remove all proxies left over from the copy. We can't
+ // pass entities across a Tx boundary and the call to create the alert def is executed in a new trans.
+ HibernateDetachUtility
+ .nullOutUninitializedFields(childAlertDefinition, SerializationType.SERIALIZATION);
alertDefinitionManager.createAlertDefinitionInNewTransaction(user, childAlertDefinition, resourceId,
false);
} catch (Throwable t) {
10 years, 11 months
[rhq] Branch 'feature/cassandra-backend' - modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java | 5
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java | 19 ---
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/NewDefinitionAction.java | 8 -
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBeanTest.java | 18 +--
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionWithComplexNotificationsTest.java | 7 -
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java | 20 +--
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerTest.java | 8 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java | 56 ++++------
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java | 28 -----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java | 25 ++--
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java | 8 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java | 6 -
13 files changed, 86 insertions(+), 124 deletions(-)
New commits:
commit be19836c7aedaa1e912bb391dd2bc96aeec46a19
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Wed May 29 15:24:14 2013 -0400
Get rid of the unnecessary and mispelled local method
AlertDefinitionManagerBean.createAlertDefinitionAndRerurnIt().
It's value was that it returned the created alert def as opposed to just
the id of the alert def. So, instead, have
AlertDefinitionManagerBean.createAlertDefinitionInNewTransaction() return
the AlertDefinition as opposed to the id.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
index d69f7f4..4f71b9c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/ResourceAlertDefinitionsView.java
@@ -197,7 +197,7 @@ public class ResourceAlertDefinitionsView extends AbstractAlertDefinitionsView {
protected void commitAlertDefinition(final AlertDefinition alertDefinition, boolean purgeInternals,
final AsyncCallback<AlertDefinition> resultReceiver) {
if (alertDefinition.getId() == 0) {
- GWTServiceLookup.getAlertDefinitionService().createAlertDefinitionAndReturn(alertDefinition,
+ GWTServiceLookup.getAlertDefinitionService().createAlertDefinition(alertDefinition,
Integer.valueOf(resource.getId()), new AsyncCallback<AlertDefinition>() {
@Override
public void onSuccess(AlertDefinition result) {
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
index 794a67f..c95fba0 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AlertDefinitionGWTService.java
@@ -30,10 +30,7 @@ public interface AlertDefinitionGWTService extends RemoteService {
PageList<AlertDefinition> findAlertDefinitionsByCriteria(AlertDefinitionCriteria criteria) throws RuntimeException;
- int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException;
-
- AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId)
- throws RuntimeException;
+ AlertDefinition createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException;
AlertDefinition updateAlertDefinition(int alertDefinitionId, AlertDefinition alertDefinition, boolean purgeInternals)
throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
index da1d981..34929b2 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
@@ -29,7 +29,6 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.gwt.AlertDefinitionGWTService;
import org.rhq.enterprise.gui.coregui.server.util.SerialUtility;
-import org.rhq.enterprise.server.alert.AlertConditionManagerLocal;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -64,20 +63,12 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
}
@Override
- public int createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
- try {
- int result = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(), alertDefinition, resourceId, true);
- return result;
- } catch (Throwable t) {
- throw getExceptionToThrowToClient(t);
- }
- }
-
- @Override
- public AlertDefinition createAlertDefinitionAndReturn(AlertDefinition alertDefinition, Integer resourceId) throws RuntimeException {
+ public AlertDefinition createAlertDefinition(AlertDefinition alertDefinition, Integer resourceId)
+ throws RuntimeException {
try {
- AlertDefinition result = alertDefManager.createAlertDefinitionAndRerurnIt(getSessionSubject(), alertDefinition, resourceId, true);
- return SerialUtility.prepare(result, "createAlertDefinitionAndReturn");
+ AlertDefinition result = alertDefManager.createAlertDefinitionInNewTransaction(getSessionSubject(),
+ alertDefinition, resourceId, true);
+ return SerialUtility.prepare(result, "createAlertDefinition");
} catch (Throwable t) {
throw getExceptionToThrowToClient(t);
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/NewDefinitionAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/NewDefinitionAction.java
index 4ade28d..8834f4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/NewDefinitionAction.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/config/NewDefinitionAction.java
@@ -92,12 +92,14 @@ public class NewDefinitionAction extends BaseAction {
alertDefinitionId = alertTemplateManager.createAlertTemplate(subject, alertDef, defForm.getType());
} else if (context == FormContext.Resource) {
AlertDefinitionManagerLocal alertDefinitionManager = LookupUtil.getAlertDefinitionManager();
- alertDefinitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(subject, alertDef, defForm.getId(), true);
+ AlertDefinition alertDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(subject,
+ alertDef, defForm.getId(), true);
+ alertDefinitionId = alertDefinition.getId();
} else if (context == FormContext.Group) {
GroupAlertDefinitionManagerLocal groupAlertDefinitionManager = LookupUtil
.getGroupAlertDefinitionManager();
- alertDefinitionId = groupAlertDefinitionManager.createGroupAlertDefinitions(subject, alertDef, defForm
- .getGroupId());
+ alertDefinitionId = groupAlertDefinitionManager.createGroupAlertDefinitions(subject, alertDef,
+ defForm.getGroupId());
} else {
throw new IllegalArgumentException("Unsupported context: " + context);
}
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBeanTest.java
index 5e40380..b9455a2 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBeanTest.java
@@ -334,10 +334,10 @@ public class AlertDefinitionManagerBeanTest extends AbstractEJB3Test {
alertDefinition.setConditionExpression(BooleanExpression.ANY);
alertDefinition.setRecoveryId(0);
alertDefinition.setEnabled(enabled);
- int alertDefinitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(testData.getSubject(),
+ alertDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(testData.getSubject(),
alertDefinition, testData.getResource().getId(), true);
- testData.getAlertDefinitionIds().add(alertDefinitionId);
- return alertDefinitionId;
+ testData.getAlertDefinitionIds().add(alertDefinition.getId());
+ return alertDefinition.getId();
}
private int createGroupAlertDefinitionAndGetId(String name) {
@@ -349,7 +349,7 @@ public class AlertDefinitionManagerBeanTest extends AbstractEJB3Test {
alertDefinition.setRecoveryId(0);
alertDefinition.setGroup(testData.getResourceGroup());
alertDefinition.setEnabled(true);
-
+
// We need a threshold alert condition to recreate the issue in bug 949048
AlertCondition ac = new AlertCondition();
ac.setCategory(AlertConditionCategory.THRESHOLD);
@@ -357,11 +357,11 @@ public class AlertDefinitionManagerBeanTest extends AbstractEJB3Test {
ac.setComparator("<");
ac.setThreshold(0.5);
alertDefinition.addCondition(ac);
-
- int alertDefinitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(testData.getSubject(),
- alertDefinition, null, true);
- testData.getAlertDefinitionIds().add(alertDefinitionId);
- return alertDefinitionId;
+
+ AlertDefinition newAlertDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(
+ testData.getSubject(), alertDefinition, null, true);
+ testData.getAlertDefinitionIds().add(newAlertDefinition.getId());
+ return newAlertDefinition.getId();
}
private static final class TestData {
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionWithComplexNotificationsTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionWithComplexNotificationsTest.java
index fbbc86a..be62ad8 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionWithComplexNotificationsTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/AlertDefinitionWithComplexNotificationsTest.java
@@ -413,14 +413,13 @@ public class AlertDefinitionWithComplexNotificationsTest extends AbstractEJB3Tes
false);
def.setResource(resources.iterator().next());
- int id = adm.createAlertDefinitionInNewTransaction(subject, def, res.getId(), true);
- def.setId(id);
+ def = adm.createAlertDefinitionInNewTransaction(subject, def, res.getId(), true);
- resourceLevelAlertDefinitionId = id;
+ resourceLevelAlertDefinitionId = def.getId();
junk.add(def);
- testMainAlertDefinition(id);
+ testMainAlertDefinition(resourceLevelAlertDefinitionId);
}
//@Test(dependsOnMethods = { "testNotificationsCopiedOnAlertTemplateApplication",
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
index 159a56d..3797542 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java
@@ -470,8 +470,8 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
alertDefinition.setConditions(conditions);
AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
- int defId = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resourceId, true);
- alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ alertDefinition = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition,
+ resourceId, true);
assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ alertDefinition;
@@ -504,8 +504,8 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
alertDefinition.setConditions(conditions);
AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
- int defId = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resourceId, true);
- alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ alertDefinition = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition,
+ resourceId, true);
assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ alertDefinition;
@@ -537,8 +537,8 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
alertDefinition.setConditions(conditions);
AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
- int defId = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resourceId, true);
- alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ alertDefinition = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition,
+ resourceId, true);
assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ alertDefinition;
@@ -570,8 +570,8 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
alertDefinition.setConditions(conditions);
AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
- int defId = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resourceId, true);
- alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ alertDefinition = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition,
+ resourceId, true);
assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ alertDefinition;
@@ -604,8 +604,8 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase {
alertDefinition.setConditions(conditions);
AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
- int defId = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resourceId, true);
- alertDefinition = alertDefManager.getAlertDefinition(getOverlord(), defId); // load it back so we get its ID and all condition IDs
+ alertDefinition = alertDefManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition,
+ resourceId, true);
assert alertDefinition != null && alertDefinition.getId() > 0 : "did not persist alert def properly: "
+ alertDefinition;
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerTest.java
index af045ca..146ee20 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertManagerTest.java
@@ -303,10 +303,10 @@ public class AlertManagerTest extends AbstractEJB3Test {
alertDefinition.setConditionExpression(BooleanExpression.ANY);
alertDefinition.setRecoveryId(0);
alertDefinition.setEnabled(true);
- int alertDefinitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(testData.getSubject(), alertDefinition,
- testData.getResource().getId(), true);
- testData.setAlertDefinitionId(alertDefinitionId);
- return alertDefinitionId;
+ alertDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(testData.getSubject(),
+ alertDefinition, testData.getResource().getId(), true);
+ testData.setAlertDefinitionId(alertDefinition.getId());
+ return alertDefinition.getId();
}
private static final class TestData {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
index 8f8fec5..fc3b1ea 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerBean.java
@@ -208,23 +208,16 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition,
- Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
- AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
- validateNotificationConfiguration);
- return newAlertDefinition.getId();
- }
-
- @Override
- @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
+ public AlertDefinition createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition,
Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
AlertDefinition newAlertDefinition = createAlertDefinitionInternal(subject, alertDefinition, resourceId, true,
validateNotificationConfiguration);
return newAlertDefinition;
}
- private AlertDefinition createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException {
+ private AlertDefinition createAlertDefinitionInternal(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean checkPerms, boolean validateNotificationConfiguration)
+ throws InvalidAlertDefinitionException {
checkAlertDefinition(subject, null, alertDefinition, resourceId, validateNotificationConfiguration);
// if this is an resource alert definition, set up the link to a resource
@@ -245,8 +238,7 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
+ alertDefinition.getResourceType() + "]");
} else if (alertDefinition.getGroup() != null) {
throw new PermissionException("User [" + subject.getName()
- + "] does not have permission to create alert definitions for group ["
- + alertDefinition.getGroup()
+ + "] does not have permission to create alert definitions for group [" + alertDefinition.getGroup()
+ "]");
} else {
throw new PermissionException("User [" + subject.getName()
@@ -275,8 +267,8 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
if (alertDefinition.getRecoveryId() != 0) {
// only add to the cache if the to-be-recovered definition is disabled, and thus needs recovering
// use entityManager direct to bypass security checks, we already know this user is authorized
- AlertDefinition toBeRecoveredDefinition = entityManager.find(AlertDefinition.class, alertDefinition
- .getRecoveryId());
+ AlertDefinition toBeRecoveredDefinition = entityManager.find(AlertDefinition.class,
+ alertDefinition.getRecoveryId());
if (toBeRecoveredDefinition.getEnabled() == false) {
addToCache = true;
}
@@ -486,15 +478,16 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public AlertDefinition updateDependentAlertDefinition(Subject subject, int alertDefinitionId, AlertDefinition alertDefinition, boolean resetMatching) throws InvalidAlertDefinitionException, AlertDefinitionUpdateException {
+ public AlertDefinition updateDependentAlertDefinition(Subject subject, int alertDefinitionId,
+ AlertDefinition alertDefinition, boolean resetMatching) throws InvalidAlertDefinitionException,
+ AlertDefinitionUpdateException {
return updateAlertDefinitionInternal(subject, alertDefinitionId, alertDefinition, resetMatching, false, false);
}
@Override
public AlertDefinition updateAlertDefinitionInternal(Subject subject, int alertDefinitionId,
- AlertDefinition alertDefinition, boolean resetMatching,
- boolean checkPerms, boolean finalizeNotifications) throws InvalidAlertDefinitionException,
- AlertDefinitionUpdateException {
+ AlertDefinition alertDefinition, boolean resetMatching, boolean checkPerms, boolean finalizeNotifications)
+ throws InvalidAlertDefinitionException, AlertDefinitionUpdateException {
if (resetMatching) {
alertDefinitionManager.purgeInternals(alertDefinitionId);
}
@@ -527,8 +520,8 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
*/
boolean isResourceLevel = (oldAlertDefinition.getResource() != null);
- checkAlertDefinition(subject, oldAlertDefinition, alertDefinition, isResourceLevel ? oldAlertDefinition.getResource().getId()
- : null, finalizeNotifications);
+ checkAlertDefinition(subject, oldAlertDefinition, alertDefinition, isResourceLevel ? oldAlertDefinition
+ .getResource().getId() : null, finalizeNotifications);
/*
* Should not be able to update an alert definition if the old alert definition is in an invalid state
@@ -594,8 +587,8 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
// if this was a recovery alert, or was recently turned into one
if (newAlertDefinition.getRecoveryId() != 0) {
// only add to the cache if the to-be-recovered definition is disabled, and thus needs recovering
- AlertDefinition toBeRecoveredDefinition = getAlertDefinitionById(subject, newAlertDefinition
- .getRecoveryId());
+ AlertDefinition toBeRecoveredDefinition = getAlertDefinitionById(subject,
+ newAlertDefinition.getRecoveryId());
if (toBeRecoveredDefinition.getEnabled() == false) {
addToCache = true;
}
@@ -646,7 +639,8 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
}
}
- private void checkAlertDefinition(Subject subject, AlertDefinition persistedAlertDefinition, AlertDefinition alertDefinition, Integer resourceId, boolean finalizeNotifications)
+ private void checkAlertDefinition(Subject subject, AlertDefinition persistedAlertDefinition,
+ AlertDefinition alertDefinition, Integer resourceId, boolean finalizeNotifications)
throws InvalidAlertDefinitionException {
// if someone enters a really long description, we need to truncate it - the column is only 250 chars
if (alertDefinition.getDescription() != null && alertDefinition.getDescription().length() > 250) {
@@ -675,11 +669,13 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
}
if (finalizeNotifications) {
- List<AlertNotification> notifications = new ArrayList<AlertNotification>(alertDefinition.getAlertNotifications());
+ List<AlertNotification> notifications = new ArrayList<AlertNotification>(
+ alertDefinition.getAlertNotifications());
//now remove the notifications that have not changed
if (persistedAlertDefinition != null) {
- List<AlertNotification> persistedNotifications = persistedAlertDefinition.getAlertNotifications() == null ? Collections.<AlertNotification>emptyList() : persistedAlertDefinition.getAlertNotifications();
+ List<AlertNotification> persistedNotifications = persistedAlertDefinition.getAlertNotifications() == null ? Collections
+ .<AlertNotification> emptyList() : persistedAlertDefinition.getAlertNotifications();
if (persistedNotifications.size() > 0) {
Iterator<AlertNotification> it = notifications.iterator();
@@ -691,10 +687,11 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
continue;
}
- for(AlertNotification persistedNotification : persistedNotifications) {
+ for (AlertNotification persistedNotification : persistedNotifications) {
//ignore the ids on the notifications as they may vary if we are comparing parent alert def with its children
//it's enough for us they they are semantically the same.
- if (newNotification.getSenderName().equals(persistedNotification.getSenderName()) && newNotification.equalsData(persistedNotification)) {
+ if (newNotification.getSenderName().equals(persistedNotification.getSenderName())
+ && newNotification.equalsData(persistedNotification)) {
it.remove();
break;
}
@@ -802,7 +799,8 @@ public class AlertDefinitionManagerBean implements AlertDefinitionManagerLocal,
generator.setAuthorizationResourceFragment(tokenType, subject.getId());
}
- CriteriaQueryRunner<AlertDefinition> queryRunner = new CriteriaQueryRunner<AlertDefinition>(criteria, generator, entityManager);
+ CriteriaQueryRunner<AlertDefinition> queryRunner = new CriteriaQueryRunner<AlertDefinition>(criteria,
+ generator, entityManager);
return queryRunner.execute();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
index ee0e161..5d5711e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertDefinitionManagerLocal.java
@@ -60,36 +60,14 @@ public interface AlertDefinitionManagerLocal {
* This would then cause the validation to fail every time you created a copy of a definition and tried
* to persist it. Note that passing false AND having new, unpersisted notifications in the alert definition can
* lead to invalid configuration being stored for the notifications.
- * @return the id of the newly persisted alert definition
+ * @return the newly persisted alert definition
* @throws InvalidAlertDefinitionException
*/
- int createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition, Integer resourceId, boolean finalizeNotificationConfiguration)
+ AlertDefinition createAlertDefinitionInNewTransaction(Subject subject, AlertDefinition alertDefinition,
+ Integer resourceId, boolean finalizeNotificationConfiguration)
throws InvalidAlertDefinitionException;
/**
- * Creates a new alert definition. Note that the suject is checked to have necessary authz, which might not
- * be what you want in all use cases. See {@link #createDependentAlertDefinition(Subject, AlertDefinition, int)}
- * for further discussion of this. The only difference between
- * {@link GroupAlertDefinitionManagerLocal#createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)}
- * and this method is the return type.
- *
- * @param subject the user creating the alert definition
- * @param alertDefinition the new alert definition to persist
- * @param resourceId the resource id for which the def is being created
- * @param finalizeNotificationConfiguration if true, the configuration of the def's notifications is validated.
- * This is NOT what you want if, for example, you are merely creating a copy of an existing definition.
- * Some notifications might require more input when creating the notification than is then persisted in their configs
- * (prominent example being the CLI alert sender).
- * This would then cause the validation to fail every time you created a copy of a definition and tried
- * to persist it. Note that passing false AND having new, unpersisted notifications in the alert definition can
- * lead to invalid configuration being stored for the notifications.
- * @return the instance of newly created alert definition
- * @throws InvalidAlertDefinitionException
- */
- AlertDefinition createAlertDefinitionAndRerurnIt(Subject subject, AlertDefinition alertDefinition,
- Integer resourceId, boolean validateNotificationConfiguration) throws InvalidAlertDefinitionException;
-
- /**
* This is exactly the same as {@link #createAlertDefinitionInNewTransaction(Subject, AlertDefinition, Integer, boolean)} but
* assumes the resource is part of a group (or has given resource type for templates) for which
* a group or template alert definition is being created.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
index ee7bbf0..1f8d4e9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertTemplateManagerBean.java
@@ -118,24 +118,22 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
}
ResourceType type = resourceTypeManager.getResourceTypeById(user, resourceTypeId);
-
+
alertTemplate.setResourceType(type); // mark this as an alert "template" definition
- int alertTemplateId = 0;
+ AlertDefinition persistedAlertTemplate = null;
try {
- alertTemplateId = alertDefinitionManager.createAlertDefinitionInNewTransaction(user, alertTemplate, null, true);
+ persistedAlertTemplate = alertDefinitionManager.createAlertDefinitionInNewTransaction(user, alertTemplate,
+ null, true);
} catch (Throwable t) {
throw new AlertDefinitionCreationException("Could not create alertTemplate for " + type + " with data "
+ alertTemplate.toSimpleString(), t);
}
- //get the alert definition we just created.. this is so that we can create copies of it
- AlertDefinition persistedAlertTemplate = alertDefinitionManager.getAlertDefinition(user, alertTemplateId);
-
Throwable firstThrowable = null;
- List<Integer> resourceIdsForType = getCommittedResourceIdsNeedingTemplateApplication(user, alertTemplateId,
- resourceTypeId);
+ List<Integer> resourceIdsForType = getCommittedResourceIdsNeedingTemplateApplication(user,
+ persistedAlertTemplate.getId(), resourceTypeId);
List<Integer> resourceIdsInError = new ArrayList<Integer>();
for (Integer resourceId : resourceIdsForType) {
try {
@@ -158,7 +156,7 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
+ resourceIdsInError + " with template" + alertTemplate.toSimpleString(), firstThrowable);
}
- return alertTemplateId;
+ return persistedAlertTemplate.getId();
}
@SuppressWarnings("unchecked")
@@ -191,7 +189,8 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
// persist the child, user is known to be overlord at this point for this system side-effect
try {
- alertDefinitionManager.createAlertDefinitionInNewTransaction(user, childAlertDefinition, resourceId, false);
+ alertDefinitionManager.createAlertDefinitionInNewTransaction(user, childAlertDefinition, resourceId,
+ false);
} catch (Throwable t) {
throw new AlertDefinitionCreationException("Failed to create child AlertDefinition for Resource[id="
+ resourceId + "] with template " + template.toSimpleString());
@@ -262,8 +261,7 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
List<Integer> alertDefinitionIdsInError = new ArrayList<Integer>();
for (Integer alertDefinitionId : alertDefinitions) {
try {
- alertDefinitionManager
- .updateDependentAlertDefinition(user, alertDefinitionId, updated, resetMatching);
+ alertDefinitionManager.updateDependentAlertDefinition(user, alertDefinitionId, updated, resetMatching);
} catch (Throwable t) {
// continue on error, update as many as possible
if (firstThrowable == null) {
@@ -287,7 +285,8 @@ public class AlertTemplateManagerBean implements AlertTemplateManagerLocal {
childAlertDefinition.setParentId(alertTemplate.getId());
// persist the child
- alertDefinitionManager.createAlertDefinitionInNewTransaction(overlord, childAlertDefinition, resourceId, false);
+ alertDefinitionManager.createAlertDefinitionInNewTransaction(overlord, childAlertDefinition,
+ resourceId, false);
} catch (Throwable t) {
// continue on error, update as many as possible
if (firstThrowable == null) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
index ef6770e..6f322ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/GroupAlertDefinitionManagerBean.java
@@ -146,19 +146,17 @@ public class GroupAlertDefinitionManagerBean implements GroupAlertDefinitionMana
ResourceGroup group = resourceGroupManager.getResourceGroupById(subject, resourceGroupId, null);
groupAlertDefinition.setGroup(group);
+ AlertDefinition persistedDefinition = null;
int groupAlertDefinitionId = 0;
try {
- groupAlertDefinitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(subject,
+ persistedDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(subject,
groupAlertDefinition, null, true);
+ groupAlertDefinitionId = persistedDefinition.getId();
} catch (Throwable t) {
throw new AlertDefinitionCreationException("Could not create groupAlertDefinitions for " + group
+ " with data " + groupAlertDefinition.toSimpleString(), t);
}
- //get the alert definition we just created.. this is so that we can create copies of it
- AlertDefinition persistedDefinition = alertDefinitionManager
- .getAlertDefinition(subject, groupAlertDefinitionId);
-
Throwable firstThrowable = null;
List<Integer> resourceIdsForGroup = getCommittedResourceIdsNeedingGroupAlertDefinitionApplication(subject,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
index 305d867..b0be87c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/rest/AlertDefinitionHandlerBean.java
@@ -279,9 +279,9 @@ public class AlertDefinitionHandlerBean extends AbstractRestBean {
throw new StuffNotFoundException("Recovery alert with id " + adr.getRecoveryId());
}
- int definitionId = alertDefinitionManager.createAlertDefinitionInNewTransaction(caller, alertDefinition, resourceId, false);
-
- AlertDefinition updatedDefinition = alertDefinitionManager.getAlertDefinition(caller,definitionId);
+ AlertDefinition updatedDefinition = alertDefinitionManager.createAlertDefinitionInNewTransaction(caller,
+ alertDefinition, resourceId, false);
+ int definitionId = updatedDefinition.getId();
AlertDefinitionRest uadr = definitionToDomain(updatedDefinition,true, uriInfo) ; // TODO param 'full' ?
uadr.setId(definitionId);
10 years, 11 months
[rhq] Branch 'feature/cassandra-backend' - modules/enterprise
by John Sanda
modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java | 17 ++++++++++
1 file changed, 17 insertions(+)
New commits:
commit c0110f46915f697dc4bb894bf6433facffa8c0e1
Author: John Sanda <jsanda(a)redhat.com>
Date: Wed May 29 10:52:14 2013 -0400
try to deal with async raw inserts
Raw data is now inserted asynchronously. Tests in the itests-2 module lack a good way,
short of adding test-specific hooks into production code, for blocking or getting notified
when inserts have finished. This commit provides a temporary work around.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
index 163a61b..63cb23d 100644
--- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
+++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java
@@ -166,6 +166,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
report.addData(new MeasurementDataNumeric(buckets.get(59) + 30, request, 6.6));
dataManager.mergeMeasurementReport(report);
+ waitForRawInserts();
List<MeasurementDataNumericHighLowComposite> actualData = findDataForContext(overlord,
EntityContext.forResource(resource.getId()), dynamicSchedule, beginTime.getMillis(), endTime.getMillis());
@@ -210,6 +211,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
report.addData(new MeasurementDataNumeric(buckets.get(59) + 30, request, 6.6));
dataManager.mergeMeasurementReport(report);
+ waitForRawInserts();
MeasurementAggregate actual = dataManager.getAggregate(overlord, dynamicSchedule.getId(),
beginTime.getMillis(), endTime.getMillis());
@@ -393,4 +395,19 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
return data.get(0);
}
+ /**
+ * Raw data is inserted asynchronously so it is possible that
+ * MeasurementDataManagerBean.mergeMeasurementReport will return before all raw data in
+ * the report has been inserted. There currently is not a good way for tests in the
+ * itests-2 module to block or to get notified when raw data inserts have finished. As
+ * a (hopefully temporary) hack we will sleep for a somewhat arbitrary amount of time
+ * to allow for the inserts to complete.
+ */
+ private void waitForRawInserts() {
+ try {
+ Thread.sleep(300);
+ } catch (InterruptedException e) {
+ }
+ }
+
}
10 years, 11 months