src/jdk.jdi/share/classes/com/sun/tools/jdi/ConnectorImpl.java
changeset 47216 71c04702a3d5
parent 45714 1820d351198d
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package com.sun.tools.jdi;
       
    27 
       
    28 import java.util.ArrayList;
       
    29 import java.util.Collection;
       
    30 import java.util.Collections;
       
    31 import java.util.Iterator;
       
    32 import java.util.LinkedHashMap;
       
    33 import java.util.List;
       
    34 import java.util.Map;
       
    35 import java.util.ResourceBundle;
       
    36 
       
    37 import com.sun.jdi.InternalException;
       
    38 import com.sun.jdi.connect.Connector;
       
    39 import com.sun.jdi.connect.IllegalConnectorArgumentsException;
       
    40 import com.sun.jdi.connect.LaunchingConnector;
       
    41 
       
    42 abstract class ConnectorImpl implements Connector {
       
    43 
       
    44     Map<String, Argument> defaultArguments = new LinkedHashMap<>();
       
    45 
       
    46     // Used by BooleanArgument
       
    47     static String trueString = null;
       
    48     static String falseString;
       
    49 
       
    50     public Map<String,Argument> defaultArguments() {
       
    51         Map<String,Argument> defaults = new LinkedHashMap<>();
       
    52         Collection<Argument> values = defaultArguments.values();
       
    53 
       
    54         Iterator<Argument> iter = values.iterator();
       
    55         while (iter.hasNext()) {
       
    56             ArgumentImpl argument = (ArgumentImpl)iter.next();
       
    57             defaults.put(argument.name(), (Argument)argument.clone());
       
    58         }
       
    59         return defaults;
       
    60     }
       
    61 
       
    62     void addStringArgument(String name, String label, String description,
       
    63                            String defaultValue, boolean mustSpecify) {
       
    64         defaultArguments.put(name,
       
    65                              new StringArgumentImpl(name, label,
       
    66                                                     description,
       
    67                                                     defaultValue,
       
    68                                                     mustSpecify));
       
    69     }
       
    70 
       
    71     void addBooleanArgument(String name, String label, String description,
       
    72                             boolean defaultValue, boolean mustSpecify) {
       
    73         defaultArguments.put(name,
       
    74                              new BooleanArgumentImpl(name, label,
       
    75                                                      description,
       
    76                                                      defaultValue,
       
    77                                                      mustSpecify));
       
    78     }
       
    79 
       
    80     void addIntegerArgument(String name, String label, String description,
       
    81                             String defaultValue, boolean mustSpecify,
       
    82                             int min, int max) {
       
    83         defaultArguments.put(name,
       
    84                              new IntegerArgumentImpl(name, label,
       
    85                                                      description,
       
    86                                                      defaultValue,
       
    87                                                      mustSpecify,
       
    88                                                      min, max));
       
    89     }
       
    90 
       
    91     void addSelectedArgument(String name, String label, String description,
       
    92                              String defaultValue, boolean mustSpecify,
       
    93                              List<String> list) {
       
    94         defaultArguments.put(name,
       
    95                              new SelectedArgumentImpl(name, label,
       
    96                                                       description,
       
    97                                                       defaultValue,
       
    98                                                       mustSpecify, list));
       
    99     }
       
   100 
       
   101     ArgumentImpl argument(String name, Map<String, ? extends Argument> arguments)
       
   102                 throws IllegalConnectorArgumentsException {
       
   103 
       
   104         ArgumentImpl argument = (ArgumentImpl)arguments.get(name);
       
   105         if (argument == null) {
       
   106             throw new IllegalConnectorArgumentsException(
       
   107                          "Argument missing", name);
       
   108         }
       
   109         String value = argument.value();
       
   110         if (value == null || value.length() == 0) {
       
   111             if (argument.mustSpecify()) {
       
   112             throw new IllegalConnectorArgumentsException(
       
   113                          "Argument unspecified", name);
       
   114             }
       
   115         } else if(!argument.isValid(value)) {
       
   116             throw new IllegalConnectorArgumentsException(
       
   117                          "Argument invalid", name);
       
   118         }
       
   119 
       
   120         return argument;
       
   121     }
       
   122 
       
   123 
       
   124     private ResourceBundle messages = null;
       
   125 
       
   126     String getString(String key) {
       
   127         if (messages == null) {
       
   128             messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
       
   129         }
       
   130         return messages.getString(key);
       
   131     }
       
   132 
       
   133     public String toString() {
       
   134         String string = name() + " (defaults: ";
       
   135         Iterator<Argument> iter = defaultArguments().values().iterator();
       
   136         boolean first = true;
       
   137         while (iter.hasNext()) {
       
   138             ArgumentImpl argument = (ArgumentImpl)iter.next();
       
   139             if (!first) {
       
   140                 string += ", ";
       
   141             }
       
   142             string += argument.toString();
       
   143             first = false;
       
   144         }
       
   145         string += ")";
       
   146         return string;
       
   147     }
       
   148 
       
   149     @SuppressWarnings("serial") // JDK implementation class
       
   150     abstract class ArgumentImpl implements Connector.Argument, Cloneable {
       
   151         private String name;
       
   152         private String label;
       
   153         private String description;
       
   154         private String value;
       
   155         private boolean mustSpecify;
       
   156 
       
   157         ArgumentImpl(String name, String label, String description,
       
   158                      String value, boolean mustSpecify) {
       
   159             this.name = name;
       
   160             this.label = label;
       
   161             this.description = description;
       
   162             this.value = value;
       
   163             this.mustSpecify = mustSpecify;
       
   164         }
       
   165 
       
   166         public abstract boolean isValid(String value);
       
   167 
       
   168         public String name() {
       
   169             return name;
       
   170         }
       
   171 
       
   172         public String label() {
       
   173             return label;
       
   174         }
       
   175 
       
   176         public String description() {
       
   177             return description;
       
   178         }
       
   179 
       
   180         public String value() {
       
   181             return value;
       
   182         }
       
   183 
       
   184         public void setValue(String value) {
       
   185             if (value == null) {
       
   186                 throw new NullPointerException("Can't set null value");
       
   187             }
       
   188             this.value = value;
       
   189         }
       
   190 
       
   191         public boolean mustSpecify() {
       
   192             return mustSpecify;
       
   193         }
       
   194 
       
   195         public boolean equals(Object obj) {
       
   196             if ((obj != null) && (obj instanceof Connector.Argument)) {
       
   197                 Connector.Argument other = (Connector.Argument)obj;
       
   198                 return (name().equals(other.name())) &&
       
   199                        (description().equals(other.description())) &&
       
   200                        (mustSpecify() == other.mustSpecify()) &&
       
   201                        (value().equals(other.value()));
       
   202             } else {
       
   203                 return false;
       
   204             }
       
   205         }
       
   206 
       
   207         public int hashCode() {
       
   208             return description().hashCode();
       
   209         }
       
   210 
       
   211         public Object clone() {
       
   212             try {
       
   213                 return super.clone();
       
   214             } catch (CloneNotSupportedException e) {
       
   215                 // Object should always support clone
       
   216                 throw new InternalException();
       
   217             }
       
   218         }
       
   219 
       
   220         public String toString() {
       
   221             return name() + "=" + value();
       
   222         }
       
   223     }
       
   224 
       
   225     class BooleanArgumentImpl extends ConnectorImpl.ArgumentImpl
       
   226                               implements Connector.BooleanArgument {
       
   227         private static final long serialVersionUID = 1624542968639361316L;
       
   228         BooleanArgumentImpl(String name, String label, String description,
       
   229                             boolean value,
       
   230                             boolean mustSpecify) {
       
   231             super(name, label, description, null, mustSpecify);
       
   232             if(trueString == null) {
       
   233                 trueString = getString("true");
       
   234                 falseString = getString("false");
       
   235             }
       
   236             setValue(value);
       
   237         }
       
   238 
       
   239         /**
       
   240          * Sets the value of the argument.
       
   241          */
       
   242         public void setValue(boolean value) {
       
   243             setValue(stringValueOf(value));
       
   244         }
       
   245 
       
   246         /**
       
   247          * Performs basic sanity check of argument.
       
   248          * @return <code>true</code> if value is a string
       
   249          * representation of a boolean value.
       
   250          * @see #stringValueOf(boolean)
       
   251          */
       
   252         public boolean isValid(String value) {
       
   253             return value.equals(trueString) || value.equals(falseString);
       
   254         }
       
   255 
       
   256         /**
       
   257          * Return the string representation of the <code>value</code>
       
   258          * parameter.
       
   259          * Does not set or examine the value or the argument.
       
   260          * @return the localized String representation of the
       
   261          * boolean value.
       
   262          */
       
   263         public String stringValueOf(boolean value) {
       
   264             return value? trueString : falseString;
       
   265         }
       
   266 
       
   267         /**
       
   268          * Return the value of the argument as a boolean.  Since
       
   269          * the argument may not have been set or may have an invalid
       
   270          * value {@link #isValid(String)} should be called on
       
   271          * {@link #value()} to check its validity.  If it is invalid
       
   272          * the boolean returned by this method is undefined.
       
   273          * @return the value of the argument as a boolean.
       
   274          */
       
   275         public boolean booleanValue() {
       
   276             return value().equals(trueString);
       
   277         }
       
   278     }
       
   279 
       
   280     class IntegerArgumentImpl extends ConnectorImpl.ArgumentImpl
       
   281                               implements Connector.IntegerArgument {
       
   282         private static final long serialVersionUID = 763286081923797770L;
       
   283         private final int min;
       
   284         private final int max;
       
   285 
       
   286         IntegerArgumentImpl(String name, String label, String description,
       
   287                             String value,
       
   288                             boolean mustSpecify, int min, int max) {
       
   289             super(name, label, description, value, mustSpecify);
       
   290             this.min = min;
       
   291             this.max = max;
       
   292         }
       
   293 
       
   294         /**
       
   295          * Sets the value of the argument.
       
   296          * The value should be checked with {@link #isValid(int)}
       
   297          * before setting it; invalid values will throw an exception
       
   298          * when the connection is established - for example,
       
   299          * on {@link LaunchingConnector#launch}
       
   300          */
       
   301         public void setValue(int value) {
       
   302             setValue(stringValueOf(value));
       
   303         }
       
   304 
       
   305         /**
       
   306          * Performs basic sanity check of argument.
       
   307          * @return <code>true</code> if value represents an int that is
       
   308          * <code>{@link #min()} &lt;= value &lt;= {@link #max()}</code>
       
   309          */
       
   310         public boolean isValid(String value) {
       
   311             if (value == null) {
       
   312                 return false;
       
   313             }
       
   314             try {
       
   315                 return isValid(Integer.decode(value).intValue());
       
   316             } catch (NumberFormatException exc) {
       
   317                 return false;
       
   318             }
       
   319         }
       
   320 
       
   321         /**
       
   322          * Performs basic sanity check of argument.
       
   323          * @return <code>true</code> if
       
   324          * <code>{@link #min()} &lt;= value  &lt;= {@link #max()}</code>
       
   325          */
       
   326         public boolean isValid(int value) {
       
   327             return min <= value && value <= max;
       
   328         }
       
   329 
       
   330         /**
       
   331          * Return the string representation of the <code>value</code>
       
   332          * parameter.
       
   333          * Does not set or examine the value or the argument.
       
   334          * @return the String representation of the
       
   335          * int value.
       
   336          */
       
   337         public String stringValueOf(int value) {
       
   338             // *** Should this be internationalized????
       
   339             // *** Even Brian Beck was unsure if an Arabic programmer
       
   340             // *** would expect port numbers in Arabic numerals,
       
   341             // *** so punt for now.
       
   342             return ""+value;
       
   343         }
       
   344 
       
   345         /**
       
   346          * Return the value of the argument as a int.  Since
       
   347          * the argument may not have been set or may have an invalid
       
   348          * value {@link #isValid(String)} should be called on
       
   349          * {@link #value()} to check its validity.  If it is invalid
       
   350          * the int returned by this method is undefined.
       
   351          * @return the value of the argument as a int.
       
   352          */
       
   353         public int intValue() {
       
   354             if (value() == null) {
       
   355                 return 0;
       
   356             }
       
   357             try {
       
   358                 return Integer.decode(value()).intValue();
       
   359             } catch(NumberFormatException exc) {
       
   360                 return 0;
       
   361             }
       
   362         }
       
   363 
       
   364         /**
       
   365          * The upper bound for the value.
       
   366          * @return the maximum allowed value for this argument.
       
   367          */
       
   368         public int max() {
       
   369             return max;
       
   370         }
       
   371 
       
   372         /**
       
   373          * The lower bound for the value.
       
   374          * @return the minimum allowed value for this argument.
       
   375          */
       
   376         public int min() {
       
   377             return min;
       
   378         }
       
   379     }
       
   380 
       
   381     class StringArgumentImpl extends ConnectorImpl.ArgumentImpl
       
   382                              implements Connector.StringArgument {
       
   383         private static final long serialVersionUID = 7500484902692107464L;
       
   384         StringArgumentImpl(String name, String label, String description,
       
   385                            String value, boolean mustSpecify) {
       
   386             super(name, label, description, value, mustSpecify);
       
   387         }
       
   388 
       
   389         /**
       
   390          * Performs basic sanity check of argument.
       
   391          * @return <code>true</code> always
       
   392          */
       
   393         public boolean isValid(String value) {
       
   394             return true;
       
   395         }
       
   396     }
       
   397 
       
   398     class SelectedArgumentImpl extends ConnectorImpl.ArgumentImpl
       
   399                               implements Connector.SelectedArgument {
       
   400         private static final long serialVersionUID = -5689584530908382517L;
       
   401         private final List<String> choices;
       
   402 
       
   403         SelectedArgumentImpl(String name, String label, String description,
       
   404                              String value,
       
   405                              boolean mustSpecify, List<String> choices) {
       
   406             super(name, label, description, value, mustSpecify);
       
   407             this.choices = Collections.unmodifiableList(new ArrayList<>(choices));
       
   408         }
       
   409 
       
   410         /**
       
   411          * Return the possible values for the argument
       
   412          * @return {@link List} of {@link String}
       
   413          */
       
   414         public List<String> choices() {
       
   415             return choices;
       
   416         }
       
   417 
       
   418         /**
       
   419          * Performs basic sanity check of argument.
       
   420          * @return <code>true</code> if value is one of {@link #choices()}.
       
   421          */
       
   422         public boolean isValid(String value) {
       
   423             return choices.contains(value);
       
   424         }
       
   425     }
       
   426 }