Package com.fasterxml.storemate.shared

Examples of com.fasterxml.storemate.shared.ByteRange


    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        final StorableStore entryStore = _stores.getEntryStore();
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForReads(entryStore, key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, entryStore,
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        // #21: provide content length header
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // one more thing; add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Issue #6: Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here


    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForGet(key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, _stores.getEntryStore(),
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here

    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        final StorableStore entryStore = _stores.getEntryStore();
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForReads(entryStore, key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, entryStore,
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        // #21: provide content length header
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // one more thing; add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Issue #6: Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here

    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForGet(key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, _stores.getEntryStore(),
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        // #21: provide content length header
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // one more thing; add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Issue #6: Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here

    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForGet(key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, _stores.getEntryStore(),
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here

public class ByteRangeTest extends SharedTestBase
{
    public void testSimpleValid()
    {
        String src = "bytes=0-500";
        ByteRange range = ByteRange.valueOf(src);
        assertEquals(0, range.getStart());
        assertEquals(500, range.getEnd());
        assertEquals(src, range.toString());
        assertEquals("bytes 0-500", range.asRequestHeader());
        assertEquals("bytes 0-500/*", range.asResponseHeader());

        src = "bytes=-2";
        range = ByteRange.valueOf(src);
        assertEquals(-2, range.getStart());
        // end not really defined...
        assertEquals(-1, range.getEnd());
        assertEquals(src, range.toString());
        range = range.resolveWithTotalLength(100);
        assertEquals("bytes 98-99", range.asRequestHeader());
        assertEquals("bytes 98-99/100", range.asResponseHeader());

        // also, may add total length indicator; if so, should be included
        src = "bytes=0-499/1500";
        range = ByteRange.valueOf(src);
        assertEquals(0, range.getStart());
        assertEquals(499, range.getEnd());
        assertEquals(1500, range.getTotalLength());
        assertEquals("bytes 0-499", range.asRequestHeader());
        assertEquals("bytes 0-499/1500", range.asResponseHeader());
    }
View Full Code Here

        if (start < 0) { // suffix, yup; must modify
            // since start is offset from end (and negative), works with addition
            // but we must consider possibility it might go beyond start, so:
            start = Math.max(0, totalLength+start);
        }
        return new ByteRange(start, end, totalLength, _source);
    }
View Full Code Here

        if (ix < 0) {
            throw new IllegalArgumentException("no hyphen found");
        }
        if (ix == 0) { // suffix entry
            // suffix range, yay; parse as negative number
            return new ByteRange(parseLong(external), -1, -1, rangeDesc);
        }
        // actual range
        long start = parseLong(external.substring(0,ix));
        String num = external.substring(ix+1).trim();
        long end;
        if (num.length() == 0) { // missing end range -- fine, use -1 to indicate 'till the end'
            end = -1;
        } else {
            end = parseLong(num);
            if (end < start) {
                throw new IllegalArgumentException("range end can not be less than start");
            }
        }
        return new ByteRange(start, end, totalLength, rangeDesc);
    }
View Full Code Here

    public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
            OperationDiagnostics diag)
        throws StoreException
    {
        String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
        ByteRange range;
        try {
            range = request.findByteRange();
        } catch (IllegalArgumentException e) {
            return invalidRange(response, key, rangeStr, e.getMessage());
        }
        final StorableStore entryStore = _stores.getEntryStore();
        String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
        Storable rawEntry;

        try {
            rawEntry = findRawEntryForReads(entryStore, key, diag);
        } catch (IOException e) {
            return _storeError(response, key, e);
        }
        if (rawEntry == null) {
            return handleGetForMissing(request, response, key);
        }
        // second: did we get a tombstone?
        if (rawEntry.isDeleted()) {
            ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
            if (resp != null) {
                return resp;
            }
        }
        // [issue #7]: Conditional GET with Etag
        if (_notChanged(request, rawEntry)) {
            return response.notChanged();
        }

        final long accessTime = _timeMaster.currentTimeMillis();
        final E entry = _entryConverter.entryFromStorable(rawEntry);

        updateLastAccessedForGet(request, response, entry, accessTime);
       
        Compression comp = entry.getCompression();
        boolean skipCompression;

        // Range to resolve, now that we know full length?
        if (range != null) {
            range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
            final long length = range.calculateLength();
            // any bytes matching? If not, it's a failure
            if (length <= 0L) {
                return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
            }
            // note: can not skip decompress if we have to give range...
            skipCompression = false;
        } else {
            skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
        }
       
        StreamingResponseContent output;

        if (entry.hasExternalData()) { // need to stream from File
            File f = entry.getRaw().getExternalFile(_fileManager);
            // this is where we can expect to get "file not found exception".
            // NOTE: not optimal, since this is one I/O operation that is outside throttling;
            // but that can't be helped for now -- we MUST catch the problem here, before
            // adding other response information
            try {
                output = new FileBackedResponseContentImpl(diag, _timeMaster, entryStore,
                    accessTime, f, skipCompression ? null : comp, range, entry);
            } catch (StoreException e) {
                LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
                return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
            }
        } else { // inline
            ByteContainer inlined = entry.getRaw().getInlinedData();
            if (!skipCompression) {
                try {
                    inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
                } catch (IOException e) {
                    return internalGetError(response, e, key, "Failed to decompress inline data");
                }
            }
            output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
        }
        // #21: provide content length header
        long cl = output.getLength();
        if (cl >= 0L) {
            response = response.setContentLength(cl);
        }
        // one more thing; add header for range if necessary; also, response code differs
        if (range == null) {
            response = response.ok(output);
        } else {
            response = response.partialContent(output, range.asResponseHeader());
        }
        // Issue #6: Need to provide Etag, if content hash available
        int contentHash = rawEntry.getContentHash();
        if (contentHash != HashConstants.NO_CHECKSUM) {
            StringBuilder sb = new StringBuilder();
View Full Code Here

TOP

Related Classes of com.fasterxml.storemate.shared.ByteRange

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.