001    /**
002     * Copyright 2010-2012 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.codehaus.mojo.license;
017    
018    import java.io.File;
019    import java.io.FileInputStream;
020    import java.io.FileOutputStream;
021    import java.io.IOException;
022    import java.io.OutputStream;
023    import java.util.Collections;
024    import java.util.Enumeration;
025    import java.util.List;
026    import java.util.Properties;
027    import java.util.Vector;
028    
029    /**
030     * Permet d'avoir les fichiers de proprietes tries.
031     *
032     * @author ruchaud <ruchaud@codelutin.com>
033     * @author tchemit <chemit@codelutin.com>
034     * @since 1.0
035     */
036    public class SortedProperties extends Properties {
037    
038        private static final long serialVersionUID = -1147150444452577558L;
039    
040        /**
041         * l'encoding a utiliser pour lire et ecrire le properties.
042         */
043        protected String encoding;
044    
045        /**
046         * un drapeau pour savoir s'il faut enlever l'entete generere
047         */
048        protected boolean removeHeader;
049    
050        public SortedProperties(String encoding) {
051            this(encoding, true);
052        }
053    
054        public SortedProperties(String encoding, boolean removeHeader) {
055            this.encoding = encoding;
056            this.removeHeader = removeHeader;
057        }
058    
059        public SortedProperties(Properties defaults) {
060            super(defaults);
061        }
062    
063        @Override
064        public Enumeration<Object> keys() {
065            List<Object> objects = Collections.list(super.keys());
066            Vector<Object> result;
067            try {
068                // Attention, si les clef ne sont pas des string, ca ne marchera pas
069                List<String> list = toGenericList(objects, String.class);
070                Collections.sort(list);
071                result = new Vector<Object>(list);
072            } catch (IllegalArgumentException e) {
073                // keys are not string !!!
074                // can not sort keys
075                result = new Vector<Object>(objects);
076            }
077            return result.elements();
078        }
079    
080        /**
081         * Charge le properties a partir d'un fichier.
082         *
083         * @param src
084         *            le fichier src a charger en utilisant l'encoding declare
085         * @return l'instance du properties
086         * @throws java.io.IOException
087         *             if any io pb
088         */
089        public SortedProperties load(File src) throws IOException {
090            FileInputStream reader = new FileInputStream(src);
091            try {
092                load(reader);
093            } finally {
094                reader.close();
095            }
096            return this;
097        }
098    
099        /**
100         * Sauvegarde le properties dans un fichier, sans commentaire et en utilisant l'encoding declare.
101         *
102         * @param dst
103         *            the fichier de destination
104         * @throws java.io.IOException
105         *             if any io pb
106         */
107        public void store(File dst) throws IOException {
108            OutputStream writer = new FileOutputStream(dst);
109            try {
110                store(writer, null);
111            } finally {
112                writer.close();
113            }
114        }
115    
116        /**
117         * Permet de convertir une liste non typee, en une liste typee.
118         * <p/>
119         * La liste en entree en juste bien castee.
120         * <p/>
121         * On effectue une verification sur le typage des elements de la liste.
122         * <p/>
123         * Note : <b>Aucune liste n'est creee, ni recopiee</b>
124         *
125         * @param <O>
126         *            le type des objets de la liste
127         * @param list
128         *            la liste a convertir
129         * @param type
130         *            le type des elements de la liste
131         * @return la liste typee
132         * @throws IllegalArgumentException
133         *             si un element de la liste en entree n'est pas en adequation avec le type voulue.
134         */
135        @SuppressWarnings({ "unchecked" })
136        static public <O> List<O> toGenericList(List<?> list, Class<O> type) throws IllegalArgumentException {
137            if (list.isEmpty()) {
138                return (List<O>) list;
139            }
140            for (Object o : list) {
141                if (!type.isAssignableFrom(o.getClass())) {
142                    throw new IllegalArgumentException("can not cast List with object of type " + o.getClass() + " to "
143                            + type + " type!");
144                }
145            }
146            return (List<O>) list;
147        }
148    
149    }