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

jnlp.sample.servlet.ResourceCatalog Maven / Gradle / Ivy

Go to download

JNLP Sample servlet that supports pack200 protocol. Taken from Sun's JDK sample/jnlp directory thanks to its permissive license.

The newest version!
/*
 * @(#)ResourceCatalog.java	1.6 05/11/17
 * 
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution 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 Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */

package jnlp.sample.servlet;

import jnlp.sample.util.VersionID;
import jnlp.sample.util.VersionString;
import org.w3c.dom.Document;
import org.xml.sax.SAXParseException;

import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class ResourceCatalog
{
    public static final String VERSION_XML_FILENAME = "version.xml";

    private Logger _log = null;

    private ServletContext _servletContext = null;

    private HashMap _entries;

    /**
     * Class to contain the information we know
     * about a specific directory
     */
    static private class PathEntries
    {
        /* Version-based entries at this particular path */
        private List _versionXmlList;

        private List _directoryList;

        private List _platformList;

        /* Last time this entry was updated */
        private long _lastModified; // Last modified time of entry;

        public PathEntries( List versionXmlList, List directoryList, List platformList, long lastModified )
        {
            _versionXmlList = versionXmlList;
            _directoryList = directoryList;
            _platformList = platformList;
            _lastModified = lastModified;
        }


        public void setDirectoryList( List dirList )
        {
            _directoryList = dirList;
        }

        public List getVersionXmlList()
        {
            return _versionXmlList;
        }

        public List getDirectoryList()
        {
            return _directoryList;
        }

        public List getPlatformList()
        {
            return _platformList;
        }

        public long getLastModified()
        {
            return _lastModified;
        }
    }

    public ResourceCatalog( ServletContext servletContext, Logger log )
    {
        _entries = new HashMap();
        _servletContext = servletContext;
        _log = log;
    }


    public JnlpResource lookupResource( DownloadRequest dreq )
        throws ErrorResponseException
    {
        // Split request up into path and name
        String path = dreq.getPath();
        String name = null;
        String dir = null;
        int idx = path.lastIndexOf( '/' );
        if ( idx == -1 )
        {
            name = path;
        }
        else
        {
            name = path.substring( idx + 1 ); // Exclude '/'
            dir = path.substring( 0, idx + 1 ); // Include '/'
        }

        // Lookup up already parsed entries, and san directory for entries if neccesary
        PathEntries pentries = (PathEntries) _entries.get( dir );
        JnlpResource xmlVersionResPath = new JnlpResource( _servletContext, dir + VERSION_XML_FILENAME );
        if ( pentries == null ||
            ( xmlVersionResPath.exists() && xmlVersionResPath.getLastModified() > pentries.getLastModified() ) )
        {
            _log.addInformational( "servlet.log.scandir", dir );
            List dirList = scanDirectory( dir, dreq );
            // Scan XML file
            List versionList = new ArrayList();
            List platformList = new ArrayList();
            parseVersionXML( versionList, platformList, dir, xmlVersionResPath );
            pentries = new PathEntries( versionList, dirList, platformList, xmlVersionResPath.getLastModified() );
            _entries.put( dir, pentries );
        }

        // Search for a match
        JnlpResource[] result = new JnlpResource[1];

        if ( dreq.isPlatformRequest() )
        {
            int sts = findMatch( pentries.getPlatformList(), name, dreq, result );
            if ( sts != DownloadResponse.STS_00_OK )
            {
                throw new ErrorResponseException( DownloadResponse.getJnlpErrorResponse( sts ) );
            }
        }
        else
        {
            // First lookup in versions.xml file
            int sts1 = findMatch( pentries.getVersionXmlList(), name, dreq, result );
            if ( sts1 != DownloadResponse.STS_00_OK )
            {
                // Then lookup in directory
                int sts2 = findMatch( pentries.getDirectoryList(), name, dreq, result );
                if ( sts2 != DownloadResponse.STS_00_OK )
                {

                    // fix for 4450104
                    // try rescan and see if it helps
                    pentries.setDirectoryList( scanDirectory( dir, dreq ) );
                    sts2 = findMatch( pentries.getDirectoryList(), name, dreq, result );
                    // try again after rescanning directory
                    if ( sts2 != DownloadResponse.STS_00_OK )
                    {
                        // Throw the most specific error code
                        throw new ErrorResponseException(
                            DownloadResponse.getJnlpErrorResponse( Math.max( sts1, sts2 ) ) );
                    }
                }
            }
        }
        return result[0];
    }

    /**
     * This method finds the best match, or return the best error code. The
     * result parameter must be an array with room for one element.
     * 

* If a match is found, the method returns DownloadResponse.STS_00_OK * If one or more entries matches on: name, version-id, os, arch, and locale, * then the one with the highest version-id is set in the result[0] field. *

* If a match is not found, it returns an error code, either: ERR_10_NO_RESOURCE, * ERR_11_NO_VERSION, ERR_20_UNSUP_OS, ERR_21_UNSUP_ARCH, ERR_22_UNSUP_LOCALE, * ERR_23_UNSUP_JRE. */ public int findMatch( List list, String name, DownloadRequest dreq, JnlpResource[] result ) { if ( list == null ) { return DownloadResponse.ERR_10_NO_RESOURCE; } // Setup return values VersionID bestVersionId = null; int error = DownloadResponse.ERR_10_NO_RESOURCE; VersionString vs = new VersionString( dreq.getVersion() ); // Iterate through entries for ( int i = 0; i < list.size(); i++ ) { JnlpResource respath = (JnlpResource) list.get( i ); VersionID vid = new VersionID( respath.getVersionId() ); int sts = matchEntry( name, vs, dreq, respath, vid ); if ( sts == DownloadResponse.STS_00_OK ) { if ( result[0] == null || vid.isGreaterThan( bestVersionId ) ) { result[0] = respath; bestVersionId = vid; } } else { error = Math.max( error, sts ); } } return ( result[0] != null ) ? DownloadResponse.STS_00_OK : error; } public int matchEntry( String name, VersionString vs, DownloadRequest dreq, JnlpResource jnlpres, VersionID vid ) { if ( !name.equals( jnlpres.getName() ) ) { return DownloadResponse.ERR_10_NO_RESOURCE; } if ( !vs.contains( vid ) ) { return DownloadResponse.ERR_11_NO_VERSION; } if ( !prefixMatchLists( jnlpres.getOSList(), dreq.getOS() ) ) { return DownloadResponse.ERR_20_UNSUP_OS; } if ( !prefixMatchLists( jnlpres.getArchList(), dreq.getArch() ) ) { return DownloadResponse.ERR_21_UNSUP_ARCH; } if ( !prefixMatchLists( jnlpres.getLocaleList(), dreq.getLocale() ) ) { return DownloadResponse.ERR_22_UNSUP_LOCALE; } return DownloadResponse.STS_00_OK; } private static boolean prefixMatchStringList( String[] prefixList, String target ) { // No prefixes matches everything if ( prefixList == null ) { return true; } // No target, but a prefix list does not match anything if ( target == null ) { return false; } for ( int i = 0; i < prefixList.length; i++ ) { if ( target.startsWith( prefixList[i] ) ) { return true; } } return false; } /* Return true if at least one of the strings in 'prefixes' are a prefix * to at least one of the 'keys'. */ public boolean prefixMatchLists( String[] prefixes, String[] keys ) { // The prefixes are part of the server resources. If none is given, // everything matches if ( prefixes == null ) { return true; } // If no os keyes was given, and the server resource is keyed of this, // then return false. if ( keys == null ) { return false; } // Check for a match on a key for ( int i = 0; i < keys.length; i++ ) { if ( prefixMatchStringList( prefixes, keys[i] ) ) { return true; } } return false; } /** * This method scans the directory pointed to by the * given path and creates a list of ResourcePath elements * that contains information about all the entries *

* The version-based information is encoded in the file name * given the following format: *

* entry ::= __ ( ). * options ::=





© 2015 - 2024 Weber Informatics LLC | Privacy Policy