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.execution;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.IOException;
21  import java.nio.ByteBuffer;
22  import java.nio.CharBuffer;
23  import java.nio.channels.FileChannel;
24  import java.nio.charset.Charset;
25  import java.nio.charset.CharsetDecoder;
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.StringTokenizer;
31  import java.util.regex.Matcher;
32  import java.util.regex.Pattern;
33  
34  import org.apache.commons.io.IOUtils;
35  import org.argeo.slc.SlcException;
36  import org.springframework.beans.factory.FactoryBean;
37  import org.springframework.beans.factory.InitializingBean;
38  import org.springframework.core.io.ByteArrayResource;
39  import org.springframework.core.io.Resource;
40  
41  /** Experimental and suboptimal */
42  public class SedFilteredResource implements FactoryBean<Resource>,
43  		InitializingBean {
44  	private Resource source;
45  
46  	private List<String> filters = new ArrayList<String>();
47  	private Map<Pattern, String> patterns = new HashMap<Pattern, String>();
48  
49  	private String charset = "UTF-8";
50  	private Charset cs;
51  	private CharsetDecoder decoder;
52  
53  	// private CharsetEncoder encoder;
54  
55  	public Resource getObject() throws Exception {
56  		if (filters.size() == 0)
57  			return source;
58  
59  		// int capacity = 100 * 1024;// 100 KB
60  		ByteBuffer bb;
61  		if (source instanceof ByteArrayResource) {
62  			bb = ByteBuffer.wrap(((ByteArrayResource) source).getByteArray());
63  		} else {
64  			FileInputStream fis = null;
65  			try {
66  				File file = source.getFile();
67  				fis = new FileInputStream(file);
68  				FileChannel fc = fis.getChannel();
69  
70  				// Get the file's size and then map it into memory
71  				int sz = (int) fc.size();
72  				bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
73  			} catch (IOException e) {
74  				// ReadableByteChannel channel = Channels.newChannel(source
75  				// .getInputStream());
76  				// bb = ByteBuffer.allocateDirect(capacity);
77  				// int read = 0;
78  				// do {
79  				// read = channel.read(bb);
80  				// } while (read > 0);
81  				// FIXME : use nio to parse the stream as it goes
82  				bb = ByteBuffer.wrap(IOUtils.toByteArray(source
83  						.getInputStream()));
84  			} finally {
85  				IOUtils.closeQuietly(fis);
86  			}
87  		}
88  		CharBuffer cb = decoder.decode(bb);
89  		for (Pattern pattern : patterns.keySet()) {
90  			Matcher matcher = pattern.matcher(cb);
91  			String output = matcher.replaceAll(patterns.get(pattern));
92  			cb = CharBuffer.wrap(output);
93  		}
94  		// ByteBuffer bbout = encoder.encode(cb);
95  		// ByteArrayOutputStream out = new ByteArrayOutputStream(capacity);
96  		// WritableByteChannel wchannel = Channels.newChannel(out);
97  		// wchannel.write(bbout);
98  		ByteArrayResource res = new ByteArrayResource(cb.toString().getBytes());
99  		return res;
100 	}
101 
102 	public Class<?> getObjectType() {
103 		return Resource.class;
104 	}
105 
106 	public boolean isSingleton() {
107 		return true;
108 	}
109 
110 	public void afterPropertiesSet() throws Exception {
111 		cs = Charset.forName(charset);
112 		decoder = cs.newDecoder();
113 		// encoder = cs.newEncoder();
114 
115 		for (String sedStr : filters) {
116 			sedStr = sedStr.trim();
117 			if (sedStr.length() < 4)
118 				throw new SlcException(sedStr + " not properly formatted.");
119 			if (sedStr.charAt(0) != 's')
120 				throw new SlcException(sedStr + " not properly formatted.");
121 			Character sep = sedStr.charAt(1);
122 			List<String> tokens = new ArrayList<String>(4);
123 			StringTokenizer st = new StringTokenizer(sedStr, sep.toString());
124 			while (st.hasMoreTokens())
125 				tokens.add(st.nextToken());
126 			if (tokens.size() != 3 && tokens.size() != 4)
127 				throw new SlcException(sedStr + " not properly formatted.");
128 			patterns.put(Pattern.compile(tokens.get(1)), tokens.get(2));
129 		}
130 	}
131 
132 	public void setSource(Resource source) {
133 		this.source = source;
134 	}
135 
136 	public void setFilters(List<String> filters) {
137 		this.filters = filters;
138 	}
139 
140 	public void setCharset(String charset) {
141 		this.charset = charset;
142 	}
143 
144 }