/*
 * 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.felix.webconsole;


import java.io.IOException;
import java.lang.reflect.Array;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.json.JSONException;
import org.json.JSONWriter;


/**
 * The <code>WebConsoleUtil</code> provides various utility methods for use
 * by Web Console plugins.
 */
public final class WebConsoleUtil
{

    private WebConsoleUtil()
    {
        /* no instantiation */
    }

    /**
     * Returns the {@link VariableResolver} for the given request.
     * <p>
     * If no resolver has yet be created for the requests, an instance of the
     * {@link DefaultVariableResolver} is created with preset properties,
     * placed into the request and returned. The preset properties are
     * <code>appRoot</code> set to the value of the
     * {@link WebConsoleConstants#ATTR_APP_ROOT} request attribute and
     * <code>pluginRoot</code> set to the value of the
     * {@link WebConsoleConstants#ATTR_PLUGIN_ROOT} request attribute.
     * <p>
     * <b>Note</b>: An object not implementing the {@link VariableResolver}
     * interface already stored as the
     * {@link WebConsoleConstants#ATTR_CONSOLE_VARIABLE_RESOLVER} attribute
     * will silently be replaced by the {@link DefaultVariableResolver}
     * instance.
     *
     * @param request The request whose attribute is returned (or set)
     *
     * @return The {@link VariableResolver} for the given request.
     */
    public static VariableResolver getVariableResolver( final ServletRequest request )
    {
        final Object resolverObj = request.getAttribute( WebConsoleConstants.ATTR_CONSOLE_VARIABLE_RESOLVER );
        if ( resolverObj instanceof VariableResolver )
        {
            return ( VariableResolver ) resolverObj;
        }

        final DefaultVariableResolver resolver = new DefaultVariableResolver();
        // FIXME: don't we need a constant for the values below?
        resolver.put( "appRoot", request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT ) ); //$NON-NLS-1$
        resolver.put( "pluginRoot", request.getAttribute( WebConsoleConstants.ATTR_PLUGIN_ROOT ) ); //$NON-NLS-1$
        setVariableResolver( request, resolver );
        return resolver;
    }


    /**
     * Sets the {@link VariableResolver} as the
     * {@link WebConsoleConstants#ATTR_CONSOLE_VARIABLE_RESOLVER}
     * attribute in the given request. An attribute of that name already
     * existing is silently replaced.
     *
     * @param request The request whose attribute is set
     * @param resolver The {@link VariableResolver} to place into the request
     */
    public static void setVariableResolver( final ServletRequest request, final VariableResolver resolver )
    {
        request.setAttribute( WebConsoleConstants.ATTR_CONSOLE_VARIABLE_RESOLVER, resolver );
    }


    /**
     * An utility method, that is used to filter out simple parameter from file
     * parameter when multipart transfer encoding is used.
     *
     * This method processes the request and sets a request attribute
     * {@link AbstractWebConsolePlugin#ATTR_FILEUPLOAD}. The attribute value is a {@link Map}
     * where the key is a String specifying the field name and the value
     * is a {@link org.apache.commons.fileupload.FileItem}.
     *
     * @param request the HTTP request coming from the user
     * @param name the name of the parameter
     * @return if not multipart transfer encoding is used - the value is the
     *  parameter value or <code>null</code> if not set. If multipart is used,
     *  and the specified parameter is field - then the value of the parameter
     *  is returned.
     */
    public static final String getParameter( HttpServletRequest request, String name )
    {
        // just get the parameter if not a multipart/form-data POST
        if ( !FileUploadBase.isMultipartContent( new ServletRequestContext( request ) ) )
        {
            return request.getParameter( name );
        }

        // check, whether we already have the parameters
        Map params = ( Map ) request.getAttribute( AbstractWebConsolePlugin.ATTR_FILEUPLOAD );
        if ( params == null )
        {
            // parameters not read yet, read now
            // Create a factory for disk-based file items
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold( 256000 );

            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload( factory );
            upload.setSizeMax( -1 );

            // Parse the request
            params = new HashMap();
            try
            {
                List items = upload.parseRequest( request );
                for ( Iterator fiter = items.iterator(); fiter.hasNext(); )
                {
                    FileItem fi = ( FileItem ) fiter.next();
                    FileItem[] current = ( FileItem[] ) params.get( fi.getFieldName() );
                    if ( current == null )
                    {
                        current = new FileItem[]
                            { fi };
                    }
                    else
                    {
                        FileItem[] newCurrent = new FileItem[current.length + 1];
                        System.arraycopy( current, 0, newCurrent, 0, current.length );
                        newCurrent[current.length] = fi;
                        current = newCurrent;
                    }
                    params.put( fi.getFieldName(), current );
                }
            }
            catch ( FileUploadException fue )
            {
                // TODO: log
            }
            request.setAttribute( AbstractWebConsolePlugin.ATTR_FILEUPLOAD, params );
        }

        FileItem[] param = ( FileItem[] ) params.get( name );
        if ( param != null )
        {
            for ( int i = 0; i < param.length; i++ )
            {
                if ( param[i].isFormField() )
                {
                    return param[i].getString();
                }
            }
        }

        // no valid string parameter, fail
        return null;
    }

    /**
     * Utility method to handle relative redirects.
     * Some application servers like Web Sphere handle relative redirects differently
     * therefore we should make an absolute URL before invoking send redirect.
     *
     * @param request the HTTP request coming from the user
     * @param response the HTTP response, where data is rendered
     * @param redirectUrl the redirect URI.
     * @throws IOException If an input or output exception occurs
     * @throws IllegalStateException   If the response was committed or if a partial
     *  URL is given and cannot be converted into a valid URL
     */
    public static final void sendRedirect(final HttpServletRequest request,
                                final HttpServletResponse response,
                                String redirectUrl) throws IOException {
        // check for relative URL
        if ( !redirectUrl.startsWith("/") ) { //$NON-NLS-1$
            String base = request.getContextPath() + request.getServletPath() + request.getPathInfo();
            int i = base.lastIndexOf('/');
            if (i > -1) {
                base = base.substring(0, i);
            } else {
                i = base.indexOf(':');
                base = (i > -1) ? base.substring(i + 1, base.length()) : ""; //$NON-NLS-1$
            }
            if (!base.startsWith("/")) { //$NON-NLS-1$
                base = '/' + base;
            }
            redirectUrl = base + '/' + redirectUrl;

        }
        response.sendRedirect(redirectUrl);
    }

    /**
     * Sets response headers to force the client to not cache the response
     * sent back. This method must be called before the response is committed
     * otherwise it will have no effect.
     * <p>
     * This method sets the <code>Cache-Control</code>, <code>Expires</code>,
     * and <code>Pragma</code> headers.
     *
     * @param response The response for which to set the cache prevention
     */
    public static final void setNoCache(final HttpServletResponse response) {
        response.setHeader("Cache-Control", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "no-store"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "must-revalidate"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "max-age=0"); //$NON-NLS-1$ //$NON-NLS-2$
        response.setHeader("Expires", "Thu, 01 Jan 1970 01:00:00 GMT"); //$NON-NLS-1$ //$NON-NLS-2$
        response.setHeader("Pragma", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    /**
     * Escapes HTML special chars like: <>&\r\n and space
     *
     *
     * @param text the text to escape
     * @return the escaped text
     */
    public static final String escapeHtml(String text)
    {
        StringBuffer sb = new StringBuffer(text.length() * 4 / 3);
        synchronized (sb) // faster buffer operations
        {
            char ch, oldch = '_';
            for (int i = 0; i < text.length(); i++)
            {
                switch (ch = text.charAt(i))
                {
                    case '<':
                        sb.append("&lt;"); //$NON-NLS-1$
                        break;
                    case '>':
                        sb.append("&gt;"); //$NON-NLS-1$
                        break;
                    case '&':
                        sb.append("&amp;"); //$NON-NLS-1$
                        break;
                    case ' ':
                        sb.append("&nbsp;"); //$NON-NLS-1$
                        break;
                    case '\r':
                    case '\n':
                        if (oldch != '\r' && oldch != '\n') // don't add twice <br>
                            sb.append("<br/>\n"); //$NON-NLS-1$
                        break;
                    default:
                        sb.append(ch);
                }
                oldch = ch;
            }

            return sb.toString();
        }
    }

    /**
     * Retrieves a request parameter and converts it to int.
     *
     * @param request the HTTP request
     * @param name the name of the request parameter
     * @param _default the default value returned if the parameter is not set or is not a valid integer.
     * @return the request parameter if set and is valid integer, or the default value
     */
    public static final int getParameterInt(HttpServletRequest request, String name,
        int _default)
    {
        int ret = _default;
        String param = request.getParameter(name);
        try
        {
            if (param != null)
                ret = Integer.parseInt(param);
        }
        catch (NumberFormatException nfe)
        {
            // don't care, will return default
        }

        return ret;
    }

    /**
     * Writes a key-value pair in a JSON writer. Write is performed only if both key and
     * value are not null.
     *
     * @param jw the writer, where to write the data
     * @param key the key value, stored under 'key'
     * @param value the value stored under 'value'
     * @throws JSONException if the value cannot be serialized.
     */
    public static final void keyVal(JSONWriter jw, String key, Object value)
        throws JSONException
    {
        if (key != null && value != null)
        {
            jw.object();
            jw.key("key"); //$NON-NLS-1$
            jw.value(key);
            jw.key("value"); //$NON-NLS-1$
            jw.value(value);
            jw.endObject();
        }
    }


    /**
     * Decode the given value expected to be URL encoded.
     * <p>
     * This method first tries to use the Java 1.4 method
     * <code>URLDecoder.decode(String, String)</code> method and falls back to
     * the now deprecated <code>URLDecoder.decode(String, String)</code>
     * which uses the platform character set to decode the string. This is
     * because the platforms before 1.4 and most notably some OSGi Execution
     * Environments (such as Minimum EE) do not provide the newer method.
     *
     * @param value the value to decode
     * @return the decoded string
     */
    public static String urlDecode( final String value )
    {
        // shortcut for empty or missing values
        if ( value == null || value.length() == 0 )
        {
            return value;
        }

        try
        {
            return URLDecoder.decode( value, "UTF-8" ); //$NON-NLS-1$
        }
        catch ( Throwable t )
        {
            // expected NoSuchMethodError: if platform does not support it
            // expected UnsupportedEncoding (not really: UTF-8 is required)
            return URLDecoder.decode( value );
        }
    }

    /**
     * This method will stringify a Java object. It is mostly used to print the values
     * of unknown properties. This method will correctly handle if the passed object
     * is array and will property display it.
     *
     * If the value is byte[] the elements are shown as Hex
     *
     * @param value the value to convert
     * @return the string representation of the value
     */
    public static final String toString(Object value)
    {
        if (value == null)
        {
            return "n/a"; //$NON-NLS-1$
        }
        else if (value.getClass().isArray())
        {
            final StringBuffer sb = new StringBuffer();
            final int len = Array.getLength(value);
            synchronized (sb)
            { // it's faster to synchronize ALL loop calls
                sb.append('[');
                for (int i = 0; i < len; i++)
                {
                    final Object element = Array.get(value, i);
                    if (element instanceof Byte)
                    {
                        // convert byte[] to hex string
                        sb.append("0x"); //$NON-NLS-1$
                        final String x = Integer.toHexString(((Byte) element).intValue() & 0xff);
                        if (1 == x.length())
                        {
                            sb.append('0');
                        }
                        sb.append(x);
                    }
                    else
                    {
                        sb.append(toString(element));
                    }

                    if (i < len - 1)
                    {
                        sb.append(", "); //$NON-NLS-1$
                    }
                }
                return sb.append(']').toString();
            }
        }
        else
        {
            return value.toString();
        }

    }
}
