com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader.java Source code

Java tutorial

Introduction

Here is the source code for com.eviware.soapui.impl.wsdl.support.wsdl.UrlWsdlLoader.java

Source

/*
 *  soapUI, copyright (C) 2004-2011 eviware.com 
 *
 *  soapUI is free software; you can redistribute it and/or modify it under the 
 *  terms of version 2.1 of the GNU Lesser General Public License as published by 
 *  the Free Software Foundation.
 *
 *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
 *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 *  See the GNU Lesser General Public License for more details at gnu.org.
 */

package com.eviware.soapui.impl.wsdl.support.wsdl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScheme;
import org.apache.commons.httpclient.auth.CredentialsNotAvailableException;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.apache.commons.httpclient.auth.NTLMScheme;
import org.apache.commons.httpclient.auth.RFC2617Scheme;
import org.apache.commons.httpclient.methods.GetMethod;

import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.support.definition.DefinitionLoader;
import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
import com.eviware.soapui.impl.wsdl.support.PathUtils;
import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
import com.eviware.soapui.impl.wsdl.support.http.ProxyUtils;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.propertyexpansion.DefaultPropertyExpansionContext;
import com.eviware.soapui.model.settings.Settings;
import com.eviware.soapui.settings.HttpSettings;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.swing.SwingWorker;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.x.form.XForm;
import com.eviware.x.form.XFormDialog;
import com.eviware.x.form.XFormDialogBuilder;
import com.eviware.x.form.XFormFactory;

/**
 * WsdlLoader for URLs
 * 
 * @author ole.matzura
 */

public class UrlWsdlLoader extends WsdlLoader implements DefinitionLoader {
    private HttpState state;
    protected GetMethod getMethod;
    private boolean aborted;
    protected Map<String, byte[]> urlCache = new HashMap<String, byte[]>();
    protected boolean finished;
    private boolean useWorker;
    private ModelItem contextModelItem;

    public UrlWsdlLoader(String url) {
        this(url, null);
    }

    public UrlWsdlLoader(String url, ModelItem contextModelItem) {
        super(url);
        this.contextModelItem = contextModelItem;
        state = new HttpState();
    }

    public boolean isUseWorker() {
        return useWorker;
    }

    public void setUseWorker(boolean useWorker) {
        this.useWorker = useWorker;
    }

    public InputStream load() throws Exception {
        return load(getBaseURI());
    }

    public synchronized InputStream load(String url) throws Exception {
        if (!PathUtils.isHttpPath(url)) {
            try {
                File file = new File(url.replace('/', File.separatorChar));
                if (file.exists())
                    url = file.toURI().toURL().toString();
            } catch (Exception e) {
            }
        }

        if (urlCache.containsKey(url)) {
            setNewBaseURI(url);
            return new ByteArrayInputStream(urlCache.get(url));
        }

        if (url.startsWith("file:")) {
            return handleFile(url);
        }

        log.debug("Getting wsdl component from [" + url + "]");

        createGetMethod(url);

        if (aborted)
            return null;

        LoaderWorker worker = new LoaderWorker();
        if (useWorker)
            worker.start();
        else
            worker.construct();

        while (!aborted && !finished) {
            Thread.sleep(200);
        }

        // wait for method to catch up - required in unit tests..
        // limited looping to 10 loops because of eclipse plugin which entered 
        // endless loop without it
        // 
        int counter = 0;
        while (!aborted && getMethod.getResponseBody() == null && counter < 10) {
            Thread.sleep(200);
            counter++;
        }

        try {
            if (aborted) {
                throw new Exception("Load of url [" + url + "] was aborted");
            } else {
                byte[] content = getMethod.getResponseBody();
                if (content != null) {
                    String compressionAlg = HttpClientSupport.getResponseCompressionType(getMethod);
                    if (compressionAlg != null)
                        content = CompressionSupport.decompress(compressionAlg, content);

                    urlCache.put(url, content);
                    String newUrl = getMethod.getURI().getURI();
                    if (!url.equals(newUrl))
                        log.info("BaseURI was redirected to [" + newUrl + "]");
                    setNewBaseURI(newUrl);
                    urlCache.put(newUrl, content);
                    return new ByteArrayInputStream(content);
                } else {
                    throw new Exception(
                            "Failed to load url; " + getMethod.getStatusCode() + " - " + getMethod.getStatusText());
                }
            }
        }

        finally {
            getMethod.releaseConnection();
        }
    }

    protected InputStream handleFile(String url) throws Exception {
        setNewBaseURI(url);
        return new URL(url).openStream();
    }

    protected void createGetMethod(String url) {
        getMethod = new GetMethod(url);
        getMethod.setFollowRedirects(true);
        getMethod.setDoAuthentication(true);
        getMethod.getParams().setParameter(CredentialsProvider.PROVIDER, new WsdlCredentialsProvider());

        if (SoapUI.getSettings().getBoolean(HttpSettings.AUTHENTICATE_PREEMPTIVELY)) {
            HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive(true);
        } else {
            HttpClientSupport.getHttpClient().getParams().setAuthenticationPreemptive(false);
        }
    }

    public final class LoaderWorker extends SwingWorker {
        public Object construct() {
            HttpClient httpClient = HttpClientSupport.getHttpClient();
            try {
                Settings soapuiSettings = SoapUI.getSettings();

                HttpClientSupport.applyHttpSettings(getMethod, soapuiSettings);
                HostConfiguration hostConfiguration = ProxyUtils.initProxySettings(soapuiSettings, state,
                        new HostConfiguration(), getMethod.getURI().toString(),
                        contextModelItem == null ? null : new DefaultPropertyExpansionContext(contextModelItem));

                httpClient.executeMethod(hostConfiguration, getMethod, state);
            } catch (Exception e) {
                return e;
            } finally {
                finished = true;
            }

            return null;
        }
    }

    public boolean abort() {
        if (getMethod != null)
            getMethod.abort();

        aborted = true;

        return true;
    }

    public boolean isAborted() {
        return aborted;
    }

    /**
     * CredentialsProvider for providing login information during WSDL loading
     * 
     * @author ole.matzura
     */

    private static Map<String, Credentials> cache = new HashMap<String, Credentials>();

    public final class WsdlCredentialsProvider implements CredentialsProvider {
        private XFormDialog basicDialog;
        private XFormDialog ntDialog;

        public WsdlCredentialsProvider() {
        }

        public Credentials getCredentials(final AuthScheme authscheme, final String host, int port, boolean proxy)
                throws CredentialsNotAvailableException {
            String key = String.valueOf(authscheme) + "-" + host + "-" + port + "-" + proxy;
            if (cache.containsKey(key))
                return cache.get(key);

            if (authscheme == null) {
                return null;
            }
            try {
                String pw = getPassword();
                if (pw == null)
                    pw = "";

                if (authscheme instanceof NTLMScheme) {
                    if (hasCredentials()) {
                        log.info("Returning url credentials");
                        return new NTCredentials(getUsername(), pw, host, null);
                    }

                    log.info(host + ":" + port + " requires Windows authentication");
                    if (ntDialog == null) {
                        buildNtDialog();
                    }

                    StringToStringMap values = new StringToStringMap();
                    values.put("Info", "Authentication required for [" + host + ":" + port + "]");
                    ntDialog.setValues(values);

                    if (ntDialog.show()) {
                        values = ntDialog.getValues();
                        NTCredentials credentials = new NTCredentials(values.get("Username"),
                                values.get("Password"), host, values.get("Domain"));

                        cache.put(key, credentials);
                        return credentials;
                    } else
                        throw new CredentialsNotAvailableException("Operation cancelled");
                } else if (authscheme instanceof RFC2617Scheme) {
                    if (hasCredentials()) {
                        log.info("Returning url credentials");
                        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(getUsername(),
                                pw);
                        cache.put(key, credentials);
                        return credentials;
                    }

                    log.info(host + ":" + port + " requires authentication with the realm '" + authscheme.getRealm()
                            + "'");
                    ShowDialog showDialog = new ShowDialog();
                    showDialog.values.put("Info", "Authentication required for [" + host + ":" + port + "]");

                    UISupport.getUIUtils().runInUIThreadIfSWT(showDialog);
                    if (showDialog.result) {
                        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
                                showDialog.values.get("Username"), showDialog.values.get("Password"));
                        cache.put(key, credentials);
                        return credentials;
                    } else
                        throw new CredentialsNotAvailableException("Operation cancelled");

                } else {
                    throw new CredentialsNotAvailableException(
                            "Unsupported authentication scheme: " + authscheme.getSchemeName());
                }
            } catch (IOException e) {
                throw new CredentialsNotAvailableException(e.getMessage(), e);
            }
        }

        private void buildBasicDialog() {
            XFormDialogBuilder builder = XFormFactory.createDialogBuilder("Basic Authentication");
            XForm mainForm = builder.createForm("Basic");
            mainForm.addLabel("Info", "");
            mainForm.addTextField("Username", "Username for authentication", XForm.FieldType.TEXT);
            mainForm.addTextField("Password", "Password for authentication", XForm.FieldType.PASSWORD);

            basicDialog = builder.buildDialog(builder.buildOkCancelActions(),
                    "Specify Basic Authentication Credentials", UISupport.OPTIONS_ICON);
        }

        private void buildNtDialog() {
            XFormDialogBuilder builder = XFormFactory.createDialogBuilder("NT Authentication");
            XForm mainForm = builder.createForm("Basic");
            mainForm.addLabel("Info", "");
            mainForm.addTextField("Username", "Username for authentication", XForm.FieldType.TEXT);
            mainForm.addTextField("Password", "Password for authentication", XForm.FieldType.PASSWORD);
            mainForm.addTextField("Domain", "NT Domain for authentication", XForm.FieldType.TEXT);

            ntDialog = builder.buildDialog(builder.buildOkCancelActions(), "Specify NT Authentication Credentials",
                    UISupport.OPTIONS_ICON);
        }

        private class ShowDialog implements Runnable {
            StringToStringMap values = new StringToStringMap();
            boolean result;

            public void run() {
                if (basicDialog == null)
                    buildBasicDialog();

                basicDialog.setValues(values);

                result = basicDialog.show();
                if (result) {
                    values = basicDialog.getValues();
                }
            }
        }
    }

    public void close() {
    }
}