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.kuali.common.util.property;
017    
018    import java.util.ArrayList;
019    import java.util.List;
020    import java.util.Properties;
021    
022    import org.kuali.common.util.CollectionUtils;
023    import org.kuali.common.util.LocationUtils;
024    import org.kuali.common.util.Mode;
025    import org.kuali.common.util.ModeUtils;
026    import org.kuali.common.util.PropertyUtils;
027    import org.kuali.common.util.property.processor.GlobalOverrideProcessor;
028    import org.kuali.common.util.property.processor.HomeProcessor;
029    import org.kuali.common.util.property.processor.OrgProcessor;
030    import org.kuali.common.util.property.processor.PathProcessor;
031    import org.kuali.common.util.property.processor.PropertyProcessor;
032    import org.kuali.common.util.property.processor.ResolvePlaceholdersProcessor;
033    import org.kuali.common.util.property.processor.TrimProcessor;
034    import org.kuali.common.util.property.processor.VersionProcessor;
035    import org.slf4j.Logger;
036    import org.slf4j.LoggerFactory;
037    import org.springframework.util.Assert;
038    
039    public class DefaultPropertyLoadContext extends DefaultPropertyContext implements PropertyLoadContext {
040            
041            private static final Logger logger = LoggerFactory.getLogger(DefaultPropertyLoadContext.class);
042    
043            List<String> locations;
044            String encoding = "UTF-8";
045            String missingLocationsMode = Mode.INFORM.name();
046            Properties locationHelperProperties;
047            String locationHelperInclude;
048            String locationHelperExclude;
049            List<String> locationHelperIncludes;
050            List<String> locationHelperExcludes;
051            String organizationGroupId;
052            String groupIdProperty = Constants.DEFAULT_GROUP_ID_PROPERTY;
053            String versionProperty = Constants.DEFAULT_VERSION_PROPERTY;
054    
055            @Override
056            public Properties init() {
057                    Assert.notNull(helper, "helper is null");
058                    Properties global = getGlobalProperties(locationHelperProperties);
059                    this.globalPropertiesMode = resolve(globalPropertiesMode, global);
060                    this.missingLocationsMode = resolve(missingLocationsMode, global);
061                    logger.info("Global properties mode - " + globalPropertiesMode);
062                    logger.info("Missing locations mode - " + missingLocationsMode);
063                    this.encoding = resolve(encoding, global);
064                    this.organizationGroupId = resolve(organizationGroupId, global);
065                    validateGlobalPropertiesMode(globalPropertiesMode);
066                    GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
067                    this.locationHelperProperties = getLocationHelperProperties(locationHelperProperties, gpm);
068                    logger.info("Property file encoding - " + encoding);
069                    logger.info("Using " + locationHelperProperties.size() + " properties to assist with property loading.");
070                    validate();
071                    if (logger.isDebugEnabled()) {
072                            PropertyUtils.debug(locationHelperProperties);
073                    }
074                    Properties p = new Properties();
075                    p.putAll(PropertyUtils.toEmpty(properties));
076                    p.putAll(PropertyUtils.toEmpty(locationHelperProperties));
077                    return p;
078            }
079    
080            protected void validateGlobalPropertiesMode(String globalPropertiesMode) {
081                    validateResolved(globalPropertiesMode);
082                    GlobalPropertiesMode.valueOf(globalPropertiesMode);
083            }
084    
085            @Override
086            protected void validate() {
087                    validateGlobalPropertiesMode(globalPropertiesMode);
088                    validateResolved(encoding);
089                    validateResolved(missingLocationsMode);
090                    Mode.valueOf(missingLocationsMode);
091            }
092    
093            @Override
094            public String getLocation(String location, Properties properties) {
095                    String resolvedLocation = getResolvedLocation(location, properties);
096                    return getValidatedLocation(resolvedLocation, Mode.valueOf(missingLocationsMode));
097            }
098    
099            protected String getValidatedLocation(String location, Mode missingLocationsMode) {
100                    validateResolved(location);
101                    if (LocationUtils.exists(location)) {
102                            return location;
103                    } else {
104                            ModeUtils.validate(missingLocationsMode, "Skipping non-existent location - [{}]", location, "Could not locate [" + location + "]");
105                            return null;
106                    }
107            }
108    
109            protected void validateResolved(String string) {
110                    if (PropertyUtils.containsUnresolvedPlaceholder(string)) {
111                            throw new IllegalArgumentException("Unable to resolve [" + string + "]");
112                    }
113            }
114    
115            protected String getResolvedLocation(String location, Properties properties) {
116                    boolean resolve = PropertyUtils.containsUnresolvedPlaceholder(location);
117                    if (resolve) {
118                            GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
119                            Properties duplicate = PropertyUtils.getProperties(properties, gpm);
120                            List<PropertyProcessor> processors = getLocationProcessors();
121                            for (PropertyProcessor processor : processors) {
122                                    processor.process(duplicate);
123                            }
124                            return helper.replacePlaceholders(location, duplicate);
125                    } else {
126                            return location;
127                    }
128            }
129    
130            protected Properties getGlobalProperties(Properties properties) {
131                    return PropertyUtils.getGlobalProperties(PropertyUtils.toEmpty(properties));
132            }
133    
134            protected Properties getLocationHelperProperties(Properties properties, GlobalPropertiesMode mode) {
135                    Properties locationHelperProperties = PropertyUtils.duplicate(PropertyUtils.toEmpty(properties));
136                    List<PropertyProcessor> processors = getLocationHelperProcessors();
137                    for (PropertyProcessor processor : processors) {
138                            processor.process(locationHelperProperties);
139                    }
140                    return locationHelperProperties;
141            }
142    
143            protected List<PropertyProcessor> getLocationProcessors() {
144                    GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
145                    List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>();
146                    processors.add(new GlobalOverrideProcessor(gpm));
147                    processors.add(new ResolvePlaceholdersProcessor(helper, gpm));
148                    return processors;
149            }
150    
151            protected String getGroupId() {
152                    if (groupIdProperty == null) {
153                            return null;
154                    } else if (locationHelperProperties == null) {
155                            return null;
156                    } else {
157                            return locationHelperProperties.getProperty(groupIdProperty);
158                    }
159            }
160    
161            protected List<PropertyProcessor> getLocationHelperProcessors() {
162                    List<PropertyProcessor> processors = new ArrayList<PropertyProcessor>();
163    
164                    this.locationHelperIncludes = CollectionUtils.sortedMerge(locationHelperIncludes, locationHelperInclude);
165                    this.locationHelperExcludes = CollectionUtils.sortedMerge(locationHelperExcludes, locationHelperExclude);
166                    processors.add(new TrimProcessor(locationHelperIncludes, locationHelperExcludes));
167    
168                    String groupId = getGroupId();
169                    if (organizationGroupId != null && groupId != null) {
170                            processors.add(new OrgProcessor(organizationGroupId, groupId));
171                            processors.add(new HomeProcessor(organizationGroupId, groupId));
172                    }
173    
174                    if (groupIdProperty != null) {
175                            processors.add(new PathProcessor(groupIdProperty));
176                    }
177    
178                    if (versionProperty != null) {
179                            processors.add(new VersionProcessor(versionProperty));
180                    }
181    
182                    GlobalPropertiesMode gpm = GlobalPropertiesMode.valueOf(globalPropertiesMode);
183                    processors.add(new GlobalOverrideProcessor(gpm));
184                    processors.add(new ResolvePlaceholdersProcessor(helper, gpm));
185    
186                    return processors;
187            }
188    
189            public String getMissingLocationsMode() {
190                    return missingLocationsMode;
191            }
192    
193            public void setMissingLocationsMode(String missingLocationsMode) {
194                    this.missingLocationsMode = missingLocationsMode;
195            }
196    
197            @Override
198            public List<String> getLocations() {
199                    return locations;
200            }
201    
202            public void setLocations(List<String> locations) {
203                    this.locations = locations;
204            }
205    
206            public Properties getLocationHelperProperties() {
207                    return locationHelperProperties;
208            }
209    
210            public void setLocationHelperProperties(Properties locationHelperProperties) {
211                    this.locationHelperProperties = locationHelperProperties;
212            }
213    
214            @Override
215            public String getEncoding() {
216                    return encoding;
217            }
218    
219            public void setEncoding(String encoding) {
220                    this.encoding = encoding;
221            }
222    
223            public String getOrganizationGroupId() {
224                    return organizationGroupId;
225            }
226    
227            public void setOrganizationGroupId(String organizationGroupId) {
228                    this.organizationGroupId = organizationGroupId;
229            }
230    
231            public String getGroupIdProperty() {
232                    return groupIdProperty;
233            }
234    
235            public void setGroupIdProperty(String groupIdProperty) {
236                    this.groupIdProperty = groupIdProperty;
237            }
238    
239            public String getVersionProperty() {
240                    return versionProperty;
241            }
242    
243            public void setVersionProperty(String versionProperty) {
244                    this.versionProperty = versionProperty;
245            }
246    
247            public List<String> getLocationHelperIncludes() {
248                    return locationHelperIncludes;
249            }
250    
251            public void setLocationHelperIncludes(List<String> locationHelperIncludes) {
252                    this.locationHelperIncludes = locationHelperIncludes;
253            }
254    
255            public List<String> getLocationHelperExcludes() {
256                    return locationHelperExcludes;
257            }
258    
259            public void setLocationHelperExcludes(List<String> locationHelperExcludes) {
260                    this.locationHelperExcludes = locationHelperExcludes;
261            }
262    
263            public String getLocationHelperInclude() {
264                    return locationHelperInclude;
265            }
266    
267            public void setLocationHelperInclude(String locationHelperInclude) {
268                    this.locationHelperInclude = locationHelperInclude;
269            }
270    
271            public String getLocationHelperExclude() {
272                    return locationHelperExclude;
273            }
274    
275            public void setLocationHelperExclude(String locationHelperExclude) {
276                    this.locationHelperExclude = locationHelperExclude;
277            }
278    
279    }