|
Glassfish example source code file (MonitoringReporter.java)
The Glassfish MonitoringReporter.java source code
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.v3.admin;
import com.sun.enterprise.admin.util.ClusterOperationUtil;
import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.config.serverbeans.Domain;
import static com.sun.enterprise.util.StringUtils.ok;
import com.sun.enterprise.v3.common.ActionReporter;
import com.sun.enterprise.v3.common.PlainTextActionReporter;
import com.sun.enterprise.v3.common.PropsFileActionReporter;
import java.lang.reflect.Proxy;
import java.util.*;
import org.glassfish.api.ActionReport;
import org.glassfish.api.admin.*;
import org.glassfish.api.admin.ExecuteOn;
import org.glassfish.api.admin.RuntimeType;
import org.glassfish.external.statistics.Statistic;
import org.glassfish.external.statistics.Stats;
import org.glassfish.external.statistics.impl.StatisticImpl;
import org.glassfish.internal.api.*;
import org.jvnet.hk2.component.*;
import static org.glassfish.api.ActionReport.ExitCode.FAILURE;
import static org.glassfish.api.ActionReport.ExitCode.SUCCESS;
import org.glassfish.api.admin.AdminCommandContext;
import org.glassfish.flashlight.MonitoringRuntimeDataRegistry;
import org.jvnet.hk2.annotations.*;
import org.jvnet.hk2.component.PerLookup;
import static com.sun.enterprise.util.SystemPropertyConstants.MONDOT;
import static com.sun.enterprise.util.SystemPropertyConstants.SLASH;
/**
*
* @author Byron Nevins
* First breathed life on November 6, 2010
* The copyright says 1997 because one method in here has code moved verbatim
* from GetCommand.java which started life in 1997
*
* Note: what do you suppose is the worst possible name for a TreeNode class?
* Correct! TreeNode! Clashing names is why we have to explicitly use this ghastly
* name: org.glassfish.flashlight.datatree.TreeNode all over the place...
*/
@Service(name = "MonitoringReporter")
@Scoped(PerLookup.class)
@ExecuteOn({RuntimeType.DAS, RuntimeType.INSTANCE})
public class MonitoringReporter extends V2DottedNameSupport {
public enum OutputType {
GET, LIST
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\nPattern=[").append(pattern).append("]").append('\n');
if (!targets.isEmpty()) {
for (Server server : targets) {
if (server != null)
sb.append("Server=[").append(server.getName()).append("]").append('\n');
}
}
else
sb.append("No Targets");
return sb.toString();
}
///////////////////////////////////////////////////////////////////////
//////////////////////// The API Methods ///////////////////////////
///////////////////////////////////////////////////////////////////////
public void prepareGet(AdminCommandContext c, String arg) {
prepare(c, arg, OutputType.GET);
}
public void prepareList(AdminCommandContext c, String arg) {
prepare(c, arg, OutputType.LIST);
}
public void execute() {
// TODO remove? make it an exception???
if (hasError())
return;
runLocally();
runRemotely();
}
///////////////////////////////////////////////////////////////////////
//////////////////////// ALL PRIVATE BELOW ///////////////////////////
///////////////////////////////////////////////////////////////////////
private void prepare(AdminCommandContext c, String arg, OutputType type) {
outputType = type;
context = c;
prepareReporter();
// DAS runs the show on this command. If we are running in an
// instance -- that means we should call runLocally() AND it also
// means that the pattern is already perfect!
if (isDas())
prepareDas(arg);
else
prepareInstance(arg);
}
/**
* The stock ActionReport we get is too inefficient. Replace it with PlainText
* note that we might be called with HTML or XML or JSON or others!
*/
private void prepareReporter() {
reporter = (ActionReporter) context.getActionReport();
if (reporter instanceof PlainTextActionReporter) {
// already setup correctly - don't change it!!
plainReporter = (PlainTextActionReporter) reporter;
}
else if (reporter instanceof PropsFileActionReporter) {
plainReporter = new PlainTextActionReporter();
reporter = plainReporter;
context.setActionReport(plainReporter);
}
else {
plainReporter = null;
}
}
private void prepareDas(String arg) {
// TODO throw an exception if any errors????
try {
setSuccess();
userarg = arg;
if (!validate())
return;
}
catch (Exception e) {
setError(Strings.get("admin.get.monitoring.unknown", e.getMessage()));
reporter.setFailureCause(e);
}
}
private void prepareInstance(String arg) {
// TODO throw an exception if any errors!
pattern = arg;
}
// mostly just copied over from old "get" implementation
// That's why it is excruciatingly unreadable...
private void runLocally() {
// don't run if this is DAS **and** DAS is not in the server list.
// otherwise we are in an instance and definitely want to run!
if (isDas() && !dasIsInList())
return;
// say the pattern is "something" -->
// we want "server.something" for DAS and "i1.server.something" for i1
// Yes -- this is difficult to get perfect!!! What if user entered
//"server.something"?
String localPattern = prependServerDot(pattern);
org.glassfish.flashlight.datatree.TreeNode tn = datareg.get(serverEnv.getInstanceName());
if (tn == null) {
// No monitoring data, so nothing to list
// officially this is considered a "success"
setSuccess(Strings.get("admin.get.monitoring.empty"));
return;
}
List<org.glassfish.flashlight.datatree.TreeNode> ltn = tn.getNodes(localPattern);
boolean singleStat = false;
if (ltn == null || ltn.isEmpty()) {
org.glassfish.flashlight.datatree.TreeNode parent = tn.getPossibleParentNode(localPattern);
if (parent != null) {
ltn = new ArrayList<org.glassfish.flashlight.datatree.TreeNode>(1);
ltn.add(parent);
singleStat = true;
}
}
if (!singleStat)
localPattern = null; // signal to method call below. localPattern was already used above...
if (outputType == OutputType.GET)
doGet(localPattern, ltn);
else if (outputType == OutputType.LIST)
doList(localPattern, ltn);
if (plainReporter != null) {
plainReporter.appendMessage(cliOutput.toString());
}
}
// Byron Nevins -- copied from original implementation
private void doGet(String localPattern, List<org.glassfish.flashlight.datatree.TreeNode> ltn) {
TreeMap map = new TreeMap();
for (org.glassfish.flashlight.datatree.TreeNode tn1 : sortTreeNodesByCompletePathName(ltn)) {
if (!tn1.hasChildNodes()) {
insertNameValuePairs(map, tn1, localPattern);
}
}
ActionReport.MessagePart topPart = reporter.getTopMessagePart();
Iterator it = map.keySet().iterator();
while (it.hasNext()) {
Object obj = it.next();
String line = obj.toString();
line = line.replace(SLASH, "/") + " = " + map.get(obj);
if (plainReporter != null)
cliOutput.append(line).append('\n');
else {
ActionReport.MessagePart part = topPart.addChild();
part.setMessage(line);
}
}
setSuccess();
}
private void doList(String localPattern, List<org.glassfish.flashlight.datatree.TreeNode> ltn) {
// list means only print things that have children. Don't print the children.
ActionReport.MessagePart topPart = reporter.getTopMessagePart();
for (org.glassfish.flashlight.datatree.TreeNode tn1 : ltn) {
if (tn1.hasChildNodes()) {
String line = tn1.getCompletePathName();
if (plainReporter != null)
cliOutput.append(line).append('\n');
else {
ActionReport.MessagePart part = topPart.addChild();
part.setMessage(line);
}
}
}
setSuccess();
}
/**
* This can be a bit confusing. It is sort of like a recursive call.
* GetCommand will be called on the instance. BUT -- the pattern arg will
* just have the actual pattern -- the target name will NOT be in there!
* So "runLocally" will be called on the instance. this method will ONLY
* run on DAS (guaranteed!)
*/
private void runRemotely() {
if (!isDas())
return;
List<Server> remoteServers = getRemoteServers();
if (remoteServers.isEmpty())
return;
try {
ParameterMap paramMap = new ParameterMap();
paramMap.set("monitor", "true");
paramMap.set("DEFAULT", pattern);
ClusterOperationUtil.replicateCommand("get", FailurePolicy.Error, FailurePolicy.Warn, remoteServers,
context, paramMap, habitat);
}
catch (Exception ex) {
setError(Strings.get("admin.get.monitoring.remote.error", getNames(remoteServers)));
}
}
private String prependServerDot(String s) {
// note -- we are now running in either DAS or an instance and we are going to gather up
// data ONLY for this server. I.e. the DAS dispatching has already happened.
// we really need this pattern to start with the instance-name (DAS's instance-name is "server"
// Issue#15054
// this is pretty intricate but this is what we want to happen for these samples:
// asadmin get -m network.thread-pool.totalexecutedtasks-count ==> ERROR no target
// asadmin get -m server.network.thread-pool.totalexecutedtasks-count ==> OK, return DAS's data
// asadmin get -m *.network.thread-pool.totalexecutedtasks-count ==> OK return DAS and instances' data
// asadmin get -m i1.network.thread-pool.totalexecutedtasks-count ==> OK return data for i1
final String namedot = serverEnv.getInstanceName() + ".";
if(s.startsWith(namedot))
return s;
return namedot + s;
}
private boolean validate() {
if (datareg == null) {
setError(Strings.get("admin.get.no.monitoring"));
return false;
}
if (!initPatternAndTargets())
return false;
return true;
}
/*
* VERY VERY complicated to get this right!
*/
private boolean initPatternAndTargets() {
Server das = domain.getServerNamed("server");
String targetName = null;
// no DAS in here!
List<Server> allServers = targetService.getAllInstances();
allServers.add(das);
// 0 decode special things
// \\ == literal backslash and \ is escaping next char
userarg = handleEscapes(userarg); // too complicated to do in-line
// MONDOT, SLASH should be replaced with literals
userarg = userarg.replace(MONDOT, ".").replace(SLASH, "/");
// 1. nothing
// 2. *
// 3. *. --> which is a weird input but let's accept it anyway!
// 4 . --> very weird but we'll take it
if (!ok(userarg)
|| userarg.equals("*")
|| userarg.equals(".")
|| userarg.equals("*.")) {
// By definition this means ALL servers and ALL data
targets = allServers;
pattern = "*";
return true;
}
// 5. *..
// 6. *.<something>
if (userarg.startsWith("*.")) {
targets = allServers;
// note: it can NOT be just "*." -- there is something at posn #2 !!
pattern = userarg.substring(2);
// "*.." is an error
if (pattern.startsWith(".")) {
String specificError = Strings.get("admin.get.monitoring.nodoubledot");
setError(Strings.get("admin.get.monitoring.invalidpattern", specificError));
return false;
}
return true;
}
// 7. See 14685 for an example --> "*jsp*"
if (userarg.startsWith("*")) {
targets = allServers;
pattern = userarg.substring(1);
return true;
}
// Another example:
// servername*something*
// IT 14778
// note we will NOT support serv*something getting resolved to server*something
// that's too crazy. They have to enter a reasonable name
// we are looking for, e.g. instance1*foo.goo*
// target is instance1 pattern is *foo.goo*
// instance1.something is handled below
String re = "[^\\.]+\\*.*";
if (userarg.matches(re)) {
int index = userarg.indexOf("*");
if (index < 0) { // can't happen!!
setError(Strings.get("admin.get.monitoring.invalidtarget", userarg));
return false;
}
targetName = userarg.substring(0, index);
pattern = userarg.substring(index);
}
if (targetName == null) {
int index = userarg.indexOf(".");
if (index >= 0) {
targetName = userarg.substring(0, index);
if (userarg.length() == index + 1) {
// 8. <servername>.
pattern = "*";
}
else
// 9. <servername>.
Other Glassfish examples (source code examples)Here is a short list of links related to this Glassfish MonitoringReporter.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.