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

org.openmdx.base.naming.URI_1Marshaller Maven / Gradle / Ivy

There is a newer version: 2.18.10
Show newest version
/*
 * ====================================================================
 * Project:     openMDX, http://www.openmdx.org/
 * Description: Legacy URI Marshaller 
 * Owner:       OMEX AG, Switzerland, http://www.omex.ch
 * ====================================================================
 *
 * This software is published under the BSD license as listed below.
 * 
 * Copyright (c) 2004-2009, OMEX AG, Switzerland
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 * 
 * * Neither the name of the openMDX team nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * ------------------
 * 
 * This product includes software developed by other organizations as
 * listed in the NOTICE file.
 */
package org.openmdx.base.naming;

import java.util.ArrayList;

import org.openmdx.base.exception.ServiceException;
import org.openmdx.base.marshalling.Marshaller;
import org.openmdx.base.text.conversion.UnicodeTransformation;
import org.openmdx.kernel.exception.BasicException;


/**
 * Handles SPICE URIs
 */
@SuppressWarnings({"rawtypes","unchecked"})
public final class URI_1Marshaller implements Marshaller {

    private URI_1Marshaller(
    ){
        // Avoid external instantiation
    }

    /**
     * Memorize the singleton
     */ 
    final static private Marshaller instance = new URI_1Marshaller();

    /**
     * Legacy' URI Scheme Prefix
     */
    public final static String OPENMDX_PREFIX = "spice:/";

    /**
     * Return the singleton
     */ 
    static public Marshaller getInstance(
    ){
        return URI_1Marshaller.instance;
    }


    //------------------------------------------------------------------------
    // Implements Marshaller
    //------------------------------------------------------------------------

    /**
     * Marshal a CharSequence[] into a CharSequence
     * 
     * @param     charSequences
     *            The array of CharSequences to be marshalled.
     * 
     * @return      A CharSequence containing the marshalled objects.
     */
    public Object marshal (
        Object charSequences
    ) throws ServiceException {
        if (charSequences == null) return null;
        Object[]source = (Object[])charSequences;
        StringBuilder target = new StringBuilder(URI_1Marshaller.OPENMDX_PREFIX);
        for(
                int i=0;
                i < source.length;
        )encode(
            source[i],
            target.append(COMPONENT_DELIMITER),
            ++i == source.length
        );
        return target;
    }


    /**
     * Unmarshal a CharSequence into a CharSequence[].
     * 
     * @param         marshalledObjects
     *            A string containing a marshalled sequence of objects
     * 
     * @return    A String array containing the unmarshaled sequence
     *                  of objects.
     * @exception ServiceException ILLEGAL_ARGUMENT
     */
    public Object unmarshal (
        Object charSequence
    ) throws ServiceException {
        if (charSequence == null) return null;
        ArrayList target = new ArrayList();
        try {
            String source = charSequence.toString();
            if(source.length() > URI_1Marshaller.OPENMDX_PREFIX.length()){
                source = source.substring(URI_1Marshaller.OPENMDX_PREFIX.length());
                if (
                        source.charAt(0) != '/'
                ) throw new ServiceException(
                    BasicException.Code.DEFAULT_DOMAIN,
                    BasicException.Code.BAD_PARAMETER,
                    "Relative URIs are not supported",
                    new BasicException.Parameter("uri",source)
                );
                int fromIndex = 0;
                int toIndex = -1;
                do {
                    toIndex = source.indexOf(
                        COMPONENT_DELIMITER,
                        fromIndex + 1
                    );
                    target.add(
                        decode(
                            source.substring(
                                fromIndex + 1, 
                                toIndex >= 0 ? toIndex : source.length()
                            )
                        )
                    );
                    fromIndex = toIndex;
                } while (toIndex > 0);
            }
            return target.toArray(new String[target.size()]);
        } catch (RuntimeException exception){
            throw new ServiceException(
                exception,
                BasicException.Code.DEFAULT_DOMAIN,
                BasicException.Code.BAD_PARAMETER,
                "CharSequence can't be transformed into an URI",
                new BasicException.Parameter("charSequence", charSequence)
            );
        }
    }

    /**
     * 
     */
    final static private void encode(
        Object charSequence,
        StringBuilder target,
        boolean terminal
    ) throws ServiceException {
        String string = charSequence.toString();
        if(terminal && string.endsWith("%")) {
            encode(
                string.substring(0, string.length() - 1),
                target,
                false
            );
            target.append("%");
        } else try {
            byte[]source=UnicodeTransformation.toByteArray(string);
            for (
                    int index = 0;
                    index < source.length;
                    index++
            ){
                byte octet = source[index];
                if ( 
                        (octet >= '0' && octet <= '9') || // Numeric character
                        (octet >= '@' && octet <= 'Z') || // pchar and Alphanumeric character
                        (octet >= 'a' && octet <= 'z') || // Alphanumeric characer
                        (octet >= '&' && octet <= '.') || // Mark character and pchar
                        octet == '_' || // Mark character
                        octet == '~' || // Mark character
                        octet == '!' || // Mark character
                        octet == '=' || // Mark character
                        octet == '$' || // Mark character
                        octet == ';' || // Parameter delimiter
                        ( // recognize lonley field delimiters
                                octet == FIELD_DELIMITER && (
                                        index + 1 == source.length ||
                                        source[index+1] != FIELD_DELIMITER 
                                ) && (
                                        index == 0 ||
                                        source[index-1] != FIELD_DELIMITER
                                )
                        )
                ){ 
                    target.append((char) octet);
                } else { // Characters to be escaped
                    target.append(ESCAPE);
                    if (octet < 0) {
                        target.append(
                            Integer.toHexString(octet).substring(6)
                        );
                    } else {
                        target.append(
                            Character.forDigit(octet / RADIX, RADIX)
                        ).append(
                            Character.forDigit(octet % RADIX, RADIX)
                        );
                    }
                }
            }
        } catch (RuntimeException exception) {
            throw new ServiceException(exception);
        }
    }


    /**
     *
     */ 
    final static private String decode(
        String source
    ) throws ServiceException {
        byte[] target = new byte[source.length()];
        int targetIndex = 0;
        for (
                int sourceIndex = 0;
                sourceIndex < target.length;
        ) target[targetIndex++] = source.charAt(sourceIndex) == ESCAPE && sourceIndex + 2 < target.length ?
            (byte)Integer.parseInt( // Parse as int to cope with f0 to ff
                source.substring(++sourceIndex, sourceIndex+=2),
                RADIX
            ) :
                (byte)source.charAt(sourceIndex++);
                try {
                    return UnicodeTransformation.toString(target,0, targetIndex);
                } catch (RuntimeException exception) {
                    throw new ServiceException(exception);
                }
    }


    //------------------------------------------------------------------------
    // Constants
    //------------------------------------------------------------------------

    final static public String ROOT = "/";

    final static public char COMPONENT_DELIMITER = '/';

    final static public char FIELD_DELIMITER = ':';

    final static public char ESCAPE = '%';

    final static int RADIX = 16;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy