Example #1
0
 private Set<String> getLocalPlayersAsUuidStrings() {
   ImmutableSet.Builder<String> builder = ImmutableSet.builder();
   for (ProxiedPlayer player : getProxy().getPlayers()) {
     builder.add(player.getUniqueId().toString());
   }
   return builder.build();
 }
Example #2
0
 final Set<UUID> getPlayers() {
   ImmutableSet.Builder<UUID> setBuilder = ImmutableSet.builder();
   if (pool != null) {
     try (Jedis rsc = pool.getResource()) {
       List<String> keys = new ArrayList<>();
       for (String i : getServerIds()) {
         keys.add("proxy:" + i + ":usersOnline");
       }
       if (!keys.isEmpty()) {
         Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()]));
         if (users != null && !users.isEmpty()) {
           for (String user : users) {
             try {
               setBuilder = setBuilder.add(UUID.fromString(user));
             } catch (IllegalArgumentException ignored) {
             }
           }
         }
       }
     } catch (JedisConnectionException e) {
       // Redis server has disappeared!
       getLogger()
           .log(
               Level.SEVERE,
               "Unable to get connection from pool - did your Redis server go away?",
               e);
       throw new RuntimeException("Unable to get all players online", e);
     }
   }
   return setBuilder.build();
 }
Example #3
0
 public static boolean ignoredSchemaRow(Row row) {
   try {
     return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.key));
   } catch (CharacterCodingException e) {
     throw new RuntimeException(e);
   }
 }
 /**
  * Endpoints which are migrating to the new tokens
  *
  * @return set of addresses of moving endpoints
  */
 public Set<Pair<Token, InetAddress>> getMovingEndpoints() {
   lock.readLock().lock();
   try {
     return ImmutableSet.copyOf(movingEndpoints);
   } finally {
     lock.readLock().unlock();
   }
 }
 /** caller should not modify leavingEndpoints */
 public Set<InetAddress> getLeavingEndpoints() {
   lock.readLock().lock();
   try {
     return ImmutableSet.copyOf(leavingEndpoints);
   } finally {
     lock.readLock().unlock();
   }
 }
 public Set<InetAddress> getAllEndpoints() {
   lock.readLock().lock();
   try {
     return ImmutableSet.copyOf(endpointToHostIdMap.keySet());
   } finally {
     lock.readLock().unlock();
   }
 }
Example #7
0
 public Set<UUID> getPlayersOnProxy(String server) {
   checkArgument(getServerIds().contains(server), server + " is not a valid proxy ID");
   try (Jedis jedis = pool.getResource()) {
     Set<String> users = jedis.smembers("proxy:" + server + ":usersOnline");
     ImmutableSet.Builder<UUID> builder = ImmutableSet.builder();
     for (String user : users) {
       builder.add(UUID.fromString(user));
     }
     return builder.build();
   }
 }
Example #8
0
 final Set<UUID> getPlayersOnServer(@NonNull String server) {
   checkArgument(getProxy().getServers().containsKey(server), "server does not exist");
   Collection<String> asStrings =
       (Collection<String>)
           getServerPlayersScript.eval(
               ImmutableList.<String>of(), ImmutableList.<String>of(server));
   ImmutableSet.Builder<UUID> builder = ImmutableSet.builder();
   for (String s : asStrings) {
     builder.add(UUID.fromString(s));
   }
   return builder.build();
 }
  private Set<TestBean> buildBeans() {

    ImmutableSet.Builder<TestBean> aBuilder = ImmutableSet.builder();

    aBuilder.add(
        new TestBean("John", "Doe", "blue"),
        new TestBean("Sally", "Smith", "red"),
        new TestBean("Abe", "Lincoln", "black"),
        new TestBean("Albus", "Dumbledore", "purple"),
        new TestBean("Herminoe", "Grainger", "pink"));

    return aBuilder.build();
  }
  private void writeDelegateMethods(
      final ClassVisitor visitor,
      final Type generatedType,
      StructSchema<?> delegateSchema,
      Set<Class<?>> typesToDelegate) {
    Class<?> delegateClass = delegateSchema.getType().getConcreteClass();
    Type delegateType = Type.getType(delegateClass);
    Map<Equivalence.Wrapper<Method>, Map<Class<?>, Method>> methodsToDelegate = Maps.newHashMap();
    for (Class<?> typeToDelegate : typesToDelegate) {
      for (Method methodToDelegate : typeToDelegate.getMethods()) {
        if (ModelSchemaUtils.isIgnoredMethod(methodToDelegate)) {
          continue;
        }
        Equivalence.Wrapper<Method> methodKey = METHOD_EQUIVALENCE.wrap(methodToDelegate);
        Map<Class<?>, Method> methodsByReturnType = methodsToDelegate.get(methodKey);
        if (methodsByReturnType == null) {
          methodsByReturnType = Maps.newHashMap();
          methodsToDelegate.put(methodKey, methodsByReturnType);
        }
        methodsByReturnType.put(methodToDelegate.getReturnType(), methodToDelegate);
      }
    }
    Set<Equivalence.Wrapper<Method>> delegateMethodKeys =
        ImmutableSet.copyOf(
            Iterables.transform(
                Arrays.asList(delegateClass.getMethods()),
                new Function<Method, Equivalence.Wrapper<Method>>() {
                  @Override
                  public Equivalence.Wrapper<Method> apply(Method method) {
                    return METHOD_EQUIVALENCE.wrap(method);
                  }
                }));
    for (Map.Entry<Equivalence.Wrapper<Method>, Map<Class<?>, Method>> entry :
        methodsToDelegate.entrySet()) {
      Equivalence.Wrapper<Method> methodKey = entry.getKey();
      if (!delegateMethodKeys.contains(methodKey)) {
        continue;
      }

      Map<Class<?>, Method> methodsByReturnType = entry.getValue();
      for (Method methodToDelegate : methodsByReturnType.values()) {
        writeDelegatedMethod(visitor, generatedType, delegateType, methodToDelegate);
      }
    }
  }
Example #11
0
  public DocIndexMetaData(IndexMetaData metaData, TableIdent ident) throws IOException {
    this.ident = ident;
    this.metaData = metaData;
    this.isAlias = !metaData.getIndex().equals(ident.esName());
    this.numberOfShards = metaData.numberOfShards();
    final Settings settings = metaData.getSettings();
    this.numberOfReplicas = NumberOfReplicas.fromSettings(settings);
    this.aliases = ImmutableSet.copyOf(metaData.aliases().keys().toArray(String.class));
    this.defaultMappingMetaData = this.metaData.mappingOrDefault(Constants.DEFAULT_MAPPING_TYPE);
    if (defaultMappingMetaData == null) {
      this.defaultMappingMap = new HashMap<>();
    } else {
      this.defaultMappingMap = this.defaultMappingMetaData.sourceAsMap();
    }
    this.tableParameters = TableParameterInfo.tableParametersFromIndexMetaData(metaData);

    prepareCrateMeta();
  }
Example #12
0
 /**
  * Returns all the fields that match the given pattern. If the pattern is prefixed with a type
  * then the fields will be returned with a type prefix.
  */
 public Set<String> simpleMatchToIndexNames(String pattern) {
   if (!Regex.isSimpleMatchPattern(pattern)) {
     return ImmutableSet.of(pattern);
   }
   int dotIndex = pattern.indexOf('.');
   if (dotIndex != -1) {
     String possibleType = pattern.substring(0, dotIndex);
     DocumentMapper possibleDocMapper = mappers.get(possibleType);
     if (possibleDocMapper != null) {
       Set<String> typedFields = Sets.newHashSet();
       for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) {
         typedFields.add(possibleType + "." + indexName);
       }
       return typedFields;
     }
   }
   return fieldMappers.simpleMatchToIndexNames(pattern);
 }
Example #13
0
 /**
  * Returns all the fields that match the given pattern, with an optional narrowing based on a list
  * of types.
  */
 public Set<String> simpleMatchToIndexNames(String pattern, @Nullable String[] types) {
   if (types == null || types.length == 0) {
     return simpleMatchToIndexNames(pattern);
   }
   if (types.length == 1 && types[0].equals("_all")) {
     return simpleMatchToIndexNames(pattern);
   }
   if (!Regex.isSimpleMatchPattern(pattern)) {
     return ImmutableSet.of(pattern);
   }
   Set<String> fields = Sets.newHashSet();
   for (String type : types) {
     DocumentMapper possibleDocMapper = mappers.get(type);
     if (possibleDocMapper != null) {
       for (String indexName : possibleDocMapper.mappers().simpleMatchToIndexNames(pattern)) {
         fields.add(indexName);
       }
     }
   }
   return fields;
 }
Example #14
0
 public Set<String> getSubSchemaNames() {
   return ImmutableSet.of();
 }
Example #15
0
public class Schema {
  private static final Logger logger = LoggerFactory.getLogger(Schema.class);

  public static final Schema instance = new Schema();

  /**
   * longest permissible KS or CF name. Our main concern is that filename not be more than 255
   * characters; the filename will contain both the KS and CF names. Since non-schema-name
   * components only take up ~64 characters, we could allow longer names than this, but on Windows,
   * the entire path should be not greater than 255 characters, so a lower limit here helps avoid
   * problems. See CASSANDRA-4110.
   */
  public static final int NAME_LENGTH = 48;

  /* metadata map for faster table lookup */
  private final Map<String, KSMetaData> tables = new NonBlockingHashMap<String, KSMetaData>();

  /* Table objects, one per keyspace. Only one instance should ever exist for any given keyspace. */
  private final Map<String, Table> tableInstances = new NonBlockingHashMap<String, Table>();

  /* metadata map for faster ColumnFamily lookup */
  private final BiMap<Pair<String, String>, UUID> cfIdMap = HashBiMap.create();
  // mapping from old ColumnFamily Id (Integer) to a new version which is UUID
  private final BiMap<Integer, UUID> oldCfIdMap = HashBiMap.create();

  private volatile UUID version;

  // 59adb24e-f3cd-3e02-97f0-5b395827453f
  public static final UUID emptyVersion;
  public static final ImmutableSet<String> systemKeyspaceNames =
      ImmutableSet.of(Table.SYSTEM_KS, Tracing.TRACE_KS);

  static {
    try {
      emptyVersion = UUID.nameUUIDFromBytes(MessageDigest.getInstance("MD5").digest());
    } catch (NoSuchAlgorithmException e) {
      throw new AssertionError();
    }
  }

  /** Initialize empty schema object */
  public Schema() {}

  /**
   * Load up non-system tables
   *
   * @param tableDefs The non-system table definitions
   * @return self to support chaining calls
   */
  public Schema load(Collection<KSMetaData> tableDefs) {
    for (KSMetaData def : tableDefs) load(def);

    return this;
  }

  /**
   * Load specific keyspace into Schema
   *
   * @param keyspaceDef The keyspace to load up
   * @return self to support chaining calls
   */
  public Schema load(KSMetaData keyspaceDef) {
    for (CFMetaData cfm : keyspaceDef.cfMetaData().values()) load(cfm);

    setTableDefinition(keyspaceDef);

    return this;
  }

  /**
   * Get table instance by name
   *
   * @param tableName The name of the table
   * @return Table object or null if table was not found
   */
  public Table getTableInstance(String tableName) {
    return tableInstances.get(tableName);
  }

  /**
   * Store given Table instance to the schema
   *
   * @param table The Table instance to store
   * @throws IllegalArgumentException if Table is already stored
   */
  public void storeTableInstance(Table table) {
    if (tableInstances.containsKey(table.name))
      throw new IllegalArgumentException(
          String.format("Table %s was already initialized.", table.name));

    tableInstances.put(table.name, table);
  }

  /**
   * Remove table from schema
   *
   * @param tableName The name of the table to remove
   * @return removed table instance or null if it wasn't found
   */
  public Table removeTableInstance(String tableName) {
    return tableInstances.remove(tableName);
  }

  /**
   * Remove table definition from system
   *
   * @param ksm The table definition to remove
   */
  public void clearTableDefinition(KSMetaData ksm) {
    tables.remove(ksm.name);
  }

  /**
   * Given a table name & column family name, get the column family meta data. If the table name or
   * column family name is not valid this function returns null.
   *
   * @param tableName The table name
   * @param cfName The ColumnFamily name
   * @return ColumnFamily Metadata object or null if it wasn't found
   */
  public CFMetaData getCFMetaData(String tableName, String cfName) {
    assert tableName != null;
    KSMetaData ksm = tables.get(tableName);
    return (ksm == null) ? null : ksm.cfMetaData().get(cfName);
  }

  /**
   * Get ColumnFamily metadata by its identifier
   *
   * @param cfId The ColumnFamily identifier
   * @return metadata about ColumnFamily
   */
  public CFMetaData getCFMetaData(UUID cfId) {
    Pair<String, String> cf = getCF(cfId);
    return (cf == null) ? null : getCFMetaData(cf.left, cf.right);
  }

  public CFMetaData getCFMetaData(Descriptor descriptor) {
    return getCFMetaData(descriptor.ksname, descriptor.cfname);
  }

  /**
   * Get type of the ColumnFamily but it's keyspace/name
   *
   * @param ksName The keyspace name
   * @param cfName The ColumnFamily name
   * @return The type of the ColumnFamily
   */
  public ColumnFamilyType getColumnFamilyType(String ksName, String cfName) {
    assert ksName != null && cfName != null;
    CFMetaData cfMetaData = getCFMetaData(ksName, cfName);
    return (cfMetaData == null) ? null : cfMetaData.cfType;
  }

  /**
   * Get column comparator for ColumnFamily but it's keyspace/name
   *
   * @param ksName The keyspace name
   * @param cfName The ColumnFamily name
   * @return The comparator of the ColumnFamily
   */
  public AbstractType<?> getComparator(String ksName, String cfName) {
    assert ksName != null;
    CFMetaData cfmd = getCFMetaData(ksName, cfName);
    if (cfmd == null)
      throw new IllegalArgumentException(
          "Unknown ColumnFamily " + cfName + " in keyspace " + ksName);
    return cfmd.comparator;
  }

  /**
   * Get subComparator of the ColumnFamily
   *
   * @param ksName The keyspace name
   * @param cfName The ColumnFamily name
   * @return The subComparator of the ColumnFamily
   */
  public AbstractType<?> getSubComparator(String ksName, String cfName) {
    assert ksName != null;
    return getCFMetaData(ksName, cfName).subcolumnComparator;
  }

  /**
   * Get value validator for specific column
   *
   * @param ksName The keyspace name
   * @param cfName The ColumnFamily name
   * @param column The name of the column
   * @return value validator specific to the column or default (per-cf) one
   */
  public AbstractType<?> getValueValidator(String ksName, String cfName, ByteBuffer column) {
    return getCFMetaData(ksName, cfName).getValueValidator(column);
  }

  /**
   * Get metadata about table by its name
   *
   * @param table The name of the table
   * @return The table metadata or null if it wasn't found
   */
  public KSMetaData getKSMetaData(String table) {
    assert table != null;
    return tables.get(table);
  }

  /** @return collection of the non-system tables */
  public List<String> getNonSystemTables() {
    return ImmutableList.copyOf(Sets.difference(tables.keySet(), systemKeyspaceNames));
  }

  /**
   * Get metadata about table by its name
   *
   * @param table The name of the table
   * @return The table metadata or null if it wasn't found
   */
  public KSMetaData getTableDefinition(String table) {
    return getKSMetaData(table);
  }

  /**
   * Get metadata about table inner ColumnFamilies
   *
   * @param tableName The name of the table
   * @return metadata about ColumnFamilies the belong to the given table
   */
  public Map<String, CFMetaData> getTableMetaData(String tableName) {
    assert tableName != null;
    KSMetaData ksm = tables.get(tableName);
    assert ksm != null;
    return ksm.cfMetaData();
  }

  /** @return collection of the all table names registered in the system (system and non-system) */
  public Set<String> getTables() {
    return tables.keySet();
  }

  /**
   * @return collection of the metadata about all tables registered in the system (system and
   *     non-system)
   */
  public Collection<KSMetaData> getTableDefinitions() {
    return tables.values();
  }

  /**
   * Update (or insert) new table definition
   *
   * @param ksm The metadata about table
   */
  public void setTableDefinition(KSMetaData ksm) {
    assert ksm != null;
    tables.put(ksm.name, ksm);
  }

  /* ColumnFamily query/control methods */

  public void addOldCfIdMapping(Integer oldId, UUID newId) {
    if (oldId == null) return;

    oldCfIdMap.put(oldId, newId);
  }

  public UUID convertOldCfId(Integer oldCfId) throws UnknownColumnFamilyException {
    UUID cfId = oldCfIdMap.get(oldCfId);

    if (cfId == null)
      throw new UnknownColumnFamilyException(
          "ColumnFamily identified by old " + oldCfId + " was not found.", null);

    return cfId;
  }

  public Integer convertNewCfId(UUID newCfId) {
    return oldCfIdMap.containsValue(newCfId) ? oldCfIdMap.inverse().get(newCfId) : null;
  }

  /**
   * @param cfId The identifier of the ColumnFamily to lookup
   * @return The (ksname,cfname) pair for the given id, or null if it has been dropped.
   */
  public Pair<String, String> getCF(UUID cfId) {
    return cfIdMap.inverse().get(cfId);
  }

  /**
   * Lookup keyspace/ColumnFamily identifier
   *
   * @param ksName The keyspace name
   * @param cfName The ColumnFamily name
   * @return The id for the given (ksname,cfname) pair, or null if it has been dropped.
   */
  public UUID getId(String ksName, String cfName) {
    return cfIdMap.get(Pair.create(ksName, cfName));
  }

  /**
   * Load individual ColumnFamily Definition to the schema (to make ColumnFamily lookup faster)
   *
   * @param cfm The ColumnFamily definition to load
   */
  public void load(CFMetaData cfm) {
    Pair<String, String> key = Pair.create(cfm.ksName, cfm.cfName);

    if (cfIdMap.containsKey(key))
      throw new RuntimeException(
          String.format(
              "Attempting to load already loaded column family %s.%s", cfm.ksName, cfm.cfName));

    logger.debug("Adding {} to cfIdMap", cfm);
    cfIdMap.put(key, cfm.cfId);
  }

  /**
   * Used for ColumnFamily data eviction out from the schema
   *
   * @param cfm The ColumnFamily Definition to evict
   */
  public void purge(CFMetaData cfm) {
    cfIdMap.remove(Pair.create(cfm.ksName, cfm.cfName));
  }

  /* Version control */

  /** @return current schema version */
  public UUID getVersion() {
    return version;
  }

  /**
   * Read schema from system table and calculate MD5 digest of every row, resulting digest will be
   * converted into UUID which would act as content-based version of the schema.
   */
  public void updateVersion() {
    try {
      MessageDigest versionDigest = MessageDigest.getInstance("MD5");

      for (Row row : SystemTable.serializedSchema()) {
        if (invalidSchemaRow(row) || ignoredSchemaRow(row)) continue;

        row.cf.updateDigest(versionDigest);
      }

      version = UUID.nameUUIDFromBytes(versionDigest.digest());
      SystemTable.updateSchemaVersion(version);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /*
   * Like updateVersion, but also announces via gossip
   */
  public void updateVersionAndAnnounce() {
    updateVersion();
    MigrationManager.passiveAnnounce(version);
  }

  /** Clear all KS/CF metadata and reset version. */
  public synchronized void clear() {
    for (String table : getNonSystemTables()) {
      KSMetaData ksm = getTableDefinition(table);
      for (CFMetaData cfm : ksm.cfMetaData().values()) purge(cfm);
      clearTableDefinition(ksm);
    }

    updateVersionAndAnnounce();
  }

  public static boolean invalidSchemaRow(Row row) {
    return row.cf == null || (row.cf.isMarkedForDelete() && row.cf.isEmpty());
  }

  public static boolean ignoredSchemaRow(Row row) {
    try {
      return systemKeyspaceNames.contains(ByteBufferUtil.string(row.key.key));
    } catch (CharacterCodingException e) {
      throw new RuntimeException(e);
    }
  }
}
  /**
   * Generates an implementation of the given managed type.
   *
   * <p>The generated class will implement/extend the managed type and will:
   *
   * <ul>
   *   <li>provide implementations for abstract getters and setters that delegate to model nodes
   *   <li>provide a `toString()` implementation
   *   <li>mix-in implementation of {@link ManagedInstance}
   *   <li>provide a constructor that accepts a {@link ModelElementState}, which will be used to
   *       implement the above.
   * </ul>
   *
   * In case a delegate schema is supplied, the generated class will also have:
   *
   * <ul>
   *   <li>a constructor that also takes a delegate instance
   *   <li>methods that call through to the delegate instance
   * </ul>
   */
  public <T, M extends T, D extends T> Class<? extends M> generate(
      StructSchema<M> viewSchema, @Nullable StructSchema<D> delegateSchema) {
    if (delegateSchema != null
        && Modifier.isAbstract(delegateSchema.getType().getConcreteClass().getModifiers())) {
      throw new IllegalArgumentException("Delegate type must be null or a non-abstract type");
    }
    ClassWriter visitor = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);

    ModelType<M> viewType = viewSchema.getType();

    StringBuilder generatedTypeNameBuilder = new StringBuilder(viewType.getName());
    if (delegateSchema != null) {
      generatedTypeNameBuilder
          .append("$BackedBy_")
          .append(delegateSchema.getType().getName().replaceAll("\\.", "_"));
    } else {
      generatedTypeNameBuilder.append("$Impl");
    }

    String generatedTypeName = generatedTypeNameBuilder.toString();
    Type generatedType = Type.getType("L" + generatedTypeName.replaceAll("\\.", "/") + ";");

    Class<M> viewClass = viewType.getConcreteClass();
    Class<?> superclass;
    final ImmutableSet.Builder<String> interfacesToImplement = ImmutableSet.builder();
    final ImmutableSet.Builder<Class<?>> typesToDelegate = ImmutableSet.builder();
    typesToDelegate.add(viewClass);
    interfacesToImplement.add(MANAGED_INSTANCE_TYPE);
    if (viewClass.isInterface()) {
      superclass = Object.class;
      interfacesToImplement.add(Type.getInternalName(viewClass));
    } else {
      superclass = viewClass;
    }
    // TODO:LPTR This should be removed once BinaryContainer is a ModelMap
    // We need to also implement all the interfaces of the delegate type because otherwise
    // BinaryContainer won't recognize managed binaries as BinarySpecInternal
    if (delegateSchema != null) {
      ModelSchemaUtils.walkTypeHierarchy(
          delegateSchema.getType().getConcreteClass(),
          new ModelSchemaUtils.TypeVisitor<D>() {
            @Override
            public void visitType(Class<? super D> type) {
              if (type.isInterface()) {
                typesToDelegate.add(type);
                interfacesToImplement.add(Type.getInternalName(type));
              }
            }
          });
    }

    generateProxyClass(
        visitor,
        viewSchema,
        delegateSchema,
        interfacesToImplement.build(),
        typesToDelegate.build(),
        generatedType,
        Type.getType(superclass));

    ClassLoader targetClassLoader = viewClass.getClassLoader();
    if (delegateSchema != null) {
      // TODO - remove this once the above is removed
      try {
        viewClass.getClassLoader().loadClass(delegateSchema.getType().getConcreteClass().getName());
      } catch (ClassNotFoundException e) {
        // Delegate class is not visible to managed view type -> view type is more general than
        // delegate type, so use the delegate classloader instead
        targetClassLoader = delegateSchema.getType().getConcreteClass().getClassLoader();
      }
    }

    return defineClass(visitor, targetClassLoader, generatedTypeName);
  }
Example #17
0
  public static class Builder {

    private String[] arguments = new String[0];
    private Set<Character> expectedValueFlags = ImmutableSet.of();
    private boolean allowHangingFlag = false;
    private Namespace namespace = new Namespace();

    public String[] getArguments() {
      return Arrays.copyOf(arguments, arguments.length);
    }

    public Builder setArguments(String[] arguments) {
      checkNotNull(arguments, "arguments");
      String[] newArguments = new String[arguments.length + 1];
      newArguments[0] = "_";
      System.arraycopy(arguments, 0, newArguments, 1, arguments.length);
      this.arguments = newArguments;
      return this;
    }

    public Builder setArguments(String arguments) {
      checkNotNull(arguments, "arguments");
      setArguments(split(arguments));
      return this;
    }

    public Builder setCommandAndArguments(String[] arguments) {
      checkNotNull(arguments, "arguments");
      this.arguments = Arrays.copyOf(arguments, arguments.length);
      return this;
    }

    public Builder setCommandAndArguments(String arguments) {
      checkNotNull(arguments, "arguments");
      setCommandAndArguments(split(arguments));
      return this;
    }

    public Set<Character> getExpectedValueFlags() {
      return expectedValueFlags;
    }

    public Builder setExpectedValueFlags(Set<Character> expectedValueFlags) {
      this.expectedValueFlags = ImmutableSet.copyOf(expectedValueFlags);
      return this;
    }

    public boolean isAllowHangingFlag() {
      return allowHangingFlag;
    }

    public Builder setAllowHangingFlag(boolean allowHangingFlag) {
      this.allowHangingFlag = allowHangingFlag;
      return this;
    }

    public Namespace getNamespace() {
      return namespace;
    }

    public Builder setNamespace(Namespace namespace) {
      checkNotNull(namespace, "namespace");
      this.namespace = namespace;
      return this;
    }

    public CommandContext build() throws CommandException {
      return new CommandContext(arguments, expectedValueFlags, allowHangingFlag, namespace);
    }
  }
Example #18
0
  /**
   * Parse the given array of arguments.
   *
   * <p>Empty arguments are removed from the list of arguments.
   *
   * @param args an array with arguments
   * @param expectedValueFlags a set containing all value flags (pass null to disable value flag
   *     parsing)
   * @param allowHangingFlag true if hanging flags are allowed
   * @param namespace the locals, null to create empty one
   * @throws CommandException thrown on a parsing error
   */
  public CommandContext(
      String[] args,
      Set<Character> expectedValueFlags,
      boolean allowHangingFlag,
      Namespace namespace)
      throws CommandException {
    if (expectedValueFlags == null) {
      expectedValueFlags = Collections.emptySet();
    }

    originalArgs = args;
    command = args[0];
    this.namespace = namespace != null ? namespace : new Namespace();
    boolean isHanging = false;
    SuggestionContext suggestionContext = SuggestionContext.hangingValue();

    // Eliminate empty args and combine multiword args first
    List<Integer> argIndexList = new ArrayList<Integer>(args.length);
    List<String> argList = new ArrayList<String>(args.length);
    for (int i = 1; i < args.length; ++i) {
      isHanging = false;

      String arg = args[i];
      if (arg.isEmpty()) {
        isHanging = true;
        continue;
      }

      argIndexList.add(i);

      switch (arg.charAt(0)) {
        case '\'':
        case '"':
          final StringBuilder build = new StringBuilder();
          final char quotedChar = arg.charAt(0);

          int endIndex;
          for (endIndex = i; endIndex < args.length; ++endIndex) {
            final String arg2 = args[endIndex];
            if (arg2.charAt(arg2.length() - 1) == quotedChar && arg2.length() > 1) {
              if (endIndex != i) build.append(' ');
              build.append(arg2.substring(endIndex == i ? 1 : 0, arg2.length() - 1));
              break;
            } else if (endIndex == i) {
              build.append(arg2.substring(1));
            } else {
              build.append(' ').append(arg2);
            }
          }

          if (endIndex < args.length) {
            arg = build.toString();
            i = endIndex;
          }

          // In case there is an empty quoted string
          if (arg.isEmpty()) {
            continue;
          }
          // else raise exception about hanging quotes?
      }
      argList.add(arg);
    }

    // Then flags

    List<Integer> originalArgIndices = Lists.newArrayListWithCapacity(argIndexList.size());
    List<String> parsedArgs = Lists.newArrayListWithCapacity(argList.size());
    Map<Character, String> valueFlags = Maps.newHashMap();
    List<Character> booleanFlags = Lists.newArrayList();

    for (int nextArg = 0; nextArg < argList.size(); ) {
      // Fetch argument
      String arg = argList.get(nextArg++);
      suggestionContext = SuggestionContext.hangingValue();

      // Not a flag?
      if (arg.charAt(0) != '-' || arg.length() == 1 || !arg.matches("^-[a-zA-Z\\?]+$")) {
        if (!isHanging) {
          suggestionContext = SuggestionContext.lastValue();
        }

        originalArgIndices.add(argIndexList.get(nextArg - 1));
        parsedArgs.add(arg);
        continue;
      }

      // Handle flag parsing terminator --
      if (arg.equals("--")) {
        while (nextArg < argList.size()) {
          originalArgIndices.add(argIndexList.get(nextArg));
          parsedArgs.add(argList.get(nextArg++));
        }
        break;
      }

      // Go through the flag characters
      for (int i = 1; i < arg.length(); ++i) {
        char flagName = arg.charAt(i);

        if (expectedValueFlags.contains(flagName)) {
          if (valueFlags.containsKey(flagName)) {
            throw new CommandException("Value flag '" + flagName + "' already given");
          }

          if (nextArg >= argList.size()) {
            if (allowHangingFlag) {
              suggestionContext = SuggestionContext.flag(flagName);
              break;
            } else {
              throw new CommandException("No value specified for the '-" + flagName + "' flag.");
            }
          }

          // If it is a value flag, read another argument and add it
          valueFlags.put(flagName, argList.get(nextArg++));
          if (!isHanging) {
            suggestionContext = SuggestionContext.flag(flagName);
          }
        } else {
          booleanFlags.add(flagName);
        }
      }
    }

    ImmutableMap.Builder<Character, String> allFlagsBuilder =
        new ImmutableMap.Builder<Character, String>().putAll(valueFlags);
    for (Character flag : booleanFlags) {
      allFlagsBuilder.put(flag, "true");
    }

    this.parsedArgs = ImmutableList.copyOf(parsedArgs);
    this.originalArgIndices = ImmutableList.copyOf(originalArgIndices);
    this.booleanFlags = ImmutableSet.copyOf(booleanFlags);
    this.valueFlags = ImmutableMap.copyOf(valueFlags);
    this.allFlags = allFlagsBuilder.build();
    this.suggestionContext = suggestionContext;
  }
Example #19
0
 public Builder setExpectedValueFlags(Set<Character> expectedValueFlags) {
   this.expectedValueFlags = ImmutableSet.copyOf(expectedValueFlags);
   return this;
 }