View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.slc.core.deploy;
17  
18  import java.io.IOException;
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.StringTokenizer;
23  import java.util.TreeMap;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.argeo.slc.SlcException;
28  import org.springframework.beans.factory.InitializingBean;
29  import org.springframework.context.ResourceLoaderAware;
30  import org.springframework.core.io.Resource;
31  import org.springframework.core.io.ResourceLoader;
32  import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
33  import org.springframework.core.io.support.ResourcePatternResolver;
34  import org.springframework.util.AntPathMatcher;
35  import org.springframework.util.PathMatcher;
36  
37  public class DefaultResourceSet implements ResourceLoaderAware,
38  		InitializingBean, ResourceSet {
39  	private final static Log log = LogFactory.getLog(DefaultResourceSet.class);
40  	public final static String DEFAULT_EXCLUDES = "**/.svn/**";
41  
42  	private String base;
43  	private String include;
44  	private List<String> includes = new ArrayList<String>();
45  	private String exclude;
46  	private List<String> excludes = new ArrayList<String>();
47  	private Boolean useDefaultExcludes = true;
48  	private ResourcePatternResolver resourcePatternResolver;
49  	private PathMatcher excludePathMatcher = new AntPathMatcher();
50  
51  	private ResourceLoader resourceLoader;
52  
53  	/** List the resources, identified by their relative path. */
54  	public Map<String, Resource> listResources() {
55  		try {
56  			Map<String, Resource> res = new TreeMap<String, Resource>();
57  			if (base == null)
58  				return res;
59  			String baseResUrl = getResourceLoaderToUse().getResource(base)
60  					.getURL().toString();
61  			for (String includePattern : includes)
62  				processInclude(res, includePattern, baseResUrl);
63  			return res;
64  		} catch (IOException e) {
65  			throw new SlcException("Cannot list resource from " + base, e);
66  		}
67  	}
68  
69  	protected void processInclude(Map<String, Resource> res, String include,
70  			String baseResUrl) throws IOException {
71  		String pattern = base + "/" + include;
72  		if (log.isTraceEnabled())
73  			log.trace("Look for resources with pattern '" + pattern
74  					+ "' in base url " + baseResUrl);
75  		Resource[] resources = resourcePatternResolver.getResources(pattern);
76  		resources: for (Resource resource : resources) {
77  			String url = resource.getURL().toString();
78  			String relPath = url.substring(baseResUrl.length());
79  
80  			// skip dir
81  			if (relPath.charAt(relPath.length() - 1) == '/') {
82  				if (log.isTraceEnabled())
83  					log.trace("Skip directory " + relPath + "=" + resource);
84  				continue resources;
85  			}
86  
87  			// make sure there is not starting '/'
88  			if (relPath.charAt(0) == '/')
89  				relPath = relPath.substring(1);
90  
91  			// skip excludes
92  			for (String exclude : excludes)
93  				if (excludePathMatcher.match(exclude, relPath)) {
94  					if (log.isTraceEnabled())
95  						log.trace("Exclude " + relPath + "=" + resource);
96  					continue resources;
97  				}
98  
99  			// check if already exists
100 			if (res.containsKey(relPath))
101 				log.warn(relPath + " already matched by " + res.get(relPath)
102 						+ ", " + resource + " will override it.");
103 
104 			// store the marched resource
105 			res.put(relPath, resource);
106 			if (log.isTraceEnabled())
107 				log.trace(relPath + "=" + resource);
108 		}
109 
110 	}
111 
112 	public void afterPropertiesSet() throws Exception {
113 		if (resourcePatternResolver == null)
114 			resourcePatternResolver = new PathMatchingResourcePatternResolver(
115 					getResourceLoaderToUse());
116 		if (include != null)
117 			addCommaSeparatedToList(include, includes);
118 		if (exclude != null)
119 			addCommaSeparatedToList(exclude, excludes);
120 
121 		if (includes.size() == 0)
122 			includes.add("**");
123 
124 		if (useDefaultExcludes)
125 			addCommaSeparatedToList(DEFAULT_EXCLUDES, excludes);
126 	}
127 
128 	private void addCommaSeparatedToList(String str, List<String> lst) {
129 		StringTokenizer st = new StringTokenizer(str, ",");
130 		while (st.hasMoreTokens()) {
131 			String token = st.nextToken();
132 			if (!lst.contains(token))
133 				lst.add(token);
134 		}
135 	}
136 
137 	public void setResourceLoader(ResourceLoader resourceLoader) {
138 		this.resourceLoader = resourceLoader;
139 	}
140 
141 	/**
142 	 * Can be overridden in order to provide the proper resource loader used to
143 	 * resolve resources.
144 	 */
145 	public ResourceLoader getResourceLoaderToUse() {
146 		return resourceLoader;
147 	}
148 
149 	public void setBase(String base) {
150 		this.base = base;
151 	}
152 
153 	public void setInclude(String include) {
154 		this.include = include;
155 	}
156 
157 	public void setIncludes(List<String> includes) {
158 		this.includes = includes;
159 	}
160 
161 	public void setExclude(String exclude) {
162 		this.exclude = exclude;
163 	}
164 
165 	public void setExcludes(List<String> excludes) {
166 		this.excludes = excludes;
167 	}
168 
169 	public void setUseDefaultExcludes(Boolean useDefaultExcludes) {
170 		this.useDefaultExcludes = useDefaultExcludes;
171 	}
172 
173 	public void setExcludePathMatcher(PathMatcher excludePathMatcher) {
174 		this.excludePathMatcher = excludePathMatcher;
175 	}
176 
177 	public void setResourcePatternResolver(
178 			ResourcePatternResolver resourcePatternResolver) {
179 		this.resourcePatternResolver = resourcePatternResolver;
180 	}
181 
182 	public ResourcePatternResolver getResourcePatternResolver() {
183 		return resourcePatternResolver;
184 	}
185 
186 }