class AvailablePlugin extends PluginMetadata
{
    private static final Logger Log = LoggerFactory.getLogger( AvailablePlugin.class );
    private static final DateFormat RELEASE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
    private static final DateFormat RELEASE_DATE_DISPLAY_FORMAT = DateFormat.getDateInstance(DateFormat.MEDIUM);

    /**
     * URL from where the latest version of the plugin can be downloaded.
     */
    private final URL downloadURL;

    /**
     * Size in bytes of the plugin jar file.
     */
    private final long fileSize;
    private final String releaseDate;

    public static AvailablePlugin getInstance( Element plugin )
    {<FILL_FUNCTION_BODY>}
    public AvailablePlugin(String name, String canonicalName, String description, Version latestVersion, String author,
                           URL icon, URL changelog, URL readme, String license,
                           Version minServerVersion, Version priorToServerVersion, JavaSpecVersion minJavaVersion,
                           URL downloadUrl, long fileSize, final String releaseDate) {
        super(
                name,
                canonicalName,
                description,
                latestVersion,
                author,
                icon,
                changelog,
                readme,
                license,
                minServerVersion,
                priorToServerVersion,
                minJavaVersion,
                false
        );
        this.downloadURL = downloadUrl;
        this.fileSize = fileSize;
        this.releaseDate = releaseDate;
    }

    /**
     * URL from where the latest version of the plugin can be downloaded.
     *
     * @return download URL.
     */
    public URL getDownloadURL() {
        return downloadURL;
    }
    /**
     * Returns the size in bytes of the plugin jar file.
     *
     * @return the size in bytes of the plugin jar file.
     */
    public long getFileSize() {
        return fileSize;
    }

    /**
     * @return the date the plugin was released
     */
    public String getReleaseDate() {
        return releaseDate;
    }
}

        String pluginName = plugin.attributeValue("name");
        Version latestVersion = null;
        String latestVersionValue = plugin.attributeValue("latest");
        if ( latestVersionValue != null && !latestVersionValue.isEmpty() )
        {
            latestVersion = new Version( latestVersionValue );
        }

        URL icon = null;
        String iconValue = plugin.attributeValue("icon");
        if ( iconValue != null && !iconValue.isEmpty() )
        {
            try
            {
                icon = new URL( iconValue );
            }
            catch ( MalformedURLException e )
            {
                Log.warn( "Unable to create icon URL from value '{}' for plugin {}.", iconValue, pluginName, e );
            }
        }

        URL readme = null;
        String readmeValue = plugin.attributeValue("readme");
        if ( readmeValue != null && !readmeValue.isEmpty() )
        {
            try
            {
                readme = new URL( readmeValue );
            }
            catch ( MalformedURLException e )
            {
                Log.warn( "Unable to create readme URL from value '{}' for plugin {}.", readmeValue, pluginName, e );
            }
        }

        URL changelog = null;
        String changelogValue = plugin.attributeValue("changelog");
        if ( changelogValue != null && !changelogValue.isEmpty() )
        {
            try
            {
                changelog = new URL( changelogValue );
            }
            catch ( MalformedURLException e )
            {
                Log.warn( "Unable to create changelog URL from value '{}' for plugin {}.", changelogValue, pluginName, e );
            }
        }
        URL downloadUrl = null;
        String downloadUrlValue = plugin.attributeValue("url");
        if ( downloadUrlValue != null && !downloadUrlValue.isEmpty() )
        {
            try
            {
                downloadUrl = new URL( downloadUrlValue );
            }
            catch ( MalformedURLException e )
            {
                Log.warn( "Unable to create download URL from value '{}' for plugin {}.", downloadUrlValue, pluginName, e );
            }
        }

        String license = plugin.attributeValue("licenseType");
        String description = plugin.attributeValue("description");
        String author = plugin.attributeValue("author");

        Version minServerVersion = null;
        String minServerVersionValue = plugin.attributeValue("minServerVersion");
        if ( minServerVersionValue != null && !minServerVersionValue.isEmpty() )
        {
            minServerVersion = new Version( minServerVersionValue );
        }

        Version priorToServerVersion = null;
        String priorToServerVersionValue = plugin.attributeValue("priorToServerVersion");
        if ( priorToServerVersionValue != null && !priorToServerVersionValue.isEmpty() )
        {
            priorToServerVersion = new Version( priorToServerVersionValue );
        }

        JavaSpecVersion minJavaVersion = null;
        String minJavaVersionValue = plugin.attributeValue( "minJavaVersion" );
        if ( minJavaVersionValue != null && !minJavaVersionValue.isEmpty() )
        {
            minJavaVersion = new JavaSpecVersion( minJavaVersionValue );
        }

        String releaseDate = null;
        final String releaseDateString = plugin.attributeValue("releaseDate");
        if( releaseDateString!= null) {
            try {
                releaseDate = RELEASE_DATE_DISPLAY_FORMAT.format(RELEASE_DATE_FORMAT.parse(releaseDateString));
            } catch (final ParseException e) {
                Log.warn("Unexpected exception parsing release date: " + releaseDateString, e);
            }
        }

        long fileSize = -1;
        String fileSizeValue = plugin.attributeValue("fileSize");
        if ( fileSizeValue != null && !fileSizeValue.isEmpty() )
        {
            fileSize = Long.parseLong( fileSizeValue );
        }

        String canonical = downloadUrlValue != null ? downloadUrlValue.substring( downloadUrlValue.lastIndexOf( '/' ) + 1, downloadUrlValue.lastIndexOf( '.' ) ) : null;

        return new AvailablePlugin(
                pluginName,
                canonical,
                description,
                latestVersion,
                author,
                icon,
                changelog,
                readme,
                license,
                minServerVersion,
                priorToServerVersion,
                minJavaVersion,
                downloadUrl,
                fileSize,
                releaseDate
        );

    
<methods>public void <init>(java.lang.String, java.lang.String, java.lang.String, org.jivesoftware.util.Version, java.lang.String, java.net.URL, java.net.URL, java.net.URL, java.lang.String, org.jivesoftware.util.Version, org.jivesoftware.util.Version, org.jivesoftware.util.JavaSpecVersion, boolean) ,public java.lang.String getAuthor() ,public java.lang.String getCanonicalName() ,public java.net.URL getChangelog() ,public java.lang.String getDescription() ,public java.lang.String getHashCode() ,public java.net.URL getIcon() ,public static org.jivesoftware.openfire.container.PluginMetadata getInstance(java.nio.file.Path) ,public static org.jivesoftware.openfire.container.PluginMetadata getInstance(org.jivesoftware.openfire.container.Plugin) ,public java.lang.String getLicense() ,public org.jivesoftware.util.JavaSpecVersion getMinJavaVersion() ,public org.jivesoftware.util.Version getMinServerVersion() ,public java.lang.String getName() ,public org.jivesoftware.util.Version getPriorToServerVersion() ,public java.net.URL getReadme() ,public org.jivesoftware.util.Version getVersion() ,public boolean isCsrfProtectionEnabled() <variables>private final non-sealed java.lang.String author,private final non-sealed java.lang.String canonicalName,private final non-sealed java.net.URL changelog,private final non-sealed boolean csrfProtectionEnabled,private final non-sealed java.lang.String description,private final non-sealed java.net.URL icon,private final non-sealed java.lang.String license,private final non-sealed org.jivesoftware.util.JavaSpecVersion minJavaVersion,private final non-sealed org.jivesoftware.util.Version minServerVersion,private final non-sealed java.lang.String name,private final non-sealed org.jivesoftware.util.Version priorToServerVersion,private final non-sealed java.net.URL readme,private final non-sealed org.jivesoftware.util.Version version