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

com.eva.properties.Proxy Maven / Gradle / Ivy

/*
 * $Id: Proxy.java 109 2007-03-24 14:55:03Z max $
 * 
 * Copyright (c) 2006-2007 Maximilian Antoni. All rights reserved.
 * 
 * This software is licensed as described in the file LICENSE.txt, which you
 * should have received as part of this distribution. The terms are also
 * available at http://www.maxantoni.de/projects/eva-properties/license.txt.
 */
package com.eva.properties;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;

/**
 * is a proxy for another properties file referenced by a path.
 * 
 * @author Max Antoni
 * @version $Revision: 109 $
 */
public class Proxy implements Replaceable {

    /**
     * interface for internal delegate types used to resolve the object behind
     * the proxy.
     */
    private static interface Type {
        
        /**
         * resolves the object behind the proxy.
         * 
         * @param inParent the parent properties to use.
         * @param inContext the current context.
         * @return the resolved object.
         */
        Object resolve(Properties inParent, Context inContext);
        
        /**
         * returns the null object to use while resolving the
         * actual object.
         * 
         * @return the null object.
         */
        Object getNullObject();
    }
    
    /**
     * delegate to resolve another properties object from a path.
     */
    private static class TypePath implements Type {
        /**
         * the path to the external properties file.
         */
        private String path;
        
        /**
         * creates a new delegate with the given path.
         * 
         * @param inPath the path.
         */
        TypePath(String inPath) {
            path = inPath;
        }
        
        /*
         * @see com.eva.properties.Proxy.Type#resolve(
         *      com.eva.properties.Properties, com.eva.properties.Context)
         */
        public Object resolve(Properties inParent, Context inContext) {
            String replacedPath = Replacer.replace(path, inContext);
            if(replacedPath == null) {
                return Null.INSTANCE;
            }
            DataSource dataSource;
            try {
                dataSource = new DataSource((ClassLoader) inContext
                        .lookup("classloader"), replacedPath);
            }
            catch(FileNotFoundException e) {
                /*
                 * This might happen a couple of times when a switch is
                 * processed.
                 */
                Log.instance().log(Level.FINE, "PropertiesProxy.fileNotFound",
                        replacedPath);
                return Null.INSTANCE;
            }
            if(Log.instance().isLoggable(Level.CONFIG)) {
                Log.instance().log(Level.CONFIG,
                        "PropertiesProxy.readingProperties",
                        dataSource.toString());
            }
            try {
                // It is okay to pass null as the parent here:
                return PropertiesParser.read(inParent, dataSource);
            }
            catch(IOException e) {
                throw new PropertiesException(
                        "IOException while reading super properties "
                                + replacedPath + ": " + e.getMessage());
            }
            catch(PropertiesException e) {
                throw new PropertiesException(
                        "PropertiesException while reading super properties "
                                + replacedPath + ": " + e.getMessage());
            }
        }
        
        /*
         * @see java.lang.Object#toString()
         */
        public String toString() {
            return "&\"" + path + "\"";
        }

        /*
         * @see com.eva.properties.Proxy.Type#getNullObject()
         */
        public Object getNullObject() {
            return NoProperties.INSTANCE;
        }
    }
    
    /**
     * delegate to resolve objects from a replaceable.
     */
    private static class TypeReplaceable implements Type {
        /**
         * the replaceable that provides the object.
         */
        private Replaceable replaceable;
        
        /**
         * creates a delegate with the given replaceable.
         * 
         * @param inReplaceable the replaceable.
         */
        TypeReplaceable(Replaceable inReplaceable) {
            replaceable = inReplaceable;
        }
        
        /*
         * @see com.eva.properties.Proxy.Type#resolve(
         *      com.eva.properties.Properties, com.eva.properties.Context)
         */
        public Object resolve(Properties inParent, Context inContext) {
            return replaceable.replace(inContext);
        }
        
        /*
         * @see java.lang.Object#toString()
         */
        public String toString() {
            return "&" + replaceable.toString();
        }

        /*
         * @see com.eva.properties.Proxy.Type#getNullObject()
         */
        public Object getNullObject() {
            return Null.INSTANCE;
        }
        
    }
    
    /**
     * the replaced object. This is null if
     * {@link #replace(Context)} was not yet called.
     */
    private Object object;
    
    /**
     * the parent properties to use. Can be null.
     */
    private Properties parent;
    
    /**
     * the delegate to use to resolve the object behind this proxy.
     */
    private Type type;
    
    /**
     * creates a proxy with a path.
     * 
     * @param inPath the path.
     * @throws NullPointerException if the path is null.
     */
    public Proxy(String inPath) {
        if(inPath == null) {
            throw new NullPointerException("Path cannot be null.");
        }
        if("".equals(inPath)) {
            throw new IllegalArgumentException("Path cannot be empty.");
        }
        type = new TypePath(inPath);
    }
    
    /**
     * creates a proxy with a parent properties object and a replaceable.
     * @param inParent the parent properties. 
     * @param inReplaceable the replaceable.
     * @throws NullPointerException if the replaceable is null.
     */
    Proxy(Properties inParent, Replaceable inReplaceable) {
        if(inReplaceable == null) {
            throw new NullPointerException("Replaceable cannot be null.");
        }
        parent = inParent;
        type = new TypeReplaceable(inReplaceable);
    }
    
    /**
     * creates a proxy with a parent properties object and a path.
     *  
     * @param inParent the parent properties. 
     * @param inPath the path.
     * @throws NullPointerException if the path is null.
     */
    Proxy(Properties inParent, String inPath) {
        this(inPath);
        parent = inParent;
    }

    /**
     * creates a proxy with parent properties and a type.
     *  
     * @param inParent the parent properties. 
     * @param inType the type.
     */
    private Proxy(Properties inParent, Type inType) {
        this(inType);
        parent = inParent;
    }
    
    /**
     * creates a proxy with the given type.
     * 
     * @param inType the type.
     */
    private Proxy(Type inType) {
        type = inType;
    }
    
    /*
     * @see com.eva.properties.Replaceable#copy(com.eva.properties.Properties)
     */
    public Replaceable copy(Properties inParent) {
        Proxy proxy = new Proxy(inParent, type);
        if(object != null) {
            if(object instanceof Replaceable) {
                proxy.object = ((Replaceable) object).copy(inParent);
            }
            else {
                proxy.object = object;
            }
        }
        return proxy;
    }
    
    /* 
     * @see com.eva.properties.Replaceable#replace(com.eva.properties.Context)
     */
    public Object replace(Context inContext) throws PropertiesException {
        if(object == null) {
            /*
             * For a path, set object to NoProperties.INSTANCE to avoid
             * recursive call when a proxy is used for "super". If something
             * needs to be replaced inside the super reference a recursive call
             * would be the consequence.
             * For a references, use Null.INSTANCE:
             */
            object = type.getNullObject();
            object = type.resolve(parent, inContext);
        }
        return object;
    }

    /* 
     * @see java.lang.Object#toString()
     */
    public String toString() {
        return type.toString();
    }

    /*
     * @see com.eva.properties.Replaceable#toString(java.lang.StringBuffer,
     *      java.lang.String)
     */
    public void write(Writer inoutWriter) {
        inoutWriter.append(type.toString());
        inoutWriter.append("\n");
    }

    /**
     * sets the parent properties for this proxy.
     * 
     * @param inParent the parent properties.
     */
    void setParent(Properties inParent) {
        parent = inParent;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy