Example usage for java.util Arrays copyOfRange

List of usage examples for java.util Arrays copyOfRange

Introduction

In this page you can find the example usage for java.util Arrays copyOfRange.

Prototype

public static boolean[] copyOfRange(boolean[] original, int from, int to) 

Source Link

Document

Copies the specified range of the specified array into a new array.

Usage

From source file:com.google.nigori.client.HashMigoriDatastore.java

/**
 * Verify that the value provided gives the correct hash when combined with the Revision
 * //from  w  w w . j a v a2  s  .  c  o m
 * @param value
 * @param revision
 * @return
 * @throws NigoriCryptographyException
 * @throws InvalidHashException
 */
private byte[] validateHash(byte[] value, Revision revision)
        throws NigoriCryptographyException, InvalidHashException {
    byte[] revBytes = revision.getBytes();
    byte[] hash = generateHash(value, Arrays.copyOfRange(revBytes, HASH_SIZE, revBytes.length));
    if (Arrays.equals(hash, revBytes)) {
        return value;
    } else {
        throw new InvalidHashException(revBytes, hash);
    }
}

From source file:d88.core.object.D88SObject.java

public D88SObject(byte[] d88Message) throws IOException, DataFormatException, Exception {
    if (this.properties == null) {
        this.properties = new HashMap<>();
    }/* w w w.  j a v  a  2s  .  co m*/
    // kim tra xem message c hp l khng > 3  byte
    if (d88Message.length >= 3) {
        // ly ra 3 byte cui  xc nh info
        // nhng file cn li l file rawdata cn unzip
        byte[] dataInfo = Arrays.copyOfRange(d88Message, d88Message.length - 3, d88Message.length);
        this.onRetoreInfo(dataInfo);
        byte[] rawData = Arrays.copyOfRange(d88Message, 0, d88Message.length - 3);
        String d88Decompress = D88SGzip.d88Decompress(rawData);
        JSONObject jsonModel = new JSONObject(d88Decompress);
        this.properties = this.toHashMap(jsonModel);
    }
}

From source file:com.trickl.math.lanczos.LanczosSolver.java

public Pair<DoubleMatrix2D, Info> getEigenvectorsWithInfo(double[] eigenvalues, RandomGenerator randomGenerator,
        int maxIterations) {

    List<DoubleMatrix1D> eigvectors = new LinkedList<>(); // contains ritz vectors.
    List<List<Double>> Tvectors = new LinkedList<>(); // contains

    // calculation of eigen vectors of T matrix(consists of alphas & betas):    
    int start = 0;
    int end = eigenvalues.length;

    int n1 = alpha.length;
    double mamax, error, lambda;
    Pair<Double, Double> a_and_b;
    int ma = 0, deltam;
    int nth, maMax = 0, count;
    List<Double> eigenval_a = new LinkedList<>();
    List<Double> residuum = new LinkedList<>();
    List<ErrorInfo> status = new LinkedList<>();

    findM1M2(eigenvalues);//from ww  w  .ja va2s. co  m
    int M1_itr = 0;
    int M2_itr = 0;

    for (int pos = start; pos < end; ++pos) {

        int maxcount = 10;
        lambda = 0;
        count = 0;
        ErrorInfo errInf = ErrorInfo.OK;

        // calculation of ma starts:
        if (M1[M1_itr] != 0 && M2[M2_itr] != 0) {
            ma = (3 * (M1[M1_itr]) + M2[M2_itr]) / 4 + 1;
            deltam = ((3 * (M1[M1_itr]) + 5 * (M2[M2_itr])) / 8 + 1 - ma) / 10 + 1;
        } else if (M1[M1_itr] != 0 && M2[M2_itr] == 0) {
            ma = (5 * (M1[M1_itr])) / 4 + 1;
            mamax = Math.min((11 * n1) / 8 + 12, (13 * (M1[M1_itr])) / 8 + 1);
            deltam = (int) ((mamax - ma) / 10) + 1;
            if (maxIterations > 0) {
                maxcount = maxIterations / deltam;
            }
        } else {
            errInf = ErrorInfo.NO_EIGENVALUE;
            deltam = 0;
            ma = 0;
        } // calculation of ma ends.

        eigvectors.add(DoubleFactory1D.dense.make(startvector.size()));
        // new ritz vector is being added in eigvectors.

        List<Double> Tvector = new LinkedList<>();
        Tvectors.add(Tvector);
        // new T matrix vector is being added in Tvectors.

        if (ma == 0) {
            eigvectors.get(eigvectors.size() - 1).assign(0);
        }

        if (ma != 0) {

            double[] eval;
            double[] nthEigenvector = null;
            do {
                if (ma > alpha.length) { // size of T matrix is to be increased.
                    LanczosIteration iter = new LanczosIterationFixed(ma);

                    generateTMatrix(iter);
                }

                count++;

                // on return, z contains all orthonormal eigen vectors of T matrix.
                EigenDecomposition eigenDecomposition = new EigenDecomposition(Arrays.copyOfRange(alpha, 0, ma),
                        Arrays.copyOfRange(beta, 0, ma));
                eval = eigenDecomposition.getRealEigenvalues();
                Arrays.sort(eval); // Consistent with IETL

                // search for the value of nth starts, where nth is the nth eigen vector in z.            
                for (nth = ma - 1; nth >= 0; nth--) {
                    if (Math.abs(eval[nth] - eigenvalues[pos]) <= threshold) {
                        break;
                    }
                }

                // search for the value of ith ends, where ith is the ith eigen vector in z.            
                if (nth == -1) {
                    error = 0;
                    ma = 0;
                    eigvectors.get(eigvectors.size() - 1).assign(0);
                    errInf = ErrorInfo.NO_EIGENVALUE;
                } else {
                    nthEigenvector = eigenDecomposition.getEigenvector(ma - 1 - nth).toArray();
                    error = Math.abs(beta[ma - 1] * nthEigenvector[ma - 1]); // beta[ma - 1] = betaMplusOne.
                    if (error > errorTolerance) {
                        ma += deltam;
                    }
                } // end of else
            } while (error > errorTolerance && count < maxcount);

            if (error > errorTolerance) {
                eigvectors.get(eigvectors.size() - 1).assign(0);
                errInf = ErrorInfo.NOT_CALCULATED;
            } else { // if error is small enough.
                if (ma != 0) {
                    for (int i = 0; i < ma; i++) {
                        (Tvectors.get(Tvectors.size() - 1)).add(nthEigenvector[i]);
                    }
                    if (ma > maMax) {
                        maMax = ma;
                    }
                    lambda = eval[nth];
                }
            }
        }

        eigenval_a.add(lambda); // for Info object.
        Ma.add(ma); // for Info object.
        status.add(errInf);
        M1_itr++;
        M2_itr++;
    } // end of while(in_eigvals_start !=  in_eigvals_end)

    // basis transformation of eigen vectors of T. These vectors are good 
    // approximation of eigen vectors of actual matrix.  
    int eigenvectors_itr;
    int Tvectors_itr;

    a_and_b = makeFirstStep(randomGenerator);
    if (a_and_b.getFirst() != alpha[0] || a_and_b.getSecond() != beta[0]) {
        throw new RuntimeException("T-matrix problem at first step");
    }

    eigenvectors_itr = 0;
    Tvectors_itr = 0;
    while (eigenvectors_itr != end) {
        if (!Tvectors.get(Tvectors_itr).isEmpty()) {
            DoubleMatrix1D eigvector = eigvectors.get(eigenvectors_itr);
            eigvector.assign(0);
            eigvector.assign(startvector, PlusMult.plusMult(Tvectors.get(Tvectors_itr).get(0)));
            eigvector.assign(vec2, PlusMult.plusMult(Tvectors.get(Tvectors_itr).get(1)));
        }
        eigenvectors_itr++;
        Tvectors_itr++;
    }
    vec2index = 2;
    for (int j = 2; j < maMax; j++) {
        a_and_b = makeStep(j - 1);
        if (a_and_b.getFirst() != alpha[j - 1] || a_and_b.getSecond() != beta[j - 1]) {
            throw new RuntimeException("T-matrix problem");
        }

        ++vec2index;
        eigenvectors_itr = 0;
        Tvectors_itr = 0;
        while (eigenvectors_itr != end) {
            if (Tvectors.get(Tvectors_itr).size() > j) {
                DoubleMatrix1D eigvector = eigvectors.get(eigenvectors_itr);
                eigvector.assign(vec2, PlusMult.plusMult(Tvectors.get(Tvectors_itr).get(j)));
            }
            // vec2 is being added in one vector of eigvectors.
            eigenvectors_itr++;
            Tvectors_itr++;
        }
    }
    // end of basis transformation.  // end of basis transformation.  

    // copying to the output iterator & residuum calculation starts:    
    int i = 0;
    DoubleMatrix2D eigenvectors = DoubleFactory2D.dense.make(startvector.size(), end - start);

    for (eigenvectors_itr = start; eigenvectors_itr != end; eigenvectors_itr++) {
        DoubleMatrix1D eigvector = eigvectors.get(eigenvectors_itr);
        eigenvectors.viewColumn(i).assign(eigvector);
        matrix.zMult(eigvector, vec3);
        vec3.assign(eigvector, PlusMult.minusMult(eigenval_a.get(i)));

        // now vec3 is (A*v - eigenval_a*v); *eigenvectors_itr) is being added in vec3.
        residuum.add(norm2(vec3));
        i++;
    } // copying to the output iterator ends.    

    Info info = new Info(M1, M2, Ma, eigenval_a, residuum, status);
    return new Pair<>(eigenvectors, info);
}

From source file:co.cask.tigon.DistributedMain.java

public void startUp(PrintStream out) throws Exception {
    registerShutDownHook();//from ww w  .j  av a 2 s .  c  o  m
    flowOperations.startAndWait();
    List<String> commandList = Lists.newArrayList();
    for (CLICommands cliCommand : CLICommands.values()) {
        commandList.add(cliCommand.toString().toLowerCase());
    }
    consoleReader.setPrompt("tigon> ");
    String line;
    while ((line = consoleReader.readLine()) != null) {
        String[] args = line.split("\\s+");
        String command = args[0].toUpperCase();
        try {
            CLICommands cmd = null;
            try {
                cmd = CLICommands.valueOf(command);
            } catch (IllegalArgumentException e) {
                out.println("Available Commands : ");
                out.println(StringUtils.join(commandList, ", "));
                continue;
            }

            if (args.length < cmd.getArgCount()) {
                throw new InvalidCLIArgumentException(cmd.printHelp());
            }

            if (cmd.equals(CLICommands.START)) {
                Map<String, String> runtimeArgs = Maps.newHashMap();
                if (args.length > cmd.getArgCount()) {
                    try {
                        runtimeArgs = DeployClient
                                .fromPosixArray(Arrays.copyOfRange(args, cmd.getArgCount(), args.length));
                    } catch (IllegalArgumentException e) {
                        LOG.error("Runtime Args are not in the correct format [ --key1=val1 --key2=val2 ]");
                        continue;
                    }
                }
                flowOperations.startFlow(new File(args[1]), args[2], runtimeArgs);
            } else if (cmd.equals(CLICommands.LIST)) {
                out.println(StringUtils.join(flowOperations.listAllFlows(), ", "));
            } else if (cmd.equals(CLICommands.STOP)) {
                flowOperations.stopFlow(args[1]);
            } else if (cmd.equals(CLICommands.DELETE)) {
                flowOperations.deleteFlow(args[1]);
            } else if (cmd.equals(CLICommands.SET)) {
                flowOperations.setInstances(args[1], args[2], Integer.valueOf(args[3]));
            } else if (cmd.equals(CLICommands.STATUS)) {
                Service.State state = flowOperations.getStatus(args[1]);
                String status = (state != null) ? state.toString() : "NOT FOUND";
                out.println(status);
            } else if (cmd.equals(CLICommands.FLOWLETINFO)) {
                out.println(String.format("%-20s %s", "Flowlet Name", "Instance Count"));
                Map<String, Integer> flowletInfoMap = flowOperations.getFlowInfo(args[1]);
                for (Map.Entry<String, Integer> flowletInfo : flowletInfoMap.entrySet()) {
                    out.println(String.format("%-20s %s", flowletInfo.getKey(), flowletInfo.getValue()));
                }
            } else if (cmd.equals(CLICommands.DISCOVER)) {
                for (InetSocketAddress socketAddress : flowOperations.discover(args[1], args[2])) {
                    out.println(String.format("%s:%s", socketAddress.getHostName(), socketAddress.getPort()));
                }
            } else if (cmd.equals(CLICommands.SHOWLOGS)) {
                flowOperations.addLogHandler(args[1], System.out);
            } else if (cmd.equals(CLICommands.SERVICEINFO)) {
                out.println(StringUtils.join(flowOperations.getServices(args[1]), "\n"));
            } else if (cmd.equals(CLICommands.VERSION)) {
                out.println(ProjectInfo.getVersion().getBuildVersion());
            } else if (cmd.equals(CLICommands.HELP)) {
                try {
                    out.println(CLICommands.valueOf(args[1].toUpperCase()).printHelp());
                } catch (IllegalArgumentException e) {
                    out.println("Command Not Found");
                }
            } else {
                //QUIT Command
                break;
            }
        } catch (InvalidCLIArgumentException e) {
            out.println(e.getMessage());
        }
    }
}

From source file:com.wso2telco.gsma.authenticators.ConsentAuthenticator.java

@Override
protected void initiateAuthenticationRequest(HttpServletRequest request, HttpServletResponse response,
        AuthenticationContext context) throws AuthenticationFailedException {
    log.info("Initiating authentication request");
    try {/*from   w  w  w .  j  av  a2  s  . com*/
        String msisdn = context.getProperty(Constants.MSISDN).toString();
        if (msisdn != null && !msisdn.isEmpty()) {
            Object scopes = context.getProperty(Constants.TELCO_SCOPE);
            if (scopes != null) {
                String[] scopesArray = scopes.toString().split("\\s+");
                String[] api_Scopes = Arrays.copyOfRange(scopesArray, 1, scopesArray.length);
                if (api_Scopes != null && api_Scopes.length > 0) {
                    String operator = context.getProperty(Constants.OPERATOR).toString();
                    boolean enableapproveall = true;
                    Map<String, String> approveNeededScopes = new HashedMap();
                    List<String> approvedScopes = new ArrayList<>();
                    String clientID = context.getProperty(Constants.CLIENT_ID).toString();
                    for (String scope : api_Scopes) {
                        String consent[] = DBUtils.getConsentStatus(scope, clientID, operator);
                        if (consent != null && consent.length == 2 && !consent[0].isEmpty()
                                && consent[0].contains("approve")) {
                            boolean approved = DBUtils.getUserConsentScopeApproval(msisdn, scope, clientID,
                                    operator);
                            if (approved) {
                                approvedScopes.add(scope);
                            } else {
                                approveNeededScopes.put(scope, consent[1]);
                            }
                            if (consent[0].equalsIgnoreCase("approve")) {
                                enableapproveall = false;
                            }
                        }
                    }
                    context.setProperty(Constants.APPROVE_NEEDED_SCOPES, approveNeededScopes);
                    context.setProperty(Constants.APPROVED_SCOPES, approvedScopes);
                    context.setProperty(Constants.APPROVE_ALL_ENABLE, enableapproveall);
                    boolean isConsentGiven = Constants.USER_ACTION_REG_CONSENT
                            .equals(request.getParameter(Constants.ACTION));
                    String logoPath = DBUtils.getSPConfigValue(operator, clientID, Constants.SP_LOGO);
                    if (logoPath != null && !logoPath.isEmpty()) {
                        context.setProperty(Constants.SP_LOGO, logoPath);
                    }
                    boolean registering = (boolean) context.getProperty(Constants.IS_REGISTERING);
                    if (!approveNeededScopes.isEmpty()) {
                        DataPublisherUtil.updateAndPublishUserStatus(
                                (UserStatus) context.getParameter(Constants.USER_STATUS_DATA_PUBLISHING_PARAM),
                                DataPublisherUtil.UserState.CONCENT_AUTH_REDIRECT_CONSENT_PAGE,
                                "Redirecting to consent page");
                        if (isConsentGiven) {
                            response.sendRedirect("/authenticationendpoint/user_consent.do?sessionDataKey="
                                    + context.getContextIdentifier());
                        } else {
                            response.sendRedirect("/authenticationendpoint/user_consent.do?sessionDataKey="
                                    + context.getContextIdentifier() + "&registering=" + registering);
                        }
                    } else {
                        if (!approvedScopes.isEmpty()) {
                            response.sendRedirect("/commonauth/?sessionDataKey="
                                    + context.getContextIdentifier() + "&action=default");
                        } else {
                            throw new AuthenticationFailedException(
                                    "Authenticator failed- Approval needed scopes not found");
                        }
                    }
                } else {
                    throw new AuthenticationFailedException(
                            "Authenticator failed- Approval needed scopes not found");
                }
            } else {
                throw new AuthenticationFailedException(
                        "Authenticator failed- Approval needed scopes not found");
            }
        } else {
            throw new AuthenticationFailedException("Authenticator failed- MSISDN not found");
        }
    } catch (Exception e) {
        log.error("Error occurred while processing request", e);
        DataPublisherUtil.updateAndPublishUserStatus(
                (UserStatus) context.getParameter(Constants.USER_STATUS_DATA_PUBLISHING_PARAM),
                DataPublisherUtil.UserState.CONCENT_AUTH_PROCESSING_FAIL, e.getMessage());
        throw new AuthenticationFailedException("Authenticator failed", e);
    }
}

From source file:net.lethargiclion.informaban.InformaBanCommandExecutor.java

/**
 * Handles the /ipban command./* w  w w.jav a2 s .  co  m*/
 * 
 * @param sender
 *            The CommandSender executing this command.
 * @param args
 *            The command arguments.
 * @return False if a usage message should be displayed.
 */
private boolean commandIPBan(CommandSender sender, String[] args) {

    if (args.length == 1)
        sender.sendMessage(plugin.messages.getString("command.ban.reasonRequired"));

    String subject = null, ip = null;
    UUID uuid = null;

    if (args.length > 1) {
        if (InetAddresses.isInetAddress(args[0])) {
            ip = subject = args[0];
        } else {
            // Assume it is a player name and try to get their IP address
            Player p = sender.getServer().getPlayer(args[0]);
            subject = p.getName();
            uuid = p.getUniqueId();
            ip = p.getAddress().getAddress().getHostAddress();
        }

        // Check for existing IP ban
        if (Bukkit.getIPBans().contains(subject)) {
            sender.sendMessage(plugin.messages.getString("error.IPAlreadyBanned"));
            return true;
        }

        if (subject != null) {
            // Set up ban message
            String banReason = StringUtils.join(Arrays.copyOfRange(args, 1, args.length), ' ');

            // Log ban to console
            plugin.getLogger().info(MessageFormat.format(plugin.messages.getString("command.ban.consoleLog"),
                    new Object[] { sender.getName(), subject }));

            // Do the ban and record it
            IPBan b = new IPBan();
            b.apply(plugin.messages, uuid, subject, sender, banReason, Ban.PERMANENT);
            b.setSubjectIP(ip);
            plugin.getDatabase().insert(b); // Record the banning event
            plugin.getDatabase().insert(b.makeActiveEvent()); // Set the actual ban
        } else
            sender.sendMessage(plugin.messages.getString("error.playerNotFound"));
        return true;
    }
    return false;
}

From source file:io.redlink.solrlib.standalone.SolrServerConnector.java

private Object findInNamedList(NamedList namedList, String... path) {
    if (path.length < 1)
        return null;
    final Object value = namedList.get(path[0]);
    if (path.length == 1)
        return value;

    final NamedList nested = value instanceof NamedList ? ((NamedList) value) : null;
    if (nested != null)
        return findInNamedList(nested, Arrays.copyOfRange(path, 1, path.length));
    return null;// w  w  w . j  a v a2 s.  c  o m
}

From source file:net.centro.rtb.monitoringcenter.MetricCollectorImpl.java

@Override
public void removeMetricSet(MetricSet metricSet, String... names) {
    Preconditions.checkNotNull(metricSet, "metricSet cannot be null");

    String namespace = null;/*from   w w w  .  ja  v  a 2s .c  o  m*/
    if (names != null && names.length > 0) {
        namespace = buildFullName(names[0], Arrays.copyOfRange(names, 1, names.length), null);
    }

    removeMetricSetImpl(metricSet, namespace);
}

From source file:example.DecrypterException.java

/**
 * Performs the decryption algorithm.// w w w.  j a v  a  2  s  . c o m
 *
 * This method decrypts the ciphertext using the encryption key and verifies
 * the integrity bits with the integrity key. The encrypted format is:
 * {initialization_vector (16 bytes)}{ciphertext}{integrity (4 bytes)}
 * https://developers.google.com/ad-exchange/rtb/response-guide/decrypt-
 * hyperlocal,
 * https://developers.google.com/ad-exchange/rtb/response-guide/decrypt
 * -price and https://support.google.com/adxbuyer/answer/3221407?hl=en have
 * more details about the encrypted format of hyperlocal, winning price,
 * IDFA, hashed IDFA and Android Advertiser ID.
 */
public static byte[] decrypt(byte[] ciphertext, SecretKey encryptionKey, SecretKey integrityKey)
        throws DecrypterException {
    try {
        // Step 1. find the length of initialization vector and clear text.
        final int plaintext_length = ciphertext.length - INITIALIZATION_VECTOR_SIZE - SIGNATURE_SIZE;
        if (plaintext_length < 0) {
            throw new RuntimeException("The plain text length can't be negative.");
        }
        System.out.println(Arrays.toString(ciphertext));
        System.out.println(byte2hex(ciphertext));
        System.out.println(ciphertext.length);
        System.out.println(plaintext_length);

        byte[] iv = Arrays.copyOf(ciphertext, INITIALIZATION_VECTOR_SIZE);

        // Step 2. recover clear text
        final Mac hmacer = Mac.getInstance("HmacSHA1");
        hmacer.init(encryptionKey);

        final int ciphertext_end = INITIALIZATION_VECTOR_SIZE + plaintext_length;
        final byte[] plaintext = new byte[plaintext_length];
        boolean add_iv_counter_byte = true;
        for (int ciphertext_begin = INITIALIZATION_VECTOR_SIZE, plaintext_begin = 0; ciphertext_begin < ciphertext_end;) {
            System.out.println("=====> FOR:");
            hmacer.reset();
            hmacer.init(encryptionKey);
            System.out.println("iv: " + byte2hex(iv));
            final byte[] pad = hmacer.doFinal(iv);
            System.out.println("pad: " + byte2hex(pad) + "  len(pad): " + pad.length);
            Base64 encoder = new Base64();
            String pad_base64 = new String(encoder.encode(pad));
            System.out.println("pad Base64: " + pad_base64);

            int i = 0;
            while (i < BLOCK_SIZE && ciphertext_begin != ciphertext_end) {
                plaintext[plaintext_begin++] = (byte) (ciphertext[ciphertext_begin++] ^ pad[i++]);
            }

            if (!add_iv_counter_byte) {
                final int index = iv.length - 1;
                add_iv_counter_byte = ++iv[index] == 0;
            }

            if (add_iv_counter_byte) {
                add_iv_counter_byte = false;
                iv = Arrays.copyOf(iv, iv.length + 1);
            }
        }
        System.out.println("plaintext: " + byte2hex(plaintext));

        // Step 3. Compute integrity hash. The input to the HMAC is
        // clear_text
        // followed by initialization vector, which is stored in the 1st
        // section
        // or ciphertext.
        hmacer.reset();
        hmacer.init(integrityKey);
        hmacer.update(plaintext);
        hmacer.update(Arrays.copyOf(ciphertext, INITIALIZATION_VECTOR_SIZE));
        final byte[] computedSignature = Arrays.copyOf(hmacer.doFinal(), SIGNATURE_SIZE);
        final byte[] signature = Arrays.copyOfRange(ciphertext, ciphertext_end,
                ciphertext_end + SIGNATURE_SIZE);
        if (!Arrays.equals(signature, computedSignature)) {
            throw new DecrypterException("Signature mismatch.");
        }
        return plaintext;
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException("HmacSHA1 not supported.", e);
    } catch (InvalidKeyException e) {
        throw new RuntimeException("Key is invalid for this purpose.", e);
    }
}

From source file:com.goncalomb.bukkit.mylib.command.MySubCommand.java

List<String> tabComplete(CommandSender sender, String[] args, int argsIndex) {
    // Find sub-command.
    if (argsIndex < args.length) {
        MySubCommand subCommand = _subCommands.get(args[argsIndex].toLowerCase());
        if (subCommand != null) {
            return subCommand.tabComplete(sender, args, argsIndex + 1);
        }/* w  w  w  .  ja v  a2s.  c o m*/
    }
    // Sub-command not found or no more arguments, let's try to run this one.
    int argsLeft = args.length - argsIndex;
    if (_tabMethod != null) {
        if (argsLeft >= _minArgs && argsLeft <= _maxArgs && _type.isValidSender(sender)
                && sender.hasPermission(_perm)) {
            return invokeTabMethod(sender, Arrays.copyOfRange(args, argsIndex, args.length));
        }
        return null;
    }
    // Tab completion not found, send all sub-commands.
    if (argsLeft == 1) {
        ArrayList<String> allowedCommands = new ArrayList<String>();
        String arg = args[args.length - 1].toLowerCase();
        for (Entry<String, MySubCommand> command : _subCommands.entrySet()) {
            String name = command.getKey();
            if (name.startsWith(arg) && command.getValue()._type.isValidSender(sender)) {
                allowedCommands.add(name);
            }
        }
        return allowedCommands;
    }
    return null;
}