SquirrelJME/SquirrelJME

View on GitHub
modules/gcf/src/main/java/cc/squirreljme/runtime/gcf/HTTPAddress.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.runtime.gcf;

import cc.squirreljme.runtime.cldc.debug.Debugging;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import net.multiphasicapps.collections.EmptyList;
import net.multiphasicapps.collections.UnmodifiableList;
import org.intellij.lang.annotations.Language;

/**
 * This represents an IP address.
 *
 * @since 2019/05/06
 */
public final class HTTPAddress
    implements SocketAddress
{
    /** The IP Address. */
    public final IPAddress ipaddr;
    
    /** The file. */
    public final FileAddress file;
    
    /** The query. */
    public final String query;
    
    /** The fragment. */
    public final String fragment;
    
    /** Parameters which exist within the address. */
    public final List<String> parameters;
    
    /**
     * Initializes the HTTP Address.
     *
     * @param __ip The IP address.
     * @param __file The file.
     * @param __parameters The parameters, there may be multiple ones.
     * @param __query The query, may be {@code null}.
     * @param __frag The fragment, may be {@code null}.
     * @throws NullPointerException On null arguments.
     * @since 2019/05/06
     */
    public HTTPAddress(IPAddress __ip, FileAddress __file,
        List<String> __parameters, String __query,
        String __frag)
        throws NullPointerException
    {
        if (__ip == null || __file == null)
            throw new NullPointerException("NARG");
        
        // Defensive copy
        if (__parameters != null)
        {
            __parameters = new ArrayList<>(__parameters);
            for (String param : __parameters)
                if (param == null)
                    throw new NullPointerException("NARG");
        }
        
        this.ipaddr = __ip;
        this.file = __file;
        this.query = __query;
        this.fragment = __frag;
        this.parameters = (__parameters == null ? EmptyList.<String>empty() :
            UnmodifiableList.of(__parameters));
    }
    
    /**
     * {@inheritDoc}
     * @since 2019/05/06
     */
    @Override
    public final boolean equals(Object __o)
    {
        throw Debugging.todo();
    }
    
    /**
     * {@inheritDoc}
     * @since 2019/05/06
     */
    @Override
    public final int hashCode()
    {
        throw Debugging.todo();
    }
    
    /**
     * {@inheritDoc}
     * @since 2019/05/06
     */
    @Override
    public final String toString()
    {
        throw Debugging.todo();
    }
    
    /**
     * Decodes an address from the URI part.
     *
     * @param __p The part to decode from.
     * @return The HTTP address.
     * @throws IllegalArgumentException If the address is not valid.
     * @throws NullPointerException On null arguments.
     * @since 2019/05/06
     */
    public static HTTPAddress fromUriPart(
        @Language("http-url-reference") String __p)
        throws IllegalArgumentException, NullPointerException
    {
        if (__p == null)
            throw new NullPointerException("NARG");
        
        // Debug
        Debugging.debugNote("Decode %s", __p);
        
        /* {@squirreljme.error EC02 HTTP address must start with double
        slash. (The URI part)} */
        if (!__p.startsWith("//"))
            throw new IllegalArgumentException("EC02 " + __p);
        __p = __p.substring(2);
        
        // Only contains the host part
        int sl = __p.indexOf('/');
        if (sl < 0)
            return new HTTPAddress(IPAddress.of(__p), FileAddress.of("/"),
                null, null, null);
        
        // Parse host portion
        IPAddress ipaddr = IPAddress.of(__p.substring(0, sl));
        
        // Parse remaining part, but keep the slash
        __p = __p.substring(sl);
        
        // The file address can end at any of these points
        int nextParam = __p.indexOf(';');
        int nextQuery = __p.indexOf('?');
        int nextFrag = __p.indexOf('#');
    
        // Extract the file parameter part
        int endPos = (nextParam >= 0 ? nextParam :
            (nextQuery >= 0 ? nextQuery :
            (nextFrag >= 0 ? nextFrag : __p.length())));
        FileAddress fileAddress = FileAddress.of(__p.substring(0, endPos));
        
        // Move to the end position
        __p = __p.substring(endPos);
        
        // Parse parameter
        List<String> parameters;
        int el = __p.indexOf(';');
        if (el >= 0)
            throw Debugging.todo();
        
        // No parameter used
        else
            parameters = null;
        
        // Parse query
        String query;
        int ql = __p.indexOf('?');
        if (ql >= 0)
        {
            // Queries can end before a fragment
            int hashAt = __p.indexOf('#', ql + 1);
            
            query = HTTPUtils.stringDecode(
                HTTPUrlCharacterSet.QUERY_OR_FRAGMENT,
                (hashAt < 0 ? __p.substring(ql + 1) :
                    __p.substring(ql + 1, hashAt)));
        }
        
        // No query used
        else
            query = null;
        
        // Parse fragment, fragments are always at the end
        String fragment;
        int fl = __p.indexOf('#');
        if (fl >= 0)
            fragment = HTTPUtils.stringDecode(
                HTTPUrlCharacterSet.QUERY_OR_FRAGMENT, __p.substring(fl + 1));
            
            // No fragment used
        else
            fragment = null;
        
        // Build remaining address
        return new HTTPAddress(ipaddr, fileAddress, parameters, query,
            fragment);
    }
    
    /**
     * Decodes an address from the URI part or returns {@code null} if not
     * valid.
     *
     * @param __part The part to decode from.
     * @return The HTTP address or {@code null} if the address is not valid.
     * @throws NullPointerException On null arguments.
     * @since 2022/10/11
     */
    public static HTTPAddress fromUriPartUnchecked(String __part)
        throws NullPointerException
    {
        if (__part == null)
            throw new NullPointerException("NARG");
        
        try
        {
            return HTTPAddress.fromUriPart(__part);
        }
        catch (IllegalArgumentException e)
        {
            e.printStackTrace();
            
            return null;
        }
    }
}