/*
 * Copyright 2004-2005 the original author or authors.
 *
 * Licensed 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 grails.util;

import java.io.*;
import java.util.Properties;

/**
 * Represents the application Metadata and loading mechanics
 *
 * @author Graeme Rocher
 * @since 1.1
 * 
 * Created: Dec 12, 2008
 */

public class Metadata extends Properties {

    public static final String FILE = "application.properties";
    public static final String APPLICATION_VERSION = "app.version";
    public static final String APPLICATION_NAME = "app.name";
    public static final String APPLICATION_GRAILS_VERSION = "app.grails.version";
    public static final String SERVLET_VERSION = "app.servlet.version";
    public static final String WAR_DEPLOYED = "grails.war.deployed";
    public static final String DEFAULT_SERVLET_VERSION = "2.4";
    
    private boolean initialized;
    private static Metadata metadata = new Metadata();
    private static File metadataFile;

    private Metadata() {
        super();
    }

    /**
     * @return Returns the metadata for the current application
     */
    public static Metadata getCurrent() {
        if(!metadata.initialized) {
            try {
                InputStream input = Metadata.class.getClassLoader().getResourceAsStream(FILE);
                if(input != null) {
                    metadata.load(input);
                }
            }
            catch (Exception e) {
                throw new RuntimeException("Cannot load application metadata:" + e.getMessage(), e);
            }
            finally {
                metadata.initialized = true;
            }

        }

        return metadata;
    }

    /***
     * Loads a Metadata instance from a Reader
     * @param reader The reader
     * @return a Metadata instance
     */
    public static Metadata getInstance(InputStream inputStream) {
        metadata = new Metadata();

        try {
            metadata.load(inputStream);
            metadata.initialized=true;
        }
        catch (IOException e) {
            throw new RuntimeException("Cannot load application metadata:" + e.getMessage(), e);
        }
        return metadata;
    }

    /**
     * Loads and returns a new Metadata object for the given File
     * @param file The File
     * @return A Metadata object
     */
    public static Metadata getInstance(File file) {
        metadata = new Metadata();
        metadataFile = file;

        if(file!= null && file.exists()) {

            FileInputStream input = null;
            try {
                input = new FileInputStream(file);
                metadata.load(input);
                metadata.initialized = true;
            }
            catch (Exception e) {
                throw new RuntimeException("Cannot load application metadata:" + e.getMessage(), e);
            }
            finally {
                try {
                    if(input!=null) input.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
        return metadata;
    }

    /**
     * Reloads the application metadata
     * @return The metadata object
     */
    public static Metadata reload() {
        if(metadataFile!=null)
            metadata = getInstance(metadataFile);
        return metadata;
    }

    /**
     * @return The application version
     */
    public String getApplicationVersion() {
        return (String) get(APPLICATION_VERSION);
    }

    /**
     * @return The Grails version used to build the application
     */
    public String getGrailsVersion() {
        return (String) get(APPLICATION_GRAILS_VERSION);
    }


    /**
     * @return The environment the application expects to run in
     */
    public String getEnvironment() {
        return (String) get(Environment.KEY);        
    }

    /**
     * @return The application name
     */
    public String getApplicationName() {
        return (String) get(APPLICATION_NAME);
    }

    /**
     * @return The version of the servlet spec the application was created for
     */
    public String getServletVersion() {
        final String servletVersion = (String) get(SERVLET_VERSION);
        if(servletVersion == null) {
            return DEFAULT_SERVLET_VERSION;
        }
        return servletVersion;
    }

    /**
     * Saves the current state of the Metadata object
     */
    public void persist() {

        if(metadataFile != null) {
            FileOutputStream out = null;

            try {
                out = new FileOutputStream(metadataFile);
                store(out, "utf-8");
            }
            catch (Exception e) {
                throw new RuntimeException("Error persisting metadata to file ["+metadataFile+"]: " + e.getMessage(),e );
            }
            finally {
                try {
                    if(out != null) out.close();
                }
                catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    /**
     * @return Returns true if this application is deployed as a WAR
     */
    public boolean isWarDeployed() {
        Object val = get(WAR_DEPLOYED);
        return val != null && val.equals("true");
    }
}
@@ -1742,16 +1742,154 @@
  input =
+ Thread.currentThread().getContextClassLoader().getResourceAsStream(FILE);%0A                if(input == null) %7B%0A                    input =
  Metadat
@@ -1932,32 +1932,50 @@
 AsStream(FILE);%0A
+                %7D%0A
                 
@@ -2416,25 +2416,35 @@
 ram 
-reader The reader
+inputStream The InputStream
 %0A   

Fix for GRAILS-4396. Use context loader first to load application.properties