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