All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ojalgo.netio.ResourceLocator Maven / Gradle / Ivy

Go to download

oj! Algorithms - ojAlgo - is Open Source Java code that has to do with mathematics, linear algebra and optimisation.

There is a newer version: 55.0.1
Show newest version
/*
 * Copyright 1997-2024 Optimatika
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.ojalgo.netio;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.net.http.HttpClient;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import org.ojalgo.ProgrammingError;

/**
 * Locate/fetch resources such as csv, json or text/html.
 * 

* Started out as something relatively simple built around {@link URL} (and related stuff in the java.net * package) but grew into a complete http client. *

* The newer {@link ServiceClient} is instead built around the {@link HttpClient} introduced with Java 11. * Think of {@link ServiceClient} as v2 of {@link ResourceLocator}, and what you should use for http/https * calls. *

* This class is not (yet) deprecated, but if it is further developed it will not be primarily as an * http/https client. The focus will then be on other {@link URL} based use cases. * * @author apete */ public final class ResourceLocator { public static class KeyedValues implements Map { private final Set myOrderedKeys = new LinkedHashSet<>(); /** * Takes advantage of the fact that java.util.Properties support strings with unicode escape * sequences, and that it can delegate to default values. */ private final Properties myValues; public KeyedValues() { super(); myValues = new Properties(); } KeyedValues(final Properties defaults) { super(); myValues = new Properties(defaults); } public void clear() { myOrderedKeys.clear(); myValues.clear(); } public boolean containsKey(final Object key) { return myValues.containsKey(key); } public boolean containsValue(final Object value) { return myValues.containsValue(value); } public Set> entrySet() { return myValues.entrySet().stream().map(e -> new Entry() { public String getKey() { return e.getKey().toString(); } public String getValue() { return e.getValue().toString(); } public String setValue(final String value) { String prev = e.getValue().toString(); e.setValue(value); return prev; } }).collect(Collectors.toSet()); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if ((obj == null) || !(obj instanceof KeyedValues)) { return false; } KeyedValues other = (KeyedValues) obj; return Objects.equals(myOrderedKeys, other.myOrderedKeys) && Objects.equals(myValues, other.myValues); } public String get(final Object key) { return myValues.getProperty(key.toString()); } @Override public int hashCode() { return Objects.hash(myOrderedKeys, myValues); } public boolean isEmpty() { return myValues.isEmpty(); } public Set keySet() { return myValues.stringPropertyNames(); } /** * Will parse/split the query string into key-value pairs and store those. * * @param keysAndValues A query (or form) string */ public void parse(final String keysAndValues) { if (keysAndValues != null) { String[] pairs = keysAndValues.split("&"); for (int i = 0; i < pairs.length; i++) { String pair = pairs[i]; int split = pair.indexOf("="); String key = pair.substring(0, split); String value = pair.substring(split + 1); this.put(key, value); } } } public String put(final String key, final String value) { myOrderedKeys.add(key); return String.valueOf(myValues.setProperty(key, value)); } public void putAll(final Map m) { myValues.putAll(m); } public String remove(final Object key) { myOrderedKeys.remove(key); Object removed = myValues.remove(key); return removed != null ? removed.toString() : null; } public int size() { return myValues.size(); } /** * @return A query string like: key1=value1&key2=value2... */ @Override public String toString() { return myOrderedKeys.stream().map(key -> key + "=" + myValues.getProperty(key)).collect(Collectors.joining("&")); } public Collection values() { return myValues.values().stream().map(Object::toString).collect(Collectors.toList()); } Set getOrderedKeys() { return myOrderedKeys; } Properties getValues() { return myValues; } } public enum Method { DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE; } public static final class Request implements BasicLogger.Printable { private final KeyedValues myForm = new KeyedValues(); private ResourceLocator.Method myMethod = ResourceLocator.Method.GET; private final ResourceSpecification myResourceSpecification; private final ResourceLocator.Session mySession; Request(final ResourceLocator.Session session) { super(); mySession = session; myResourceSpecification = new ResourceSpecification(); } Request(final ResourceLocator.Session session, final URL url) { super(); mySession = session; myResourceSpecification = new ResourceSpecification(url); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof Request)) { return false; } Request other = (Request) obj; if (!myForm.equals(other.myForm) || (myMethod != other.myMethod)) { return false; } if (myResourceSpecification == null) { if (other.myResourceSpecification != null) { return false; } } else if (!myResourceSpecification.equals(other.myResourceSpecification)) { return false; } if (mySession == null) { if (other.mySession != null) { return false; } } else if (!mySession.equals(other.mySession)) { return false; } return true; } public ResourceLocator.Request form(final String form) { myForm.parse(form); return this; } public ResourceLocator.Request form(final String key, final String value) { ProgrammingError.throwIfNull(key); if (value != null) { myForm.put(key, value); } else { myForm.remove(key); } return this; } public ResourceLocator.Request fragment(final String fragment) { myResourceSpecification.setFragment(fragment); return this; } public String getFormValue(final String key) { return myForm.get(key); } public String getQueryValue(final String key) { return myResourceSpecification.getQueryValue(key); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + myForm.hashCode(); result = prime * result + ((myMethod == null) ? 0 : myMethod.hashCode()); result = prime * result + ((myResourceSpecification == null) ? 0 : myResourceSpecification.hashCode()); return prime * result + ((mySession == null) ? 0 : mySession.hashCode()); } public ResourceLocator.Request host(final String host) { myResourceSpecification.setHost(host); return this; } public ResourceLocator.Request method(final Method method) { myMethod = method; return this; } public ResourceLocator.Request path(final String path) { myResourceSpecification.setPath(path); return this; } /** * The default (null) value is -1. */ public ResourceLocator.Request port(final int port) { myResourceSpecification.setPort(port); return this; } public void print(final BasicLogger receiver) { mySession.print(receiver); receiver.println("Request URL: {}", this.toURL()); if (myForm.size() > 0) { receiver.println("Request form: {}", myForm); } } public ResourceLocator.Request query(final String query) { myResourceSpecification.setQuery(query); return this; } public ResourceLocator.Request query(final String key, final String value) { myResourceSpecification.putQueryEntry(key, value); return this; } public Response response() { return new Response(this); } /** * Protocol The default value is "https" */ public ResourceLocator.Request scheme(final String scheme) { myResourceSpecification.setScheme(scheme); return this; } @Override public String toString() { return this.toURL().toString(); } private String query() { return myResourceSpecification.getQuery(); } private URL toURL() { return myResourceSpecification.toURL(); } void configure(final HttpURLConnection connection) { try { connection.setRequestMethod(myMethod.name()); } catch (ProtocolException exception) { throw new ProgrammingError(exception); } } String form() { if (myForm.isEmpty()) { return null; } else { return myForm.toString(); } } ResourceLocator.Session getSession() { return mySession; } URLConnection newConnection() { URLConnection retVal = null; try { CookieHandler.setDefault(mySession.getCookieManager()); retVal = this.toURL().openConnection(); } catch (final IOException exception) { exception.printStackTrace(); } return retVal; } } public static final class Response implements BasicLogger.Printable { private final URLConnection myConnection; private final ResourceLocator.Session mySession; private transient String myString; Response(final ResourceLocator.Request request) { super(); mySession = request.getSession(); myConnection = request.newConnection(); if (myConnection instanceof HttpURLConnection) { request.configure((HttpURLConnection) myConnection); } String form = request.form(); if ((form != null) && (form.length() > 0)) { myConnection.setDoOutput(true); try (DataOutputStream output = new DataOutputStream(myConnection.getOutputStream())) { output.write(form.getBytes(UTF_8)); } catch (IOException exception) { exception.printStackTrace(); } } } /** * Open a connection and get the input stream. */ public InputStream getInputStream() { InputStream retVal = null; try { retVal = myConnection.getInputStream(); } catch (final IOException exception) { exception.printStackTrace(); } return retVal; } /** * Will recreate the request that resulted in the final response. If there has been one or more * redirects, then this is NOT the same as the original request. */ public ResourceLocator.Request getRequest() { return new ResourceLocator.Request(mySession, myConnection.getURL()); } /** * @return The http response status code, or -1 if this is not http/hhtps or if the code cannot be * discerned from the response */ public int getStatusCode() { if (myConnection instanceof HttpURLConnection) { try { return ((HttpURLConnection) myConnection).getResponseCode(); } catch (IOException exception) { return -1; } } else { return -1; } } /** * Open connection and return an input stream reader. This method can only be called once on each * instance, and the {@link #toString()} and {@link #print(Printer)} methods delegate to this method. * (Those methods can be called multiple timea.) */ public Reader getStreamReader() { return new InputStreamReader(this.getInputStream()); } /** * @return true if the status (response) code is in [200,300) */ public boolean isResponseOK() { int statusCode = this.getStatusCode(); if ((200 <= statusCode) && (statusCode < 300)) { return true; } else { return false; } } public void print(final BasicLogger receiver) { receiver.println("Response body: {}", this.toString()); receiver.println("Response headers: {}", myConnection.getHeaderFields()); receiver.println(""); this.getRequest().print(receiver); receiver.println(""); mySession.print(receiver); } @Override public String toString() { if (myString == null) { StringBuilder builder = new StringBuilder(); String line = null; try (BufferedReader reader = new BufferedReader(this.getStreamReader())) { while ((line = reader.readLine()) != null) { builder.append(line); } } catch (IOException exception) { exception.printStackTrace(); } myString = builder.toString(); } return myString; } } public static final class Session implements BasicLogger.Printable { private final CookieManager myCookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); private final KeyedValues myParameters = new KeyedValues(DEFAULTS.getValues()); Session() { super(); CookieHandler.setDefault(myCookieManager); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!(obj instanceof Session)) { return false; } Session other = (Session) obj; if (!myCookieManager.equals(other.myCookieManager) || !myParameters.equals(other.myParameters)) { return false; } return true; } public String getParameterValue(final String key) { return myParameters.get(key); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + myCookieManager.hashCode(); return prime * result + myParameters.hashCode(); } public ResourceLocator.Session parameter(final String key, final String value) { if (value != null) { myParameters.put(key, value); } else { myParameters.remove(key); } return this; } public void print(final BasicLogger receiver) { receiver.println("Session parameters: {}", myParameters); receiver.println("Session cookies: {}", myCookieManager.getCookieStore().getCookies()); } public Request request() { return new Request(this); } public Request request(final String url) { try { return new Request(this, new URL(url)); } catch (MalformedURLException exception) { throw new ProgrammingError(exception); } } public void reset() { myParameters.clear(); myCookieManager.getCookieStore().removeAll(); } CookieManager getCookieManager() { return myCookieManager; } } /** * Default session parameters */ public static ResourceLocator.KeyedValues DEFAULTS = new ResourceLocator.KeyedValues(); static final String UTF_8 = StandardCharsets.UTF_8.name(); public static ResourceLocator.Session session() { return new Session(); } static String urldecode(final String encoded) { try { return URLDecoder.decode(encoded, UTF_8); } catch (UnsupportedEncodingException exception) { return null; } } static String urlencode(final String unencoded) { try { return URLEncoder.encode(unencoded, UTF_8); } catch (UnsupportedEncodingException exception) { return null; } } private transient ResourceLocator.Request myRequest = null; private final ResourceLocator.Session mySession = new Session(); public ResourceLocator() { super(); } public ResourceLocator(final String url) { super(); myRequest = mySession.request(url); } public ResourceLocator form(final String key, final String value) { this.request().form(key, value); return this; } public ResourceLocator fragment(final String fragment) { this.request().fragment(fragment); return this; } public InputStream getInputStream() { return this.response().getInputStream(); } /** * Open connection and return an input stream reader. */ public Reader getStreamReader() { return this.response().getStreamReader(); } public ResourceLocator host(final String host) { this.request().host(host); return this; } public ResourceLocator method(final Method method) { this.request().method(method); return this; } public ResourceLocator path(final String path) { this.request().path(path); return this; } /** * The default (null) value is -1. */ public ResourceLocator port(final int port) { this.request().port(port); return this; } public ResourceLocator query(final String key, final String value) { this.request().query(key, value); return this; } /** * Protocol The default value is "https" */ public ResourceLocator scheme(final String scheme) { this.request().scheme(scheme); return this; } @Override public String toString() { return this.request().toString(); } private ResourceLocator.Request request() { if (myRequest == null) { myRequest = mySession.request(); } return myRequest; } private ResourceLocator.Response response() { return new Response(this.request()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy