001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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:
017: package org.springframework.core.io.support;
018:
019: import java.beans.PropertyEditorSupport;
020: import java.io.IOException;
021: import java.util.ArrayList;
022: import java.util.Arrays;
023: import java.util.Collection;
024: import java.util.Iterator;
025: import java.util.List;
026:
027: import org.springframework.core.io.Resource;
028: import org.springframework.util.SystemPropertyUtils;
029:
030: /**
031: * Editor for {@link org.springframework.core.io.Resource} arrays, to
032: * automatically convert <code>String</code> location patterns
033: * (e.g. <code>"file:C:/my*.txt"</code> or <code>"classpath*:myfile.txt"</code>)
034: * to <code>Resource</code> array properties. Can also translate a collection
035: * or array of location patterns into a merged Resource array.
036: *
037: * <p>The path may contain <code>${...}</code> placeholders, to be resolved
038: * as system properties: e.g. <code>${user.dir}</code>.
039: *
040: * <p>Delegates to a {@link ResourcePatternResolver},
041: * by default using a {@link PathMatchingResourcePatternResolver}.
042: *
043: * @author Juergen Hoeller
044: * @since 1.1.2
045: * @see org.springframework.core.io.Resource
046: * @see ResourcePatternResolver
047: * @see PathMatchingResourcePatternResolver
048: * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
049: * @see System#getProperty(String)
050: */
051: public class ResourceArrayPropertyEditor extends PropertyEditorSupport {
052:
053: private final ResourcePatternResolver resourcePatternResolver;
054:
055: /**
056: * Create a new ResourceArrayPropertyEditor with a default
057: * PathMatchingResourcePatternResolver.
058: * @see PathMatchingResourcePatternResolver
059: */
060: public ResourceArrayPropertyEditor() {
061: this .resourcePatternResolver = new PathMatchingResourcePatternResolver();
062: }
063:
064: /**
065: * Create a new ResourceArrayPropertyEditor with the given ResourcePatternResolver.
066: * @param resourcePatternResolver the ResourcePatternResolver to use
067: */
068: public ResourceArrayPropertyEditor(
069: ResourcePatternResolver resourcePatternResolver) {
070: this .resourcePatternResolver = resourcePatternResolver;
071: }
072:
073: /**
074: * Treat the given text as location pattern and convert it to a Resource array.
075: */
076: public void setAsText(String text) {
077: String pattern = resolvePath(text).trim();
078: try {
079: setValue(this .resourcePatternResolver.getResources(pattern));
080: } catch (IOException ex) {
081: throw new IllegalArgumentException(
082: "Could not resolve resource location pattern ["
083: + pattern + "]: " + ex.getMessage());
084: }
085: }
086:
087: /**
088: * Treat the given value as collection or array and convert it to a Resource array.
089: * Considers String elements as location patterns, and takes Resource elements as-is.
090: */
091: public void setValue(Object value) throws IllegalArgumentException {
092: if (value instanceof Collection
093: || (value instanceof Object[] && !(value instanceof Resource[]))) {
094: Collection input = (value instanceof Collection ? (Collection) value
095: : Arrays.asList((Object[]) value));
096: List merged = new ArrayList();
097: for (Iterator it = input.iterator(); it.hasNext();) {
098: Object element = it.next();
099: if (element instanceof String) {
100: // A location pattern: resolve it into a Resource array.
101: // Might point to a single resource or to multiple resources.
102: String pattern = resolvePath((String) element)
103: .trim();
104: try {
105: Resource[] resources = this .resourcePatternResolver
106: .getResources(pattern);
107: for (int i = 0; i < resources.length; i++) {
108: Resource resource = resources[i];
109: if (!merged.contains(resource)) {
110: merged.add(resource);
111: }
112: }
113: } catch (IOException ex) {
114: throw new IllegalArgumentException(
115: "Could not resolve resource location pattern ["
116: + pattern + "]: "
117: + ex.getMessage());
118: }
119: } else if (element instanceof Resource) {
120: // A Resource object: add it to the result.
121: if (!merged.contains(element)) {
122: merged.add(element);
123: }
124: } else {
125: throw new IllegalArgumentException(
126: "Cannot convert element ["
127: + element
128: + "] to ["
129: + Resource.class.getName()
130: + "]: only location String and Resource object supported");
131: }
132: }
133: super .setValue(merged.toArray(new Resource[merged.size()]));
134: }
135:
136: else {
137: // An arbitrary value: probably a String or a Resource array.
138: // setAsText will be called for a String; a Resource array will be used as-is.
139: super .setValue(value);
140: }
141: }
142:
143: /**
144: * Resolve the given path, replacing placeholders with
145: * corresponding system property values if necessary.
146: * @param path the original file path
147: * @return the resolved file path
148: * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders
149: */
150: protected String resolvePath(String path) {
151: return SystemPropertyUtils.resolvePlaceholders(path);
152: }
153:
154: }
|