001: /*
002: * Coefficient - facilitates project based collaboration
003: * Copyright (C) 2003, Dylan Etkin, CSIR icomtek
004: * PO Box 395
005: * Pretoria 0001, RSA
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package za.org.coefficient.core;
021:
022: import java.beans.IndexedPropertyDescriptor;
023: import java.beans.PropertyDescriptor;
024: import java.io.IOException;
025: import java.lang.reflect.Method;
026:
027: import java.util.ArrayList;
028: import java.util.Date;
029: import java.util.HashMap;
030: import java.util.Iterator;
031: import java.util.Map;
032:
033: import java.beans.Introspector;
034: import java.beans.PropertyDescriptor;
035:
036: import org.apache.commons.fileupload.FileUploadException;
037: import org.apache.commons.httpclient.Cookie;
038:
039: import za.org.coefficient.authentication.CoefficientUser;
040: import za.org.coefficient.exception.ConfigurationException;
041: import za.org.coefficient.html.Page;
042: import za.org.coefficient.interfaces.CoefficientContext;
043: import za.org.coefficient.util.common.BaseMultipartRequest;
044: import za.org.coefficient.util.common.MultipartRequest;
045: import za.org.coefficient.util.common.UploadedFile;
046:
047: /**
048: * <p>Project: coefficient</p>
049: * <p>Description: </p>
050: * <p>Copyright: Copyright (c) 2003</p>
051: * <p>Company: CSIR</p>
052: * @author tfogwill
053: */
054: public abstract class BaseCoefficientContext implements
055: CoefficientContext {
056:
057: public static final String CURRENT_PROJECT = "__current_project__";
058:
059: public static final String LAST_NON_HELP_OP = "__last_non_help_op";
060: protected static final String URL_PREFIX = "index.html?module=";
061:
062: /** The page to handle this request */
063: protected Page page_;
064: /** URL to redirect to if set */
065: protected String redirectionURL = null;
066: protected String domain = null;
067: protected String requestURL = null;
068: protected boolean inWorkflowAction = false;
069: protected boolean invalidateSession = false;
070: private CoefficientUser tempUser = null;
071: private CoefficientUser workflowUser = null;
072:
073: protected MultipartRequest multipartRequest;
074: protected Map session = new HashMap();
075: protected Map requestData = new HashMap();
076: protected Map requestAttributes = new HashMap();
077: protected Map fileUploadData = new HashMap();
078: protected Cookie[] serializableExistingCookies;
079: protected ArrayList serializableNewCookies = new ArrayList();
080: protected ArrayList removedSessionKeys = new ArrayList();
081:
082: /**
083: * Passthru method to set the error content on the internal Page object
084: *
085: * @param html a String containing the html content defining an error
086: * display
087: */
088: public void setError(String html) {
089: getPage().setError(html);
090: }
091:
092: public boolean isError() {
093: return getPage().getErrors().trim().length() > 0;
094: }
095:
096: public Page getPage() {
097: if (this .page_ == null) {
098: try {
099: createPageObject();
100: } catch (Exception e) {
101: e.printStackTrace();
102: throw new RuntimeException(
103: "Could not create Page object.", e);
104: }
105: }
106: return page_;
107: }
108:
109: public String getTheme() {
110: String theme = (String) getSessionAttribute(Constants.CURRENT_THEME_STRING);
111: return theme;
112: }
113:
114: public void setTheme(String theme) {
115: setSessionAttribute(Constants.CURRENT_THEME_STRING, theme);
116: }
117:
118: /**
119: * This will forward to the module and perform its main method
120: */
121: public void setForward(String moduleName)
122: throws ConfigurationException {
123: this .setForward(moduleName, null, null);
124: }
125:
126: /**
127: * This will forward to the module and perform the method specified by
128: * op and will pass no other parameters
129: */
130: public void setForward(String moduleName, String opName)
131: throws ConfigurationException {
132: this .setForward(moduleName, opName, null);
133: }
134:
135: /**
136: * This method is used to force a redirect after the current iteration
137: * of the interceptor chain has completed.
138: *
139: * @param moduleName is the module to forward control to, this must not
140: * be null
141: * @param opName is the operation that the forwarded module should perform
142: * if this value is null then it will use the MainMethod
143: * @param params is a hashmap containing key-value pairs that will be
144: * additional parameters included on the request line to the
145: * specified module. If null no additional parameters will
146: * be sent
147: *
148: * @exception configuationException is thrown if module name is empty
149: * or null
150: */
151: public void setForward(String moduleName, String opName,
152: HashMap params) throws ConfigurationException {
153: if ((moduleName == null) || (moduleName.trim().length() == 0)) {
154: throw new ConfigurationException(
155: "You can not forward without providing a module name");
156: }
157: StringBuffer sb = new StringBuffer(URL_PREFIX);
158: sb.append(moduleName);
159: if ((opName != null) && (opName.trim().length() != 0)) {
160: sb.append("&op=").append(opName);
161: }
162: if ((params != null) && (params.size() != 0)) {
163: for (Iterator it = params.keySet().iterator(); it.hasNext();) {
164: Object key = it.next();
165: Object val = params.get(key);
166: sb.append("&").append(key).append("=").append(val);
167: }
168: }
169: redirectionURL = sb.toString();
170: }
171:
172: /**
173: * Passthru method to set the module content on the internal Page object
174: *
175: * @param html a String containing the html content the module wants to
176: * display
177: * @param name is the result of the call to getModuleName on the module
178: * setting the content
179: */
180: public void setModuleContent(String html, String name)
181: throws RuntimeException {
182: try {
183: getPage().setModuleContent(html, name);
184: } catch (Exception e) {
185: throw new RuntimeException();
186: }
187: }
188:
189: /**
190: * force a specific theme - used primarily for printing
191: */
192: public void setModuleContent(String html, String name, String theme)
193: throws RuntimeException {
194: try {
195: getPage().setModuleContent(html, name, theme);
196: } catch (Exception e) {
197: throw new RuntimeException();
198: }
199: }
200:
201: public String clearModuleContent(String name) {
202: return getPage().clearModuleContent(name);
203: }
204:
205: public void setCookie(Cookie cookie) {
206: serializableNewCookies.add(cookie);
207: }
208:
209: public Cookie[] getCookies() {
210: return serializableExistingCookies;
211: }
212:
213: public BaseMultipartRequest getMultipartRequest()
214: throws FileUploadException {
215: if (this .multipartRequest == null) {
216: throw new RuntimeException(
217: "The current request doesn't contain a multipart/form-data or multipart/mixed stream");
218: }
219: return this .multipartRequest;
220: }
221:
222: /**
223: * Passthru method to the request object.
224: *
225: * @param name a String containing the paramameter name.
226: * @return a String containing the parameter value.
227: *
228: *
229: * @see #getParameter(String,String) The getParameter() with a default value.
230: *
231: */
232: public String getParameter(String name) {
233:
234: String value_str = null;
235: Object value = requestData.get(name);
236: if (value != null) {
237: if (value instanceof String[]) {
238: value_str = ((String[]) value)[0];
239: } else {
240: value_str = value.toString();
241: }
242: }
243: if ((value_str == null) || value_str.trim().equals("")) {
244: value = getRequestAttribute(name);
245: if (value != null) {
246: if (value instanceof String[]) {
247: value_str = ((String[]) value)[0];
248: } else {
249: value_str = value.toString();
250: }
251: }
252: }
253: return value_str;
254: }
255:
256: /**
257: * Passthru method to the request object. If request
258: * is null, return an empty array of String.
259: *
260: * @param name a String containing the parameter name.
261: * @return an array of Strings with all values associated
262: *
263: */
264: public String[] getParameterValues(String name) {
265: return getParametersValues(name);
266: }
267:
268: public String[] getParametersValues(String name) {
269: Object value = requestData.get(name);
270: if (value != null) {
271: if (value instanceof String[]) {
272: return (String[]) value;
273: } else {
274: return new String[] { value.toString() };
275: }
276: } else {
277: return new String[0];
278: }
279: }
280:
281: /**
282: * Uses bean introspection to set writable properties of bean from the
283: * parameters, where a (case-insensitive) name match between the bean
284: * property and the parameter is looked for
285: *
286: * @param bean an object
287: * @return if true then all properties were successfully set, else some
288: * were not
289: */
290: public boolean setProperties(Object bean) {
291: boolean complete = true;
292: try {
293: Class beanClass = bean.getClass();
294: Map params = new HashMap();
295: for (Iterator e = requestData.keySet().iterator(); e
296: .hasNext();) {
297: String name = (String) e.next();
298: String value = getParameter(name);
299: params.put(name, value);
300: }
301: PropertyDescriptor[] props = Introspector.getBeanInfo(
302: beanClass).getPropertyDescriptors();
303:
304: for (int i = 0; i < props.length; i++) {
305: String propname = props[i].getName();
306: Method setter = props[i].getWriteMethod();
307: if ((setter != null) && (params.containsKey(propname))) {
308: try {
309: setProperty(bean, props[i]);
310: } catch (Exception e) {
311: e.printStackTrace();
312: complete = false;
313: }
314: }
315: }
316: } catch (Exception e) {
317: // swallow all exceptions, just populate what you can
318: complete = false;
319: }
320: return complete;
321: }
322:
323: public void setRequestAttribute(String name, Object value) {
324: requestAttributes.put(name, value);
325: }
326:
327: public Object getRequestAttribute(String name) {
328: return requestAttributes.get(name);
329: }
330:
331: public void setSessionAttribute(String name, Object value) {
332: session.put(name, value);
333: }
334:
335: public Object getSessionAttribute(String name) {
336: return session.get(name);
337: }
338:
339: public void removeRequestAttribute(String name) {
340: requestAttributes.remove(name);
341: }
342:
343: public void removeSessionAttribute(String name) {
344: session.remove(name);
345: removedSessionKeys.add(name);
346: }
347:
348: /**
349: * Passthru method to the request object.
350: *
351: * @param name a String with the name of the parameter
352: * @param defaultValue if no parameter with that name is defined
353: * the return value is the defaultValue
354: * @return a String with the parameter value or
355: * the default value.
356: */
357: public String getParameter(String name, String defaultValue) {
358: String value = getParameter(name);
359:
360: return (value != null) ? value : defaultValue;
361: }
362:
363: public boolean getParameterAsBoolean(String name) {
364: String val = getParameter(name);
365: if ("on".equals(val)) {
366: val = "true";
367: }
368: return Boolean.valueOf(val).booleanValue();
369: }
370:
371: public Date getParameterAsDate(String name) {
372: Date retVal = null;
373: try {
374: java.text.SimpleDateFormat df = new java.text.SimpleDateFormat(
375: Constants.SYSTEM_DATE_FORMAT);
376: df.setLenient(false);
377: retVal = df.parse(getParameter(name, ""));
378: } catch (java.text.ParseException e) {
379: // do nothing
380: }
381:
382: return retVal;
383: }
384:
385: public Double getParameterAsDouble(String name, double defaultValue) {
386: Double value = getParameterAsDouble(name);
387:
388: return (value != null) ? value : new Double(defaultValue);
389: }
390:
391: public Double getParameterAsDouble(String name) {
392: String value = getParameter(name);
393: try {
394: return (value != null) ? new Double(value) : null;
395: } catch (NumberFormatException e) {
396: return null;
397: }
398: }
399:
400: public double getParameterAsDoublePrimitive(String name,
401: double defaultValue) {
402: return getParameterAsDouble(name, defaultValue).doubleValue();
403: }
404:
405: public int getParameterAsInt(String name, int defaultValue) {
406: return getParameterAsInteger(name, defaultValue).intValue();
407: }
408:
409: public Integer getParameterAsInteger(String name, int defaultValue) {
410: Integer value = getParameterAsInteger(name);
411:
412: return (value != null) ? value : new Integer(defaultValue);
413: }
414:
415: public Integer getParameterAsInteger(String name) {
416: String value = getParameter(name);
417: try {
418: return (value != null) ? new Integer(value) : null;
419: } catch (NumberFormatException e) {
420: return null;
421: }
422: }
423:
424: public Long getParameterAsLong(String name, long defaultValue) {
425: Long value = getParameterAsLong(name);
426:
427: return (value != null) ? value : new Long(defaultValue);
428: }
429:
430: public Long getParameterAsLong(String name) {
431: String value = getParameter(name);
432: try {
433: return (value != null) ? new Long(value) : null;
434: } catch (NumberFormatException e) {
435: return null;
436: }
437: }
438:
439: public long getParameterAsLongPrimitive(String name,
440: long defaultValue) {
441: return getParameterAsLong(name, defaultValue).longValue();
442: }
443:
444: /**
445: * Method to the request values as longs.
446: * @param name a String containing the parameter name.
447: * @return an array of Longs with all values associated
448: *
449: */
450: public Long[] getParameterValuesLong(String name) {
451: String[] vals = getParameterValues(name);
452: if (vals != null) {
453: Long[] retVals = new Long[vals.length];
454: for (int i = 0; i < vals.length; i++) {
455: try {
456: retVals[i] = (vals[i] != null) ? new Long(vals[i])
457: : null;
458: } catch (NumberFormatException e) {
459: retVals[i] = null;
460: }
461: }
462:
463: return retVals;
464: } else {
465: return new Long[0];
466: }
467: }
468:
469: public UploadedFile getUploadedFile(String name)
470: throws FileUploadException {
471: return (getMultipartRequest()).getFileParameter(name);
472: }
473:
474: public void setWorkflowUser(CoefficientUser workflowUser) {
475: this .workflowUser = workflowUser;
476: }
477:
478: /**
479: * This is used to do anything that needs doing for a workflow action
480: * to succeed
481: */
482: public void beginWorkflowAction() {
483: if (!inWorkflowAction) {
484: tempUser = getCurrentUser();
485: if (workflowUser != null) {
486: setSessionAttribute(Constants.USER_SESSION_STRING,
487: workflowUser);
488: }
489: inWorkflowAction = true;
490: }
491: }
492:
493: /**
494: * This should reset the state if need be
495: */
496: public void endWorkflowAction() {
497: if (inWorkflowAction) {
498: setSessionAttribute(Constants.USER_SESSION_STRING, tempUser);
499: try {
500: clearPage();
501: } catch (IOException ioex) {
502: // just let it go
503: }
504: inWorkflowAction = false;
505: }
506: }
507:
508: public String getLastNonHelpOp() {
509: return (String) getSessionAttribute(LAST_NON_HELP_OP);
510: }
511:
512: public void setProject(Project project) {
513: this .session.put(CURRENT_PROJECT, project);
514: }
515:
516: public Project getProject() {
517: return (Project) this .session.get(CURRENT_PROJECT);
518: }
519:
520: public void invalidateSession() {
521: session.clear();
522: invalidateSession = true;
523: }
524:
525: /**
526: * If a user is logged in this will return that user otherwise it will
527: * return null
528: *
529: * @return the logged in user or null if not logged in
530: */
531: public CoefficientUser getCurrentUser() {
532: return (CoefficientUser) getSessionAttribute(Constants.USER_SESSION_STRING);
533: }
534:
535: public String getRequestURL() {
536: return requestURL;
537: }
538:
539: /**
540: * Set the property 'prop' in the bean to the value of the
541: * corresponding parameters. Supports all types supported by
542: * getXXX methods plus a few more that come for free because
543: * primitives have to be wrapped before being passed to invoke
544: * anyway.
545: *
546: * @param bean An Object.
547: * @param prop A PropertyDescriptor.
548: * @exception Exception a generic exception.
549: */
550: protected void setProperty(Object bean, PropertyDescriptor prop)
551: throws Exception {
552: if (prop instanceof IndexedPropertyDescriptor) {
553: throw new Exception(prop.getName()
554: + " is an indexed property (not supported)");
555: }
556:
557: Method setter = prop.getWriteMethod();
558: if (setter == null) {
559: throw new Exception(prop.getName()
560: + " is a read only property");
561: }
562:
563: Class propclass = prop.getPropertyType();
564: Object[] args = { null };
565:
566: if (propclass == String.class) {
567: args[0] = getParameter(prop.getName());
568: } else if ((propclass == Integer.class)
569: || (propclass == Integer.TYPE)) {
570: args[0] = getParameterAsInteger(prop.getName());
571: } else if ((propclass == Long.class)
572: || (propclass == Long.TYPE)) {
573: args[0] = getParameterAsLong(prop.getName());
574: } else if ((propclass == Boolean.class)
575: || (propclass == Boolean.TYPE)) {
576: args[0] = new Boolean(getParameterAsBoolean(prop.getName()));
577: } else if ((propclass == Double.class)
578: || (propclass == Double.TYPE)) {
579: args[0] = getParameterAsDouble(prop.getName());
580: } else if (propclass == String[].class) {
581: args[0] = getParameterValues(prop.getName());
582: } else if (propclass == Object.class) {
583: args[0] = getParameter(prop.getName());
584: } else if (propclass == Date.class) {
585: args[0] = getParameterAsDate(prop.getName());
586: } else if (propclass == java.util.Locale.class) {
587: args[0] = new java.util.Locale(getParameter(prop.getName()));
588: } else if (propclass == java.util.TimeZone.class) {
589: args[0] = java.util.TimeZone.getTimeZone(getParameter(prop
590: .getName()));
591: } else {
592: throw new Exception("property " + prop.getName()
593: + " is of unsupported type " + propclass.toString());
594: }
595:
596: setter.invoke(bean, args);
597: }
598:
599: protected void clearPage() throws IOException {
600: createPageObject();
601: this .redirectionURL = null;
602: }
603:
604: /*
605: * @see za.org.coefficient.core.BaseCoefficientContext#createPageObject()
606: */
607: protected void createPageObject() throws IOException {
608: this .page_ = new Page(this );
609: }
610:
611: private String getCallerClassName() {
612: StackTraceElement[] ste = new Exception().getStackTrace();
613: if ((ste == null) || (ste.length < 3)) {
614: return null;
615: } else {
616: return ste[2].getClassName();
617: }
618: }
619:
620: }
|