org.apache.jmeter.protocol.http.control.AuthManager.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.jmeter.protocol.http.control.AuthManager.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.apache.jmeter.protocol.http.control;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

import org.apache.commons.io.IOUtils;
import org.apache.jmeter.config.ConfigElement;
import org.apache.jmeter.config.ConfigTestElement;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.testelement.property.TestElementProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;

// For Unit tests, @see TestAuthManager

/**
 * This class provides a way to provide Authorization in jmeter requests. The
 * format of the authorization file is: URL user pass where URL is an HTTP URL,
 * user a username to use and pass the appropriate password.
 *
 */
public class AuthManager extends ConfigTestElement implements Serializable {
    private static final long serialVersionUID = 233L;

    private static final Logger log = LoggingManager.getLoggerForClass();

    private static final String AUTH_LIST = "AuthManager.auth_list"; //$NON-NLS-1$

    private static final String[] COLUMN_RESOURCE_NAMES = { "auth_base_url", //$NON-NLS-1$
            "username", //$NON-NLS-1$
            "password", //$NON-NLS-1$
            "domain", //$NON-NLS-1$
            "realm", //$NON-NLS-1$
    };

    // Column numbers - must agree with order above
    public static final int COL_URL = 0;
    public static final int COL_USERNAME = 1;
    public static final int COL_PASSWORD = 2;
    public static final int COL_DOMAIN = 3;
    public static final int COL_REALM = 4;

    private static final int COLUMN_COUNT = COLUMN_RESOURCE_NAMES.length;

    /**
     * Default Constructor.
     */
    public AuthManager() {
        setProperty(new CollectionProperty(AUTH_LIST, new ArrayList<Object>()));
    }

    /** {@inheritDoc} */
    @Override
    public void clear() {
        super.clear();
        setProperty(new CollectionProperty(AUTH_LIST, new ArrayList<Object>()));
    }

    /**
     * Update an authentication record.
     */
    public void set(int index, String url, String user, String pass, String domain, String realm) {
        Authorization auth = new Authorization(url, user, pass, domain, realm);
        if (index >= 0) {
            getAuthObjects().set(index, new TestElementProperty(auth.getName(), auth));
        } else {
            getAuthObjects().addItem(auth);
        }
    }

    public CollectionProperty getAuthObjects() {
        return (CollectionProperty) getProperty(AUTH_LIST);
    }

    public int getColumnCount() {
        return COLUMN_COUNT;
    }

    public String getColumnName(int column) {
        return COLUMN_RESOURCE_NAMES[column];
    }

    public Class<?> getColumnClass(int column) {
        return COLUMN_RESOURCE_NAMES[column].getClass();
    }

    public Authorization getAuthObjectAt(int row) {
        return (Authorization) getAuthObjects().get(row).getObjectValue();
    }

    public boolean isEditable() {
        return true;
    }

    /**
     * Return the record at index i
     */
    public Authorization get(int i) {
        return (Authorization) getAuthObjects().get(i).getObjectValue();
    }

    public String getAuthHeaderForURL(URL url) {
        Authorization auth = getAuthForURL(url);
        if (auth == null) {
            return null;
        }
        return auth.toBasicHeader();
    }

    public Authorization getAuthForURL(URL url) {
        if (!isSupportedProtocol(url)) {
            return null;
        }

        // TODO: replace all this url2 mess with a proper method
        // "areEquivalent(url1, url2)" that
        // would also ignore case in protocol and host names, etc. -- use that
        // method in the CookieManager too.

        URL url2 = null;

        try {
            if (url.getPort() == -1) {
                // Obtain another URL with an explicit port:
                int port = url.getProtocol().equalsIgnoreCase("http") ? HTTPConstants.DEFAULT_HTTP_PORT
                        : HTTPConstants.DEFAULT_HTTPS_PORT;
                // only http and https are supported
                url2 = new URL(url.getProtocol(), url.getHost(), port, url.getPath());
            } else if ((url.getPort() == HTTPConstants.DEFAULT_HTTP_PORT
                    && url.getProtocol().equalsIgnoreCase("http"))
                    || (url.getPort() == HTTPConstants.DEFAULT_HTTPS_PORT
                            && url.getProtocol().equalsIgnoreCase("https"))) {
                url2 = new URL(url.getProtocol(), url.getHost(), url.getPath());
            }
        } catch (MalformedURLException e) {
            log.error("Internal error!", e); // this should never happen
            // anyway, we'll continue with url2 set to null.
        }

        String s1 = url.toString();
        String s2 = null;
        if (url2 != null) {
            s2 = url2.toString();
        }

        log.debug("Target URL strings to match against: " + s1 + " and " + s2);
        // TODO should really return most specific (i.e. longest) match.
        for (PropertyIterator iter = getAuthObjects().iterator(); iter.hasNext();) {
            Authorization auth = (Authorization) iter.next().getObjectValue();

            String uRL = auth.getURL();
            log.debug("Checking match against auth'n entry: " + uRL);
            if (s1.startsWith(uRL) || s2 != null && s2.startsWith(uRL)) {
                log.debug("Matched");
                return auth;
            }
            log.debug("Did not match");
        }
        return null;
    }

    /** {@inheritDoc} */
    @Override
    public void addConfigElement(ConfigElement config) {
    }

    public void addAuth(Authorization auth) {
        getAuthObjects().addItem(auth);
    }

    public void addAuth() {
        getAuthObjects().addItem(new Authorization());
    }

    /** {@inheritDoc} */
    @Override
    public boolean expectsModification() {
        return false;
    }

    /**
     * Save the authentication data to a file.
     */
    public void save(String authFile) throws IOException {
        File file = new File(authFile);
        if (!file.isAbsolute()) {
            file = new File(System.getProperty("user.dir"), authFile);
        }
        PrintWriter writer = new PrintWriter(new FileWriter(file));
        writer.println("# JMeter generated Authorization file");
        for (int i = 0; i < getAuthObjects().size(); i++) {
            Authorization auth = (Authorization) getAuthObjects().get(i).getObjectValue();
            writer.println(auth.toString());
        }
        writer.flush();
        writer.close();
    }

    /**
     * Add authentication data from a file.
     */
    public void addFile(String authFile) throws IOException {
        File file = new File(authFile);
        if (!file.isAbsolute()) {
            file = new File(System.getProperty("user.dir") + File.separator + authFile);
        }
        if (!file.canRead()) {
            throw new IOException("The file you specified cannot be read.");
        }

        BufferedReader reader = null;
        boolean ok = true;
        try {
            reader = new BufferedReader(new FileReader(file));
            String line;
            while ((line = reader.readLine()) != null) {
                try {
                    if (line.startsWith("#") || JOrphanUtils.isBlank(line)) { //$NON-NLS-1$
                        continue;
                    }
                    StringTokenizer st = new StringTokenizer(line, "\t"); //$NON-NLS-1$
                    String url = st.nextToken();
                    String user = st.nextToken();
                    String pass = st.nextToken();
                    String domain = "";
                    String realm = "";
                    if (st.hasMoreTokens()) {// Allow for old format file without the extra columnns
                        domain = st.nextToken();
                        realm = st.nextToken();
                    }
                    Authorization auth = new Authorization(url, user, pass, domain, realm);
                    getAuthObjects().addItem(auth);
                } catch (NoSuchElementException e) {
                    log.error("Error parsing auth line: '" + line + "'");
                    ok = false;
                }
            }
        } finally {
            IOUtils.closeQuietly(reader);
        }
        if (!ok) {
            JMeterUtils.reportErrorToUser("One or more errors found when reading the Auth file - see the log file");
        }
    }

    /**
     * Remove an authentication record.
     */
    public void remove(int index) {
        getAuthObjects().remove(index);
    }

    /**
     * Return the number of records.
     */
    public int getAuthCount() {
        return getAuthObjects().size();
    }

    // Needs to be package protected for Unit test
    static boolean isSupportedProtocol(URL url) {
        String protocol = url.getProtocol().toLowerCase(java.util.Locale.ENGLISH);
        return protocol.equals(HTTPConstants.PROTOCOL_HTTP) || protocol.equals(HTTPConstants.PROTOCOL_HTTPS);
    }
}