|
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-2021 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.