Home | History | Annotate | Download | only in swing
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 package org.opensolaris.os.vp.panels.coreadm.client.swing;
     28 
     29 import java.util.*;
     30 import org.opensolaris.os.scf.common.*;
     31 import org.opensolaris.os.vp.common.smf.ServiceMXBean;
     32 import org.opensolaris.os.vp.panel.common.smf.*;
     33 import org.opensolaris.os.vp.util.misc.Finder;
     34 
     35 /**
     36  * Wholly encapsulates core file configuration.  Can be constructed
     37  * manually or from an existing SMF configuration.
     38  */
     39 public class CoreConfig {
     40 
     41     /**
     42      * Core file content types, enumerated.
     43      */
     44     public enum ContentType {
     45 	ANON("anon"), CTF("ctf"), DATA("data"), DISM("dism"), HEAP("heap"),
     46 	ISM("ism"), RODATA("rodata"), SHANON("shanon"), SHFILE("shfile"),
     47 	SHM("shm"), STACK("stack"), SYMTAB("symtab"), TEXT("text");
     48 
     49 	private final String literal_;
     50 	private ContentType(String literal) {
     51 	    literal_ = literal;
     52 	}
     53 
     54 	/**
     55 	 * Returns the string the system uses to represent the type.
     56 	 * Should only be needed inside of CoreConfig.
     57 	 *
     58 	 * @return the string the system uses to represent the type
     59 	 */
     60 	private String getLiteral()
     61 	{
     62 	    return (literal_);
     63 	}
     64 
     65 	/**
     66 	 * Returns the natural language name of the content type.
     67 	 *
     68 	 * @return the natural language name of the content type.
     69 	 */
     70 	public String getName()
     71 	{
     72 	    return (Finder.getString("coreadm.contents." + literal_));
     73 	}
     74     }
     75 
     76     /*
     77      * Ideally this would be unmodifiable, but there is no
     78      * Collections.umodifiableEnumSet() and the EnumSet-specific
     79      * interfaces are very useful.
     80      */
     81 
     82     /**
     83      * The default set of content types.
     84      */
     85     private static final String LITERAL_DEFAULT = "default";
     86     public static final EnumSet<ContentType> CONTENT_DEFAULT =
     87 	EnumSet.complementOf(EnumSet.of(ContentType.SHFILE));
     88 
     89     private static final String LITERAL_NONE = "none";
     90     public static final EnumSet<ContentType> CONTENT_NONE =
     91 	EnumSet.noneOf(ContentType.class);
     92 
     93     private static final String LITERAL_ALL = "all";
     94     public static final EnumSet<ContentType> CONTENT_ALL =
     95 	EnumSet.allOf(ContentType.class);
     96 
     97     /*
     98      * Constants for SMF representation.
     99      */
    100     private static final String CONFIG_PG = "config_params";
    101     private static final String PROP_LOGGING = "global_log_enabled";
    102 
    103     private static final String PROP_SFX_CONTENT = "_content";
    104     private static final String PROP_SFX_PATTERN = "_pattern";
    105     private static final String PROP_SFX_ENABLED = "_enabled";
    106     private static final String PROP_SFX_SETID = "_setid_enabled";
    107 
    108     private static final String PROP_PFX_GLOBAL = "global";
    109     private static final String PROP_PFX_PROC = "process";
    110     /* Needed for content and pattern */
    111     private static final String PROP_PFX_ALTPROC = "init";
    112 
    113     /**
    114      * Converts a literal content type into an EnumSet containing
    115      * the appropriate ContentTypes.
    116      *
    117      * @param literal the string to convert to a ContentType
    118      * @return the EnumSet of corresponding ContentTypes
    119      * @throws IllegalArugmentException if literal isn't a valid
    120      * content type literal
    121      */
    122     private static EnumSet<ContentType> literalToSet(String literal)
    123     {
    124 	/*
    125 	 * This isn't the most efficient implementation, but
    126 	 * it does the job.
    127 	 */
    128 	for (ContentType t : ContentType.values())
    129 	    if (t.getLiteral().equals(literal))
    130 		return (EnumSet.of(t));
    131 
    132 	if (literal.equals(LITERAL_DEFAULT))
    133 		return (CONTENT_DEFAULT);
    134 
    135 	if (literal.equals(LITERAL_NONE))
    136 		return (CONTENT_NONE);
    137 
    138 	if (literal.equals(LITERAL_ALL))
    139 		return (CONTENT_ALL);
    140 
    141 	throw (new IllegalArgumentException(literal));
    142     }
    143 
    144     /**
    145      * Converts a Set of ContentTypes to a comma-separated list of
    146      * system-recognized type names.
    147      *
    148      * @param s the Set of ContentTypes to convert to a String
    149      * @return the comma-separated String representation of the Set
    150      */
    151     private static String setToLiterals(EnumSet<ContentType> s)
    152     {
    153 	if (s.equals(CONTENT_DEFAULT))
    154 	    return (LITERAL_DEFAULT);
    155 
    156 	if (s.equals(CONTENT_ALL))
    157 	    return (LITERAL_ALL);
    158 
    159 	if (s.equals(CONTENT_NONE))
    160 	    return (LITERAL_NONE);
    161 
    162 	StringBuilder sb = new StringBuilder();
    163 	boolean comma = false;
    164 	for (ContentType t : s) {
    165 	    if (comma)
    166 		sb.append("+");
    167 	    comma = true;
    168 	    sb.append(t.getLiteral());
    169 	}
    170 	return (sb.toString());
    171     }
    172 
    173     /**
    174      * Converts a list of content types in string form into a EnumSet
    175      * of ContentTypes.
    176      *
    177      * @param lit the list of content types in string form
    178      * @return an EnumSet containing the content types
    179      */
    180     private static EnumSet<ContentType> literalsToSet(String lit)
    181     {
    182         boolean plus = true;
    183 	int offset = 0;
    184 	int max = lit.length();
    185 
    186 	EnumSet<ContentType> result = EnumSet.noneOf(ContentType.class);
    187 	for (String s : lit.split("[+-]")) {
    188 	    if (plus)
    189 		result.addAll(literalToSet(s));
    190 	    else
    191 		result.retainAll(EnumSet.complementOf(literalToSet(s)));
    192 
    193 	    offset += s.length();
    194 	    if (offset < max)
    195 		plus = lit.charAt(offset) == '+';
    196 	    offset++;
    197         }
    198 	return (result);
    199     }
    200 
    201     /**
    202      * Encapsulates configuration that could apply to either
    203      * the process or global scope.
    204      */
    205     static public class ScopeConfig
    206     {
    207 	private EnumSet<ContentType> content_;
    208 	private String pattern_;
    209 	private boolean enabled_;
    210 	private boolean setid_;
    211 
    212 	public ScopeConfig(EnumSet<ContentType> content,
    213 	    String pattern, boolean enabled, boolean setid)
    214 	{
    215 	    content_ = content;
    216 	    pattern_ = pattern;
    217 	    enabled_ = enabled;
    218 	    setid_ = setid;
    219 	}
    220 
    221 	public ScopeConfig()
    222 	{
    223 	    this(CONTENT_DEFAULT.clone(), "", false, false);
    224 	}
    225 
    226 
    227 	public ScopeConfig(ScopeConfig config)
    228 	{
    229 	    this(config.content_.clone(),
    230 		config.pattern_, config.enabled_, config.setid_);
    231 	}
    232 
    233 	public ScopeConfig(ServiceMXBean service, String pfx, String altpfx)
    234 	    throws ScfException, InvalidScfDataException,
    235 	    MissingScfDataException
    236 	{
    237 	    List<String> content = service.getSnapshotPropertyValues(
    238 		ScfConstants.SCF_RUNNING, CONFIG_PG, altpfx + PROP_SFX_CONTENT);
    239 	    List<String> pattern = service.getSnapshotPropertyValues(
    240 		ScfConstants.SCF_RUNNING, CONFIG_PG, altpfx + PROP_SFX_PATTERN);
    241 	    List<String> enabled = service.getSnapshotPropertyValues(
    242 		ScfConstants.SCF_RUNNING, CONFIG_PG, pfx + PROP_SFX_ENABLED);
    243 	    List<String> setid = service.getSnapshotPropertyValues(
    244 		ScfConstants.SCF_RUNNING, CONFIG_PG, pfx + PROP_SFX_SETID);
    245 
    246 	    String name = null;
    247 	    String value = null;
    248 	    try {
    249 		name = altpfx + PROP_SFX_CONTENT;
    250 		value = content.get(0);
    251 		content_ = literalsToSet(value);
    252 
    253 		name = altpfx + PROP_SFX_PATTERN;
    254 		pattern_ = pattern.get(0);
    255 
    256 		name = pfx + PROP_SFX_ENABLED;
    257 		enabled_ = Boolean.parseBoolean(enabled.get(0));
    258 
    259 		name = pfx + PROP_SFX_SETID;
    260 		setid_ = Boolean.parseBoolean(setid.get(0));
    261 	    } catch (IndexOutOfBoundsException e) {
    262 		throw new MissingScfDataException(name);
    263 	    } catch (IllegalArgumentException e) {
    264 		throw new InvalidScfDataException(name, value);
    265 	    }
    266 	}
    267 
    268 	/*
    269 	 * Object methods.
    270 	 */
    271 
    272 	@Override
    273 	public boolean equals(Object o)
    274 	{
    275 	    if (!(o instanceof ScopeConfig))
    276 		return (false);
    277 	    ScopeConfig c = (ScopeConfig)o;
    278 	    return (enabled_ == c.enabled_ && setid_ == c.setid_ &&
    279 		pattern_.equals(c.pattern_) && content_.equals(c.content_));
    280 	}
    281 
    282 	@Override
    283 	public int hashCode()
    284 	{
    285 	    int hash = 7;
    286 	    hash = 61 * hash +
    287 		(this.content_ != null ? this.content_.hashCode() : 0);
    288 	    hash = 61 * hash +
    289 		(this.pattern_ != null ? this.pattern_.hashCode() : 0);
    290 	    hash = 61 * hash + (this.enabled_ ? 1 : 0);
    291 	    hash = 61 * hash + (this.setid_ ? 1 : 0);
    292 	    return (hash);
    293 	}
    294 
    295 	/*
    296 	 * ScopeConfig methods.
    297 	 */
    298 
    299         void write(ServiceMXBean service, String pfx, String altpfx)
    300 	    throws ScfException
    301 	{
    302 	    service.setPropertyValues(CONFIG_PG, altpfx + PROP_SFX_CONTENT,
    303 		setToLiterals(content_));
    304 	    service.setPropertyValues(CONFIG_PG, altpfx + PROP_SFX_PATTERN,
    305 		pattern_);
    306 	    service.setPropertyValues(CONFIG_PG, pfx + PROP_SFX_ENABLED,
    307 		Boolean.toString(enabled_));
    308 	    service.setPropertyValues(CONFIG_PG, pfx + PROP_SFX_SETID,
    309 		Boolean.toString(setid_));
    310 	}
    311 
    312 	EnumSet<ContentType> getContent()
    313 	{
    314 	    return (content_.clone());
    315 	}
    316 
    317 	String getPattern()
    318 	{
    319 	    return (pattern_);
    320 	}
    321 
    322 	boolean getEnabled()
    323 	{
    324 	    return (enabled_);
    325 	}
    326 
    327 	boolean getSetid()
    328 	{
    329 	    return (setid_);
    330 	}
    331 
    332 	void setContent(Set<ContentType> content)
    333 	{
    334 	    content_.clear();
    335 	    content_.addAll(content);
    336 	}
    337 
    338 	void setPattern(String pattern)
    339 	{
    340 	    pattern_ = pattern;
    341 	}
    342 
    343 	void setEnabled(boolean enabled)
    344 	{
    345 	    enabled_ = enabled;
    346 	}
    347 
    348 	void setSetid(boolean setid)
    349 	{
    350 	    setid_ = setid;
    351 	}
    352     }
    353 
    354     ScopeConfig processScope_;
    355     ScopeConfig globalScope_;
    356     boolean logging_;
    357 
    358     CoreConfig(ScopeConfig global, ScopeConfig process, boolean logging)
    359     {
    360 	globalScope_ = global;
    361 	processScope_ = process;
    362 	logging_ = logging;
    363     }
    364 
    365     CoreConfig()
    366     {
    367 	this(new ScopeConfig(), new ScopeConfig(), false);
    368     }
    369 
    370     CoreConfig(String globalPattern, String processPattern,
    371 	boolean global, boolean globalSetid,
    372 	boolean process, boolean processSetid,
    373 	boolean logging)
    374     {
    375 	this(new ScopeConfig(CONTENT_DEFAULT.clone(),
    376 	    globalPattern, global, globalSetid),
    377 	    new ScopeConfig(CONTENT_DEFAULT.clone(),
    378 	    processPattern, process, processSetid),
    379 	    logging);
    380     }
    381 
    382     /**
    383      * Copy constructor.
    384      *
    385      * @param cc the CoreConfig object we are copying.
    386      */
    387     CoreConfig(CoreConfig cc)
    388     {
    389 	this(new ScopeConfig(cc.globalScope_),
    390 	    new ScopeConfig(cc.processScope_), cc.logging_);
    391     }
    392 
    393     CoreConfig(ServiceMXBean service) throws ScfException,
    394 	InvalidScfDataException, MissingScfDataException
    395     {
    396 	globalScope_ =
    397 	    new ScopeConfig(service, PROP_PFX_GLOBAL, PROP_PFX_GLOBAL);
    398 	processScope_ =
    399 	    new ScopeConfig(service, PROP_PFX_PROC, PROP_PFX_ALTPROC);
    400 
    401 	try {
    402 	    List<String> logging = service.getSnapshotPropertyValues(
    403 		ScfConstants.SCF_RUNNING, CONFIG_PG, PROP_LOGGING);
    404 	    logging_ = Boolean.parseBoolean(logging.get(0));
    405 	} catch (IndexOutOfBoundsException e) {
    406 	    throw new MissingScfDataException(PROP_LOGGING);
    407 	}
    408     }
    409 
    410     void write(ServiceMXBean service) throws ScfException
    411     {
    412 	globalScope_.write(service, PROP_PFX_GLOBAL, PROP_PFX_GLOBAL);
    413 	processScope_.write(service, PROP_PFX_PROC, PROP_PFX_ALTPROC);
    414 	service.setPropertyValues(CONFIG_PG, PROP_LOGGING,
    415 	    Boolean.toString(logging_));
    416 
    417 	service.refresh();
    418     }
    419 
    420     ScopeConfig getProcessScope()
    421     {
    422 	return (processScope_);
    423     }
    424 
    425     ScopeConfig getGlobalScope()
    426     {
    427 	return (globalScope_);
    428     }
    429 
    430     boolean getLogging()
    431     {
    432 	return (logging_);
    433     }
    434 
    435     void setLogging(boolean logging)
    436     {
    437 	logging_ = logging;
    438     }
    439 
    440     /*
    441      * Object methods
    442      */
    443 
    444     @Override
    445     public boolean equals(Object o)
    446     {
    447 	if (!(o instanceof CoreConfig))
    448 	    return (false);
    449 	CoreConfig c = (CoreConfig)o;
    450 	return (logging_ == c.logging_ &&
    451 	    globalScope_.equals(c.globalScope_) &&
    452 	    processScope_.equals(c.processScope_));
    453     }
    454 
    455     @Override
    456     public int hashCode()
    457     {
    458 	int hash = 7;
    459 	hash = 97 * hash +
    460 	    (this.processScope_ != null ? this.processScope_.hashCode() : 0);
    461 	hash = 97 * hash +
    462 	    (this.globalScope_ != null ? this.globalScope_.hashCode() : 0);
    463 	hash = 97 * hash + (this.logging_ ? 1 : 0);
    464 	return (hash);
    465     }
    466 
    467     private String boolToEnabled(boolean b)
    468     {
    469 	return (b ? "enabled" : "disabled");
    470     }
    471 
    472     /**
    473      * Pretty print a CoreConfig coreadm(1M)-style.
    474      *
    475      * @param ps the PrintStream to pretty-print to (e.g. System.out)
    476      */
    477     public void dump(java.io.PrintStream ps)
    478     {
    479 	ps.println("     global core file pattern: " +
    480 	    globalScope_.getPattern());
    481 	ps.println("     global core file content: " +
    482 	    setToLiterals(globalScope_.getContent()));
    483 	ps.println("       init core file pattern: " +
    484 	    processScope_.getPattern());
    485 	ps.println("       init core file content: " +
    486 	    setToLiterals(processScope_.getContent()));
    487 	ps.println("            global core dumps: " +
    488 	    boolToEnabled(globalScope_.getEnabled()));
    489 	ps.println("       per-process core dumps: " +
    490 	    boolToEnabled(processScope_.getEnabled()));
    491 	ps.println("      global setid core dumps: " +
    492 	    boolToEnabled(globalScope_.getSetid()));
    493 	ps.println(" per-process setid core dumps: " +
    494 	    boolToEnabled(processScope_.getSetid()));
    495 	ps.println("     global core dump logging: " + boolToEnabled(logging_));
    496     }
    497 }
    498