001 package org.apache.fulcrum.parser;
002
003
004 /*
005 * Licensed to the Apache Software Foundation (ASF) under one
006 * or more contributor license agreements. See the NOTICE file
007 * distributed with this work for additional information
008 * regarding copyright ownership. The ASF licenses this file
009 * to you under the Apache License, Version 2.0 (the
010 * "License"); you may not use this file except in compliance
011 * with the License. You may obtain a copy of the License at
012 *
013 * http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing,
016 * software distributed under the License is distributed on an
017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018 * KIND, either express or implied. See the License for the
019 * specific language governing permissions and limitations
020 * under the License.
021 */
022
023
024 import java.util.List;
025
026 import javax.servlet.http.HttpServletRequest;
027
028 import org.apache.avalon.framework.configuration.Configurable;
029 import org.apache.avalon.framework.configuration.Configuration;
030 import org.apache.avalon.framework.configuration.ConfigurationException;
031 import org.apache.avalon.framework.logger.AbstractLogEnabled;
032 import org.apache.avalon.framework.logger.LogEnabled;
033 import org.apache.avalon.framework.service.ServiceException;
034 import org.apache.avalon.framework.service.ServiceManager;
035 import org.apache.avalon.framework.service.Serviceable;
036 import org.apache.commons.lang.StringUtils;
037 import org.apache.fulcrum.pool.PoolException;
038 import org.apache.fulcrum.pool.PoolService;
039 import org.apache.fulcrum.upload.UploadService;
040
041
042 /**
043 * The DefaultParserService provides the efault implementation
044 * of a {@link ParserService}.
045 *
046 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
047 * @version $Id: BaseValueParser.java 542062 2007-05-28 00:29:43Z seade $
048 */
049 public class DefaultParserService
050 extends AbstractLogEnabled
051 implements ParserService,
052 Configurable, Serviceable
053 {
054 /** The folding from the configuration */
055 private int folding = URL_CASE_FOLDING_NONE;
056
057 /** The automaticUpload setting from the configuration */
058 private boolean automaticUpload = AUTOMATIC_DEFAULT;
059
060 /**
061 * The parameter encoding to use when parsing parameter strings
062 */
063 private String parameterEncoding = PARAMETER_ENCODING_DEFAULT;
064
065 /**
066 * The upload service component to use
067 */
068 private UploadService uploadService = null;
069
070 /**
071 * The pool service component to use
072 */
073 private PoolService poolService = null;
074
075 /**
076 * Get the character encoding that will be used by this ValueParser.
077 */
078 public String getParameterEncoding()
079 {
080 return parameterEncoding;
081 }
082
083 /**
084 * Trims the string data and applies the conversion specified in
085 * the property given by URL_CASE_FOLDING. It returns a new
086 * string so that it does not destroy the value data.
087 *
088 * @param value A String to be processed.
089 * @return A new String converted to lowercase and trimmed.
090 */
091 public String convert(String value)
092 {
093 return convertAndTrim(value);
094 }
095
096 /**
097 * Convert a String value according to the url-case-folding property.
098 *
099 * @param value the String to convert
100 *
101 * @return a new String.
102 *
103 */
104 public String convertAndTrim(String value)
105 {
106 return convertAndTrim(value, getUrlFolding());
107 }
108
109 /**
110 * A static version of the convert method, which
111 * trims the string data and applies the conversion specified in
112 * the property given by URL_CASE_FOLDING. It returns a new
113 * string so that it does not destroy the value data.
114 *
115 * @param value A String to be processed.
116 * @return A new String converted to lowercase and trimmed.
117 */
118 public String convertAndTrim(String value, int fold)
119 {
120 if(value == null) return "";
121
122 String tmp = value.trim();
123
124 switch (fold)
125 {
126 case URL_CASE_FOLDING_NONE:
127 {
128 break;
129 }
130
131 case URL_CASE_FOLDING_LOWER:
132 {
133 tmp = tmp.toLowerCase();
134 break;
135 }
136
137 case URL_CASE_FOLDING_UPPER:
138 {
139 tmp = tmp.toUpperCase();
140 break;
141 }
142
143 default:
144 {
145 getLogger().error("Passed " + fold + " as fold rule, which is illegal!");
146 break;
147 }
148 }
149 return tmp;
150 }
151
152 /**
153 * Gets the folding value from the configuration
154 *
155 * @return The current Folding Value
156 */
157 public int getUrlFolding()
158 {
159 return folding;
160 }
161
162 /**
163 * Gets the automaticUpload value from the configuration
164 *
165 * @return The current automaticUpload Value
166 */
167 public boolean getAutomaticUpload()
168 {
169 return automaticUpload;
170 }
171
172 /**
173 * Use the UploadService if available to parse the given request
174 * for uploaded files
175 *
176 * @return A list of {@link org.apache.commons.upload.FileItem}s
177 *
178 * @throws ServiceException if parsing fails or the UploadService
179 * is not available
180 */
181 public List parseUpload(HttpServletRequest request) throws ServiceException
182 {
183 if (uploadService == null)
184 {
185 throw new ServiceException(ParserService.ROLE, "UploadService is not available.");
186 }
187 else
188 {
189 return uploadService.parseRequest(request);
190 }
191 }
192
193 /**
194 * Get a {@link ValueParser} instance from the service. Use the
195 * given Class to create the object.
196 *
197 * @return An object that implements ValueParser
198 *
199 * @throws InstantiationException if the instance could not be created
200 */
201 public ValueParser getParser(Class ppClass) throws InstantiationException
202 {
203 ValueParser vp = null;
204
205 try
206 {
207 vp = (ValueParser) poolService.getInstance(ppClass);
208
209 if (vp instanceof ParserServiceSupport)
210 {
211 ((ParserServiceSupport)vp).setParserService(this);
212 }
213
214 if (vp instanceof LogEnabled)
215 {
216 ((LogEnabled)vp).enableLogging(getLogger().getChildLogger(ppClass.getName()));
217 }
218
219 }
220 catch (PoolException pe)
221 {
222 throw new InstantiationException("Parser class '" + ppClass + "' is illegal. " + pe.getMessage());
223 }
224 catch (ClassCastException x)
225 {
226 throw new InstantiationException("Parser class '" + ppClass + "' is illegal. " + x.getMessage());
227 }
228
229 return vp;
230 }
231
232 /**
233 * Return a used Parser to the service. This allows for
234 * pooling and recycling
235 *
236 * @param parser
237 */
238 public void putParser(ValueParser parser)
239 {
240 parser.clear();
241 poolService.putInstance(parser);
242 }
243
244 /**
245 * Avalon component lifecycle method
246 */
247 public void configure(Configuration conf) throws ConfigurationException
248 {
249 if (folding == URL_CASE_FOLDING_UNSET)
250 {
251 String foldString = conf.getChild(URL_CASE_FOLDING_KEY).getValue(URL_CASE_FOLDING_NONE_VALUE).toLowerCase();
252
253 folding = URL_CASE_FOLDING_NONE;
254
255 getLogger().debug("Setting folding from " + foldString);
256
257 if (StringUtils.isNotEmpty(foldString))
258 {
259 if (foldString.equals(URL_CASE_FOLDING_NONE_VALUE))
260 {
261 folding = URL_CASE_FOLDING_NONE;
262 }
263 else if (foldString.equals(URL_CASE_FOLDING_LOWER_VALUE))
264 {
265 folding = URL_CASE_FOLDING_LOWER;
266 }
267 else if (foldString.equals(URL_CASE_FOLDING_UPPER_VALUE))
268 {
269 folding = URL_CASE_FOLDING_UPPER;
270 }
271 else
272 {
273 getLogger().error("Got " + foldString + " from " + URL_CASE_FOLDING_KEY + " property, which is illegal!");
274 throw new ConfigurationException("Value " + foldString + " is illegal!");
275 }
276 }
277 }
278
279 parameterEncoding = conf.getChild(PARAMETER_ENCODING_KEY)
280 .getValue(PARAMETER_ENCODING_DEFAULT).toLowerCase();
281
282 automaticUpload = conf.getAttributeAsBoolean(
283 AUTOMATIC_KEY,
284 AUTOMATIC_DEFAULT);
285 }
286
287 // ---------------- Avalon Lifecycle Methods ---------------------
288 /**
289 * Avalon component lifecycle method
290 */
291 public void service(ServiceManager manager) throws ServiceException
292 {
293 if (manager.hasService(UploadService.ROLE))
294 {
295 uploadService = (UploadService)manager.lookup(UploadService.ROLE);
296 }
297 else
298 {
299 /*
300 * Automatic parsing of uploaded file items was requested but no
301 * UploadService is available
302 */
303 if (getAutomaticUpload())
304 {
305 throw new ServiceException(ParserService.ROLE,
306 AUTOMATIC_KEY + " = true requires " +
307 UploadService.ROLE + " to be available");
308 }
309 }
310
311 if (manager.hasService(PoolService.ROLE))
312 {
313 poolService = (PoolService)manager.lookup(PoolService.ROLE);
314 }
315 else
316 {
317 throw new ServiceException(ParserService.ROLE,
318 "Service requires " +
319 PoolService.ROLE + " to be available");
320 }
321 }
322 }