Source Code Cross Referenced for MailboxAction.java in  » ERP-CRM-Financial » sakai » org » sakaiproject » mailarchive » tool » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » sakai » org.sakaiproject.mailarchive.tool 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**********************************************************************************
0002:         * $URL: https://source.sakaiproject.org/svn/mailarchive/tags/sakai_2-4-1/mailarchive-tool/tool/src/java/org/sakaiproject/mailarchive/tool/MailboxAction.java $
0003:         * $Id: MailboxAction.java 29104 2007-04-18 22:03:36Z ajpoland@iupui.edu $
0004:         ***********************************************************************************
0005:         *
0006:         * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
0007:         * 
0008:         * Licensed under the Educational Community License, Version 1.0 (the "License"); 
0009:         * you may not use this file except in compliance with the License. 
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         *      http://www.opensource.org/licenses/ecl1.php
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software 
0015:         * distributed under the License is distributed on an "AS IS" BASIS, 
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
0017:         * See the License for the specific language governing permissions and 
0018:         * limitations under the License.
0019:         *
0020:         **********************************************************************************/package org.sakaiproject.mailarchive.tool;
0021:
0022:        import java.util.Collections;
0023:        import java.util.Comparator;
0024:        import java.util.Iterator;
0025:        import java.util.List;
0026:        import java.util.Vector;
0027:
0028:        import org.sakaiproject.alias.api.Alias;
0029:        import org.sakaiproject.alias.cover.AliasService;
0030:        import org.sakaiproject.authz.api.PermissionsHelper;
0031:        import org.sakaiproject.cheftool.Context;
0032:        import org.sakaiproject.cheftool.JetspeedRunData;
0033:        import org.sakaiproject.cheftool.PagedResourceActionII;
0034:        import org.sakaiproject.cheftool.PortletConfig;
0035:        import org.sakaiproject.cheftool.RunData;
0036:        import org.sakaiproject.cheftool.VelocityPortlet;
0037:        import org.sakaiproject.cheftool.api.Menu;
0038:        import org.sakaiproject.cheftool.menu.MenuDivider;
0039:        import org.sakaiproject.cheftool.menu.MenuEntry;
0040:        import org.sakaiproject.cheftool.menu.MenuImpl;
0041:        import org.sakaiproject.component.cover.ServerConfigurationService;
0042:        import org.sakaiproject.content.cover.ContentTypeImageService;
0043:        import org.sakaiproject.entity.api.Reference;
0044:        import org.sakaiproject.entity.cover.EntityManager;
0045:        import org.sakaiproject.event.api.SessionState;
0046:        import org.sakaiproject.exception.IdUnusedException;
0047:        import org.sakaiproject.exception.PermissionException;
0048:        import org.sakaiproject.javax.PagingPosition;
0049:        import org.sakaiproject.mailarchive.api.MailArchiveChannel;
0050:        import org.sakaiproject.mailarchive.api.MailArchiveChannelEdit;
0051:        import org.sakaiproject.mailarchive.api.MailArchiveMessage;
0052:        import org.sakaiproject.mailarchive.cover.MailArchiveService;
0053:        import org.sakaiproject.site.cover.SiteService;
0054:        import org.sakaiproject.tool.cover.ToolManager;
0055:        import org.sakaiproject.user.api.User;
0056:        import org.sakaiproject.user.cover.UserDirectoryService;
0057:        import org.sakaiproject.util.FormattedText;
0058:        import org.sakaiproject.util.ResourceLoader;
0059:        import org.sakaiproject.util.StringUtil;
0060:        import org.sakaiproject.util.Validator;
0061:
0062:        /**
0063:         * <p>
0064:         * MailboxAction is a the Sakai mailbox tool.
0065:         * </p>
0066:         */
0067:        public class MailboxAction extends PagedResourceActionII {
0068:            private static ResourceLoader rb = new ResourceLoader("email");
0069:
0070:            /** portlet configuration parameter names. */
0071:            private static final String PARAM_CHANNEL = "channel";
0072:
0073:            private static final String PARAM_SITE = "site";
0074:
0075:            /** Configure form field names. */
0076:            private static final String FORM_CHANNEL = "channel";
0077:
0078:            private static final String FORM_PAGESIZE = "pagesize";
0079:
0080:            private static final String FORM_OPEN = "open";
0081:
0082:            private static final String FORM_ALIAS = "alias";
0083:
0084:            /** List request parameters. */
0085:            private static final String VIEW_ID = "view-id";
0086:
0087:            /** state attribute names. */
0088:            private static final String STATE_CHANNEL_REF = "channelId";
0089:
0090:            private static final String STATE_ASCENDING = "ascending";
0091:
0092:            private static final String STATE_SORT = "sort";
0093:
0094:            private static final String STATE_VIEW_HEADERS = "view-headers";
0095:
0096:            private static final String STATE_OPTION_PAGESIZE = "optSize";
0097:
0098:            private static final String STATE_OPTION_OPEN = "optOpen";
0099:
0100:            private static final String STATE_OPTION_ALIAS = "optAlias";
0101:
0102:            /** Sort codes. */
0103:            private static final int SORT_FROM = 0;
0104:
0105:            private static final int SORT_DATE = 1;
0106:
0107:            private static final int SORT_SUBJECT = 2;
0108:
0109:            /** paging */
0110:            private static final String STATE_ALL_MESSAGES = "allMessages";
0111:
0112:            private static final String STATE_MSG_VIEW_ID = "msg-id";
0113:
0114:            /** paging */
0115:            /*
0116:             * (non-Javadoc)
0117:             * 
0118:             * @see org.sakaiproject.cheftool.PagedResourceActionII#readResourcesPage(org.sakaiproject.service.framework.session.SessionState, int, int)
0119:             */
0120:            protected List readResourcesPage(SessionState state, int first,
0121:                    int last) {
0122:
0123:                List rv = new Vector();
0124:                if (state.getAttribute(STATE_ALL_MESSAGES) != null) {
0125:                    rv = (List) state.getAttribute(STATE_ALL_MESSAGES);
0126:                }
0127:
0128:                PagingPosition page = new PagingPosition(first, last);
0129:                page.validate(rv.size());
0130:                rv = rv.subList(page.getFirst() - 1, page.getLast());
0131:
0132:                return rv;
0133:            }
0134:
0135:            /*
0136:             * (non-Javadoc)
0137:             * 
0138:             * @see org.sakaiproject.cheftool.PagedResourceActionII#sizeResources(org.sakaiproject.service.framework.session.SessionState)
0139:             */
0140:            protected int sizeResources(SessionState state) {
0141:                int size = 0;
0142:                if (state.getAttribute(STATE_ALL_MESSAGES) != null) {
0143:                    size = ((List) state.getAttribute(STATE_ALL_MESSAGES))
0144:                            .size();
0145:                }
0146:                return size;
0147:            }
0148:
0149:            /**
0150:             * Sort support for email messages.
0151:             */
0152:            private class MyComparator implements  Comparator {
0153:                /** the criteria - a sort code. */
0154:                private int m_criteria = SORT_DATE;
0155:
0156:                /** True for ascending sort, false for descending. */
0157:                private boolean m_asc = true;
0158:
0159:                /**
0160:                 * constructor
0161:                 * 
0162:                 * @param criteria
0163:                 *        The sort criteria string
0164:                 * @param asc
0165:                 *        The sort order string. "true" if ascending; "false" otherwise.
0166:                 */
0167:                public MyComparator(int criteria, boolean asc) {
0168:                    m_criteria = criteria;
0169:                    m_asc = asc;
0170:
0171:                } // MyComparator
0172:
0173:                /**
0174:                 * Compares its two arguments for order.
0175:                 * 
0176:                 * @param o1
0177:                 *        The first object.
0178:                 * @param o2
0179:                 *        The second object.
0180:                 * @return a a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
0181:                 */
0182:                public int compare(Object o1, Object o2) {
0183:                    // make these MailArchiveMessages - let the class cast exception be thrown if not
0184:                    MailArchiveMessage m1 = (MailArchiveMessage) o1;
0185:                    MailArchiveMessage m2 = (MailArchiveMessage) o2;
0186:
0187:                    // if these are the same object (or equal - it may be cheaper to just let the comparison find the equality)
0188:                    if ((m1 == m2) /* || (m1.equals(m2)) */)
0189:                        return 0;
0190:
0191:                    // if it's ascending, use the compareTo value - if descending, reverse it
0192:                    int orderFactor = (m_asc ? 1 : -1);
0193:
0194:                    switch (m_criteria) {
0195:                    case SORT_FROM: {
0196:                        String addr1 = m1.getMailArchiveHeader()
0197:                                .getFromAddress();
0198:                        String addr2 = m2.getMailArchiveHeader()
0199:                                .getFromAddress();
0200:                        String rex = "^[^<>]*<[^<>@]*@[^<>@]*>[^<>@]*";
0201:                        if (addr1.matches(rex)) {
0202:                            addr1 = addr1.substring(addr1.indexOf('<') + 1,
0203:                                    addr1.indexOf('>'));
0204:                        }
0205:                        if (addr2.matches(rex)) {
0206:                            addr2 = addr2.substring(addr2.indexOf('<') + 1,
0207:                                    addr2.indexOf('>'));
0208:                        }
0209:                        return orderFactor * addr1.compareTo(addr2);
0210:                    }
0211:
0212:                    case SORT_DATE: {
0213:                        return orderFactor
0214:                                * m1.getMailArchiveHeader().getDateSent()
0215:                                        .compareTo(
0216:                                                m2.getMailArchiveHeader()
0217:                                                        .getDateSent());
0218:                    }
0219:
0220:                    case SORT_SUBJECT: {
0221:                        String subj1 = m1.getMailArchiveHeader().getSubject()
0222:                                .toUpperCase();
0223:                        String subj2 = m2.getMailArchiveHeader().getSubject()
0224:                                .toUpperCase();
0225:                        while (subj1.startsWith("RE:")) {
0226:                            subj1 = subj1.substring(subj1.indexOf(':') + 1)
0227:                                    .trim();
0228:                        }
0229:                        while (subj2.startsWith("RE:")) {
0230:                            subj2 = subj2.substring(subj2.indexOf(':') + 1)
0231:                                    .trim();
0232:                        }
0233:                        return orderFactor * subj1.compareTo(subj2);
0234:                    }
0235:                    }
0236:
0237:                    // trouble!
0238:                    Log.warn("chef",
0239:                            "MailboxAction.MyComparator - invalid sort: "
0240:                                    + m_criteria);
0241:                    return 0;
0242:
0243:                } // compare
0244:
0245:            } // class MyComparator
0246:
0247:            /**
0248:             * Implement this to return alist of all the resources that there are to page. Sort them as appropriate.
0249:             */
0250:            protected List readAllResources(SessionState state) {
0251:                // read all channel messages
0252:                List allMessages = null;
0253:                try {
0254:                    MailArchiveChannel channel = MailArchiveService
0255:                            .getMailArchiveChannel((String) state
0256:                                    .getAttribute(STATE_CHANNEL_REF));
0257:
0258:                    allMessages = channel.getMessages(null, true);
0259:                } catch (PermissionException e) {
0260:                } catch (IdUnusedException e) {
0261:                }
0262:
0263:                // deal with no messages
0264:                if (allMessages == null)
0265:                    return new Vector();
0266:
0267:                String search = (String) state.getAttribute(STATE_SEARCH);
0268:
0269:                // filter if searching
0270:                if (search != null) {
0271:                    Vector filtered = new Vector();
0272:                    for (Iterator iMsgs = allMessages.iterator(); iMsgs
0273:                            .hasNext();) {
0274:                        MailArchiveMessage msg = (MailArchiveMessage) iMsgs
0275:                                .next();
0276:
0277:                        if (StringUtil.containsIgnoreCase(msg
0278:                                .getMailArchiveHeader().getSubject(), search)
0279:                                || StringUtil.containsIgnoreCase(msg
0280:                                        .getMailArchiveHeader()
0281:                                        .getFromAddress(), search)
0282:                                || StringUtil.containsIgnoreCase(FormattedText
0283:                                        .convertFormattedTextToPlaintext(msg
0284:                                                .getBody()), search)) {
0285:                            filtered.add(msg);
0286:                        }
0287:                    }
0288:
0289:                    allMessages = filtered;
0290:                }
0291:
0292:                // if other than ascending date, sort them all
0293:                boolean ascending = ((Boolean) state
0294:                        .getAttribute(STATE_ASCENDING)).booleanValue();
0295:                int sort = ((Integer) state.getAttribute(STATE_SORT))
0296:                        .intValue();
0297:                if ((allMessages.size() > 1)
0298:                        && ((!ascending) || (sort != SORT_DATE))) {
0299:                    Collections.sort(allMessages, new MyComparator(sort,
0300:                            ascending));
0301:                }
0302:
0303:                return allMessages;
0304:
0305:            } // readAllResources
0306:
0307:            /**
0308:             * Populate the state object, if needed.
0309:             */
0310:            protected void initState(SessionState state,
0311:                    VelocityPortlet portlet, JetspeedRunData rundata) {
0312:                super .initState(state, portlet, rundata);
0313:
0314:                if (state.getAttribute(STATE_CHANNEL_REF) == null) {
0315:                    PortletConfig config = portlet.getPortletConfig();
0316:
0317:                    // start in list mode
0318:                    state.setAttribute(STATE_MODE, "list");
0319:
0320:                    // read the channel from configuration, or, if not specified, use the default for the request
0321:                    String channel = StringUtil.trimToNull(config
0322:                            .getInitParameter(PARAM_CHANNEL));
0323:                    if (channel == null) {
0324:                        channel = MailArchiveService.channelReference(
0325:                                ToolManager.getCurrentPlacement().getContext(),
0326:                                SiteService.MAIN_CONTAINER);
0327:                    }
0328:                    state.setAttribute(STATE_CHANNEL_REF, channel);
0329:
0330:                    if (state.getAttribute(STATE_ASCENDING) == null) {
0331:                        state.setAttribute(STATE_ASCENDING, new Boolean(false));
0332:                    }
0333:
0334:                    if (state.getAttribute(STATE_SORT) == null) {
0335:                        state.setAttribute(STATE_SORT, new Integer(SORT_DATE));
0336:                    }
0337:
0338:                    if (state.getAttribute(STATE_VIEW_HEADERS) == null) {
0339:                        state.setAttribute(STATE_VIEW_HEADERS, new Boolean(
0340:                                false));
0341:                    }
0342:
0343:                    // // setup the observer to notify our main panel
0344:                    // if (state.getAttribute(STATE_OBSERVER) == null)
0345:                    // {
0346:                    // // the delivery location for this tool
0347:                    // String deliveryId = clientWindowId(state, portlet.getID());
0348:                    //				
0349:                    // // the html element to update on delivery
0350:                    // String elementId = mainPanelUpdateId(portlet.getID());
0351:                    //				
0352:                    // // the event resource reference pattern to watch for
0353:                    // Reference r = EntityManager.newReference(channel);
0354:                    // String pattern = MailArchiveService.messageReference(r.getContext(), r.getId(), "");
0355:                    //
0356:                    // state.setAttribute(STATE_OBSERVER, new EventObservingCourier(deliveryId, elementId, pattern));
0357:                    // }
0358:                }
0359:
0360:            } // initState
0361:
0362:            /**
0363:             * build the context for the main panel
0364:             * 
0365:             * @return (optional) template name for this panel
0366:             */
0367:            public String buildMainPanelContext(VelocityPortlet portlet,
0368:                    Context context, RunData rundata, SessionState state) {
0369:                String mode = (String) state.getAttribute(STATE_MODE);
0370:
0371:                context.put(Menu.CONTEXT_ACTION, state
0372:                        .getAttribute(STATE_ACTION));
0373:
0374:                if ("list".equals(mode)) {
0375:                    return buildListModeContext(portlet, context, rundata,
0376:                            state);
0377:                }
0378:
0379:                else if ("confirm-remove".equals(mode)) {
0380:                    return buildConfirmModeContext(portlet, context, rundata,
0381:                            state);
0382:                }
0383:
0384:                else if ("view".equals(mode)) {
0385:                    return buildViewModeContext(portlet, context, rundata,
0386:                            state);
0387:                }
0388:
0389:                else if (MODE_OPTIONS.equals(mode)) {
0390:                    return buildOptionsPanelContext(portlet, context, rundata,
0391:                            state);
0392:                }
0393:
0394:                else {
0395:                    Log.warn("chef", this 
0396:                            + ".buildMainPanelContext: invalid mode: " + mode);
0397:                    return null;
0398:                }
0399:
0400:            } // buildMainPanelContext
0401:
0402:            /**
0403:             * build the context for the View mode (in the Main panel)
0404:             * 
0405:             * @return (optional) template name for this panel
0406:             */
0407:            private String buildViewModeContext(VelocityPortlet portlet,
0408:                    Context context, RunData rundata, SessionState state) {
0409:                boolean allowDelete = false;
0410:
0411:                // get the message
0412:                MailArchiveMessage message = null;
0413:
0414:                // prepare the sort of messages
0415:                context.put("tlang", rb);
0416:                prepPage(state);
0417:
0418:                List messages = (List) state.getAttribute(STATE_ALL_MESSAGES);
0419:                int pos = ((Integer) state.getAttribute(STATE_VIEW_ID))
0420:                        .intValue();
0421:                message = (MailArchiveMessage) messages.get(pos);
0422:
0423:                // fix for SAK-5879
0424:                // make sure STATE_MSG_VIEW_ID is updated so that Confirm mode will have access to the correct message id
0425:                state.setAttribute(STATE_MSG_VIEW_ID, message.getId());
0426:                //
0427:
0428:                boolean goNext = state.getAttribute(STATE_NEXT_EXISTS) != null;
0429:                boolean goPrev = state.getAttribute(STATE_PREV_EXISTS) != null;
0430:                context.put("goPPButton", new Boolean(goPrev));
0431:                context.put("goNPButton", new Boolean(goNext));
0432:
0433:                try {
0434:                    MailArchiveChannel channel = MailArchiveService
0435:                            .getMailArchiveChannel((String) state
0436:                                    .getAttribute(STATE_CHANNEL_REF));
0437:                    context.put("email", message);
0438:
0439:                    allowDelete = channel.allowRemoveMessage(message);
0440:                } catch (IdUnusedException e) {
0441:                } catch (PermissionException e) {
0442:                }
0443:                if (message == null) {
0444:                    context.put("message", rb.getString("thiemames1"));
0445:                }
0446:
0447:                context.put("viewheaders", state
0448:                        .getAttribute(STATE_VIEW_HEADERS));
0449:
0450:                context.put("contentTypeImageService", ContentTypeImageService
0451:                        .getInstance());
0452:
0453:                // build the menu
0454:                Menu bar = new MenuImpl(portlet, rundata, (String) state
0455:                        .getAttribute(STATE_ACTION));
0456:
0457:                // bar.add( new MenuEntry(rb.getString("listall"), "doList"));
0458:                // addViewPagingMenus(bar, state);
0459:
0460:                if (((Boolean) state.getAttribute(STATE_VIEW_HEADERS))
0461:                        .booleanValue()) {
0462:                    bar.add(new MenuEntry(rb.getString("hidehead"),
0463:                            "doHide_headers"));
0464:                } else {
0465:                    bar.add(new MenuEntry(rb.getString("viehea"),
0466:                            "doView_headers"));
0467:                }
0468:                if (allowDelete)
0469:                    bar.add(new MenuEntry(rb.getString("del"), "doRemove"));
0470:
0471:                // make sure there's not leading or trailing dividers
0472:                bar.adjustDividers();
0473:
0474:                context.put(Menu.CONTEXT_MENU, bar);
0475:
0476:                return (String) getContext(rundata).get("template") + "-view";
0477:
0478:            } // buildViewModeContext
0479:
0480:            /*
0481:             * 
0482:             */
0483:            /*
0484:             * private MailArchiveMessage adjustPaging(Context context, SessionState state) { MailArchiveMessage message = null; List messages = (List) state.getAttribute(STATE_ALL_MESSAGES); int pos = ((Integer) state.getAttribute(STATE_VIEW_ID)).intValue();
0485:             * boolean goNext = state.getAttribute(STATE_GO_NEXT) != null; boolean goPrev = state.getAttribute(STATE_GO_PREV) != null; state.removeAttribute(STATE_GO_NEXT); state.removeAttribute(STATE_GO_PREV); if (goNext || goPrev) { if (goNext) { if (pos <
0486:             * messages.size()-1) { pos++; } } if (goPrev) { if (pos > 0) { pos--; } } } if (pos == -1) { pos = 0; } if (pos >= messages.size()) { pos = messages.size() -1; } message = (MailArchiveMessage) messages.get(pos); //get the message id if (pos > 0) {
0487:             * context.put("goPPButton", Boolean.TRUE); } else { context.put("goPPButton", Boolean.FALSE); } if (pos < sizeResources(state)-1) { context.put("goNPButton", Boolean.TRUE); } else { context.put("goNPButton", Boolean.FALSE); } return message; }
0488:             */
0489:
0490:            /**
0491:             * Build the context for the confirm remove mode (in the Main panel).
0492:             */
0493:            private String buildConfirmModeContext(VelocityPortlet portlet,
0494:                    Context context, RunData rundata, SessionState state) {
0495:                // get the message
0496:                context.put("tlang", rb);
0497:                MailArchiveMessage message = null;
0498:                try {
0499:                    MailArchiveChannel channel = MailArchiveService
0500:                            .getMailArchiveChannel((String) state
0501:                                    .getAttribute(STATE_CHANNEL_REF));
0502:                    message = channel.getMailArchiveMessage((String) state
0503:                            .getAttribute(STATE_MSG_VIEW_ID));
0504:                    context.put("email", message);
0505:                } catch (IdUnusedException e) {
0506:                } catch (PermissionException e) {
0507:                }
0508:
0509:                if (message == null) {
0510:                    context.put("message", rb.getString("thiemames1"));
0511:                }
0512:
0513:                context.put("viewheaders", state
0514:                        .getAttribute(STATE_VIEW_HEADERS));
0515:
0516:                return (String) getContext(rundata).get("template")
0517:                        + "-confirm_remove";
0518:
0519:            } // buildConfirmModeContext
0520:
0521:            /**
0522:             * build the context for the list mode (in the Main panel).
0523:             */
0524:            private String buildListModeContext(VelocityPortlet portlet,
0525:                    Context context, RunData rundata, SessionState state) {
0526:                state.setAttribute(STATE_ALL_MESSAGES, readAllResources(state));
0527:
0528:                // prepare the page of messages
0529:                context.put("tlang", rb);
0530:                List messages = prepPage(state);
0531:                context.put("messages", messages);
0532:
0533:                // build the menu
0534:                Menu bar = new MenuImpl(portlet, rundata, (String) state
0535:                        .getAttribute(STATE_ACTION));
0536:
0537:                // add paging commands
0538:                // addListPagingMenus(bar, state);
0539:
0540:                // add the search commands
0541:                // addSearchMenus(bar, state);
0542:
0543:                // add the refresh commands
0544:                // addRefreshMenus(bar, state);
0545:
0546:                if (SiteService.allowUpdateSite(ToolManager
0547:                        .getCurrentPlacement().getContext())) {
0548:                    bar.add(new MenuDivider());
0549:
0550:                    // add options if allowed
0551:                    addOptionsMenu(bar, (JetspeedRunData) rundata);
0552:
0553:                    bar
0554:                            .add(new MenuEntry(rb.getString("perm"),
0555:                                    "doPermissions"));
0556:                }
0557:
0558:                // make sure there's not leading or trailing dividers
0559:                bar.adjustDividers();
0560:
0561:                context.put(Menu.CONTEXT_MENU, bar);
0562:
0563:                // output the search field
0564:                context.put(STATE_SEARCH, state.getAttribute(STATE_SEARCH));
0565:
0566:                // if (state.getAttribute(STATE_NUM_MESSAGES) != null)
0567:                // {
0568:                // context.put("num-messages", state.getAttribute(STATE_NUM_MESSAGES));
0569:                // }
0570:
0571:                // eventSubmit value and id field for drill down
0572:                context.put("view-id", VIEW_ID);
0573:
0574:                context.put(Menu.CONTEXT_ACTION, state
0575:                        .getAttribute(STATE_ACTION));
0576:
0577:                context.put("sort-by", state.getAttribute(STATE_SORT));
0578:                context.put("sort-order", state.getAttribute(STATE_ASCENDING));
0579:
0580:                pagingInfoToContext(state, context);
0581:
0582:                // the aliases for the channel
0583:                List all = AliasService.getAliases((String) state
0584:                        .getAttribute(STATE_CHANNEL_REF));
0585:
0586:                // and the aliases for the site (context)
0587:                Reference channelRef = EntityManager
0588:                        .newReference((String) state
0589:                                .getAttribute(STATE_CHANNEL_REF));
0590:                String siteRef = SiteService.siteReference(channelRef
0591:                        .getContext());
0592:                all.addAll(AliasService.getAliases(siteRef));
0593:
0594:                context.put("aliases", all);
0595:                context.put("nonAlias", channelRef.getContext());
0596:                context.put("serverName", ServerConfigurationService
0597:                        .getServerName());
0598:
0599:                // if the user has permission to send mail, drop in the email address
0600:                try {
0601:                    MailArchiveChannel channel = MailArchiveService
0602:                            .getMailArchiveChannel((String) state
0603:                                    .getAttribute(STATE_CHANNEL_REF));
0604:                    if (channel.getEnabled()) {
0605:                        if (channel.getOpen()) {
0606:                            // if open, mail from anywhere
0607:                            context.put("validFrom", "*");
0608:                        } else if (channel.allowAddMessage()) {
0609:                            User user = UserDirectoryService.getCurrentUser();
0610:                            String email = user.getEmail();
0611:                            context.put("validFrom", email);
0612:                        }
0613:                    }
0614:                } catch (IdUnusedException e) {
0615:                    addAlert(state, rb.getString("thismaiis"));
0616:                } catch (PermissionException e) {
0617:                    addAlert(state, rb.getString("youdonot1"));
0618:                } catch (Exception e) {
0619:                }
0620:
0621:                // inform the observing courier that we just updated the page...
0622:                // if there are pending requests to do so they can be cleared
0623:                justDelivered(state);
0624:
0625:                return (String) getContext(rundata).get("template") + "-List";
0626:
0627:            } // buildListModeContext
0628:
0629:            /**
0630:             * Handle a user drill down request.
0631:             */
0632:            public void doView(RunData runData, Context context) {
0633:                // access the portlet element id to find our state
0634:                String peid = ((JetspeedRunData) runData).getJs_peid();
0635:                SessionState state = ((JetspeedRunData) runData)
0636:                        .getPortletSessionState(peid);
0637:
0638:                // switch to view mode
0639:                state.setAttribute(STATE_MODE, "view");
0640:
0641:                String id = runData.getParameters().getString(VIEW_ID);
0642:                state.setAttribute(STATE_MSG_VIEW_ID, id);
0643:
0644:                int pos = -1;
0645:                List resources = (List) state.getAttribute(STATE_ALL_MESSAGES);
0646:                if (resources != null) {
0647:                    for (int i = 0; i < resources.size(); i++) {
0648:                        // if this is the one, return this index
0649:                        if (((MailArchiveMessage) (resources.get(i))).getId()
0650:                                .equals(id))
0651:                            pos = i;
0652:                    }
0653:                }
0654:                state.setAttribute(STATE_VIEW_ID, new Integer(pos));
0655:
0656:                // disable auto-updates while in view mode
0657:                disableObservers(state);
0658:
0659:                // set the message id
0660:                // state.setAttribute(STATE_VIEW_ID, runData.getParameters().getString(VIEW_ID));
0661:
0662:            } // doView
0663:
0664:            /**
0665:             * Handle a return-to-list-view request.
0666:             */
0667:            public void doList(RunData runData, Context context) {
0668:                // access the portlet element id to find our state
0669:                String peid = ((JetspeedRunData) runData).getJs_peid();
0670:                SessionState state = ((JetspeedRunData) runData)
0671:                        .getPortletSessionState(peid);
0672:
0673:                // switch to view mode
0674:                state.setAttribute(STATE_MODE, "list");
0675:
0676:                // make sure auto-updates are enabled
0677:                enableObserver(state);
0678:
0679:                // cleanup
0680:                state.removeAttribute(STATE_VIEW_ID);
0681:                state.removeAttribute(STATE_MSG_VIEW_ID);
0682:
0683:            } // doList
0684:
0685:            /**
0686:             * Handle a view headers request.
0687:             */
0688:            public void doView_headers(RunData runData, Context context) {
0689:                // access the portlet element id to find our state
0690:                String peid = ((JetspeedRunData) runData).getJs_peid();
0691:                SessionState state = ((JetspeedRunData) runData)
0692:                        .getPortletSessionState(peid);
0693:
0694:                // switch to view mode
0695:                state.setAttribute(STATE_VIEW_HEADERS, new Boolean(true));
0696:
0697:            } // doView_headers
0698:
0699:            /**
0700:             * Handle a hide headers request.
0701:             */
0702:            public void doHide_headers(RunData runData, Context context) {
0703:                // access the portlet element id to find our state
0704:                String peid = ((JetspeedRunData) runData).getJs_peid();
0705:                SessionState state = ((JetspeedRunData) runData)
0706:                        .getPortletSessionState(peid);
0707:
0708:                // switch to view mode
0709:                state.setAttribute(STATE_VIEW_HEADERS, new Boolean(false));
0710:
0711:            } // doHide_headers
0712:
0713:            /**
0714:             * Handle a user request to change the sort to "from"
0715:             */
0716:            public void doSort_from(RunData runData, Context context) {
0717:                // access the portlet element id to find our state
0718:                String peid = ((JetspeedRunData) runData).getJs_peid();
0719:                SessionState state = ((JetspeedRunData) runData)
0720:                        .getPortletSessionState(peid);
0721:
0722:                // we are changing the sort, so start from the first page again
0723:                resetPaging(state);
0724:
0725:                // if already from, swap the order
0726:                if (((Integer) state.getAttribute(STATE_SORT)).intValue() == SORT_FROM) {
0727:                    boolean order = !((Boolean) state
0728:                            .getAttribute(STATE_ASCENDING)).booleanValue();
0729:                    state.setAttribute(STATE_ASCENDING, new Boolean(order));
0730:                }
0731:
0732:                // set state
0733:                else {
0734:                    state.setAttribute(STATE_SORT, new Integer(SORT_FROM));
0735:                }
0736:
0737:            } // doSort_from
0738:
0739:            /**
0740:             * Handle a user request to change the sort to "date"
0741:             */
0742:            public void doSort_date(RunData runData, Context context) {
0743:                // access the portlet element id to find our state
0744:                String peid = ((JetspeedRunData) runData).getJs_peid();
0745:                SessionState state = ((JetspeedRunData) runData)
0746:                        .getPortletSessionState(peid);
0747:
0748:                // we are changing the sort, so start from the first page again
0749:                resetPaging(state);
0750:
0751:                // if already date, swap the order
0752:                if (((Integer) state.getAttribute(STATE_SORT)).intValue() == SORT_DATE) {
0753:                    boolean order = !((Boolean) state
0754:                            .getAttribute(STATE_ASCENDING)).booleanValue();
0755:                    state.setAttribute(STATE_ASCENDING, new Boolean(order));
0756:                }
0757:
0758:                // set state
0759:                else {
0760:                    state.setAttribute(STATE_SORT, new Integer(SORT_DATE));
0761:                }
0762:
0763:            } // doSort_date
0764:
0765:            /**
0766:             * Handle a user request to change the sort to "subject"
0767:             */
0768:            public void doSort_subject(RunData runData, Context context) {
0769:                // access the portlet element id to find our state
0770:                String peid = ((JetspeedRunData) runData).getJs_peid();
0771:                SessionState state = ((JetspeedRunData) runData)
0772:                        .getPortletSessionState(peid);
0773:
0774:                // we are changing the sort, so start from the first page again
0775:                resetPaging(state);
0776:
0777:                // if already subject, swap the order
0778:                if (((Integer) state.getAttribute(STATE_SORT)).intValue() == SORT_SUBJECT) {
0779:                    boolean order = !((Boolean) state
0780:                            .getAttribute(STATE_ASCENDING)).booleanValue();
0781:                    state.setAttribute(STATE_ASCENDING, new Boolean(order));
0782:                }
0783:
0784:                // set state
0785:                else {
0786:                    state.setAttribute(STATE_SORT, new Integer(SORT_SUBJECT));
0787:                }
0788:
0789:            } // doSort_subject
0790:
0791:            /**
0792:             * doRemove called when "eventSubmit_doRemove" is in the request parameters to confirm removal of the group
0793:             */
0794:            public void doRemove(RunData data, Context context) {
0795:                // access the portlet element id to find our state
0796:                String peid = ((JetspeedRunData) data).getJs_peid();
0797:                SessionState state = ((JetspeedRunData) data)
0798:                        .getPortletSessionState(peid);
0799:
0800:                // go to remove confirm mode
0801:                state.setAttribute(STATE_MODE, "confirm-remove");
0802:
0803:                // disable auto-updates while in confirm mode
0804:                disableObservers(state);
0805:
0806:            } // doRemove
0807:
0808:            /**
0809:             * doRemove_confirmed called when "eventSubmit_doRemove_confirmed" is in the request parameters to remove the group
0810:             */
0811:            public void doRemove_confirmed(RunData data, Context context) {
0812:                // access the portlet element id to find our state
0813:                String peid = ((JetspeedRunData) data).getJs_peid();
0814:                SessionState state = ((JetspeedRunData) data)
0815:                        .getPortletSessionState(peid);
0816:
0817:                // remove
0818:                try {
0819:                    MailArchiveChannel channel = MailArchiveService
0820:                            .getMailArchiveChannel((String) state
0821:                                    .getAttribute(STATE_CHANNEL_REF));
0822:
0823:                    String msgId = (String) state
0824:                            .getAttribute(STATE_MSG_VIEW_ID);
0825:
0826:                    if (msgId != null)
0827:                        channel.removeMessage(msgId);
0828:                    else
0829:                        addAlert(state, rb.getString("thimeshas"));
0830:                } catch (PermissionException e) {
0831:                    addAlert(state, rb.getString("youdonot3"));
0832:                } catch (IdUnusedException e) {
0833:                    addAlert(state, rb.getString("thimeshas"));
0834:                }
0835:
0836:                // go to list mode
0837:                doList(data, context);
0838:
0839:            } // doRemove_confirmed
0840:
0841:            /**
0842:             * doCancel_remove called when "eventSubmit_doCancel_remove" is in the request parameters to cancel group removal
0843:             */
0844:            public void doRemove_cancel(RunData data, Context context) {
0845:                // access the portlet element id to find our state
0846:                String peid = ((JetspeedRunData) data).getJs_peid();
0847:                SessionState state = ((JetspeedRunData) data)
0848:                        .getPortletSessionState(peid);
0849:
0850:                // return to view mode
0851:                state.setAttribute(STATE_MODE, "view");
0852:
0853:                // disable auto-updates while in view mode
0854:                disableObservers(state);
0855:
0856:            } // doRemove_cancel
0857:
0858:            /**
0859:             * Handle a request to set options.
0860:             */
0861:            public void doOptions(RunData runData, Context context) {
0862:                super .doOptions(runData, context);
0863:
0864:                // access the portlet element id to find our state
0865:                String peid = ((JetspeedRunData) runData).getJs_peid();
0866:                SessionState state = ((JetspeedRunData) runData)
0867:                        .getPortletSessionState(peid);
0868:
0869:                // if we ended up in options mode, do whatever else ...
0870:                if (!MODE_OPTIONS.equals(state.getAttribute(STATE_MODE)))
0871:                    return;
0872:
0873:            } // doOptions
0874:
0875:            /**
0876:             * Setup for options.
0877:             */
0878:            public String buildOptionsPanelContext(VelocityPortlet portlet,
0879:                    Context context, RunData rundata, SessionState state) {
0880:
0881:                context.put("tlang", rb);
0882:                // provide "pagesize" with the current page size setting
0883:                context.put("pagesize", ((Integer) state
0884:                        .getAttribute(STATE_PAGESIZE)).toString());
0885:
0886:                // provide form names
0887:                context.put("form-pagesize", FORM_PAGESIZE);
0888:                context.put("form-open", FORM_OPEN);
0889:                context.put("form-alias", FORM_ALIAS);
0890:                context.put("form-submit", BUTTON + "doUpdate");
0891:                context.put("form-cancel", BUTTON + "doCancel");
0892:
0893:                // in progress values
0894:                if (state.getAttribute(STATE_OPTION_PAGESIZE) != null)
0895:                    context.put(STATE_OPTION_PAGESIZE, state
0896:                            .getAttribute(STATE_OPTION_PAGESIZE));
0897:                if (state.getAttribute(STATE_OPTION_OPEN) != null)
0898:                    context.put(STATE_OPTION_OPEN, state
0899:                            .getAttribute(STATE_OPTION_OPEN));
0900:                if (state.getAttribute(STATE_OPTION_ALIAS) != null)
0901:                    context.put(STATE_OPTION_ALIAS, state
0902:                            .getAttribute(STATE_OPTION_ALIAS));
0903:
0904:                // provide the channel
0905:                try {
0906:                    MailArchiveChannel channel = MailArchiveService
0907:                            .getMailArchiveChannel((String) state
0908:                                    .getAttribute(STATE_CHANNEL_REF));
0909:                    context.put("channel", channel);
0910:                } catch (Exception ignore) {
0911:                }
0912:
0913:                // place the current alias, if any, in to context
0914:                List all = AliasService.getAliases((String) state
0915:                        .getAttribute(STATE_CHANNEL_REF), 1, 1);
0916:                if (!all.isEmpty())
0917:                    context.put("alias", ((Alias) all.get(0)).getId());
0918:
0919:                context.put("serverName", ServerConfigurationService
0920:                        .getServerName());
0921:
0922:                // pick the "-customize" template based on the standard template name
0923:                String template = (String) getContext(rundata).get("template");
0924:                return template + "-customize";
0925:
0926:            } // buildOptionsPanelContext
0927:
0928:            /**
0929:             * doUpdate called for form input tags type="submit" named="eventSubmit_doUpdate" update/save from the options process
0930:             */
0931:            public void doUpdate(RunData data, Context context) {
0932:                // access the portlet element id to find our state
0933:                String peid = ((JetspeedRunData) data).getJs_peid();
0934:                SessionState state = ((JetspeedRunData) data)
0935:                        .getPortletSessionState(peid);
0936:
0937:                // collect & save in state (for possible form re-draw)
0938:                // String pagesize = StringUtil.trimToZero(data.getParameters().getString(FORM_PAGESIZE));
0939:                // state.setAttribute(STATE_OPTION_PAGESIZE, pagesize);
0940:                String open = data.getParameters().getString(FORM_OPEN);
0941:                state.setAttribute(STATE_OPTION_OPEN, open);
0942:                String alias = StringUtil.trimToNull(data.getParameters()
0943:                        .getString(FORM_ALIAS));
0944:                state.setAttribute(STATE_OPTION_ALIAS, alias);
0945:
0946:                MailArchiveChannel channel = null;
0947:                try {
0948:                    channel = MailArchiveService
0949:                            .getMailArchiveChannel((String) state
0950:                                    .getAttribute(STATE_CHANNEL_REF));
0951:                } catch (Exception e) {
0952:                    addAlert(state, rb.getString("cannot1"));
0953:                }
0954:
0955:                // first validate - page size
0956:                // int size = 0;
0957:                // try
0958:                // {
0959:                // size = Integer.parseInt(pagesize);
0960:                // if (size <= 0)
0961:                // {
0962:                // addAlert(state,rb.getString("pagsiz"));
0963:                // }
0964:                // }
0965:                // catch (Exception any)
0966:                // {
0967:                // addAlert(state, rb.getString("pagsiz"));
0968:                // }
0969:
0970:                // validate the email alias
0971:                if (alias != null) {
0972:                    if (!Validator.checkEmailLocal(alias)) {
0973:                        addAlert(state, rb.getString("theemaali"));
0974:                    }
0975:                }
0976:
0977:                // make sure we can get to the channel
0978:                MailArchiveChannelEdit edit = null;
0979:                try {
0980:                    edit = (MailArchiveChannelEdit) MailArchiveService
0981:                            .editChannel(channel.getReference());
0982:                } catch (Exception any) {
0983:                    addAlert(state, rb.getString("theemaarc"));
0984:                }
0985:
0986:                // if all is well, save
0987:                if (state.getAttribute(STATE_MESSAGE) == null) {
0988:                    // get any current alias for this channel
0989:                    List all = AliasService.getAliases((String) state
0990:                            .getAttribute(STATE_CHANNEL_REF), 1, 1);
0991:                    String curAlias = null;
0992:                    if (!all.isEmpty())
0993:                        curAlias = ((Alias) all.get(0)).getId();
0994:
0995:                    // alias from the form
0996:                    if (StringUtil.different(curAlias, alias)) {
0997:                        boolean ok = false;
0998:
0999:                        // see if this alias exists
1000:                        if (alias != null) {
1001:                            try {
1002:                                String target = AliasService.getTarget(alias);
1003:
1004:                                // if so, is it this channel?
1005:                                ok = target.equals(channel.getReference());
1006:                            } catch (IdUnusedException e) {
1007:                                // not in use
1008:                                ok = true;
1009:                            }
1010:                        } else {
1011:                            // no alias is desired
1012:                            ok = true;
1013:                        }
1014:
1015:                        if (ok) {
1016:                            try {
1017:                                // first, clear any alias set to this channel
1018:                                AliasService.removeTargetAliases(channel
1019:                                        .getReference());
1020:
1021:                                // then add the desired alias
1022:                                if (alias != null) {
1023:                                    AliasService.setAlias(alias, channel
1024:                                            .getReference());
1025:                                }
1026:                            } catch (Exception any) {
1027:                                addAlert(state, rb.getString("theemaali2"));
1028:                            }
1029:                        } else {
1030:                            addAlert(state, rb.getString("theemaali3"));
1031:                        }
1032:                    }
1033:
1034:                    // if the alias saving went well, go on to the rest
1035:                    if (state.getAttribute(STATE_MESSAGE) == null) {
1036:                        // update the channel for open (if changed)
1037:                        boolean ss = new Boolean(open).booleanValue();
1038:                        if (channel.getOpen() != ss) {
1039:                            edit.setOpen(ss);
1040:                            MailArchiveService.commitChannel(edit);
1041:                        } else {
1042:                            MailArchiveService.cancelChannel(edit);
1043:                        }
1044:                        edit = null;
1045:
1046:                        // // update the tool config & state for page size (if different)
1047:                        // if (size != ((Integer) state.getAttribute(STATE_PAGESIZE)).intValue())
1048:                        // {
1049:                        // state.setAttribute(STATE_PAGESIZE, new Integer(size));
1050:                        // Placement placement = ToolManager.getCurrentPlacement();
1051:                        // placement.getPlacementConfig().setProperty(PARAM_PAGESIZE, Integer.toString(size));
1052:                        //		
1053:                        // // commit the options change
1054:                        // saveOptions();
1055:                        // }
1056:                        // else
1057:                        // {
1058:                        // cancelOptions();
1059:                        // }
1060:
1061:                        // we are done with customization... back to the main (list) mode
1062:                        state.setAttribute(STATE_MODE, "list");
1063:
1064:                        // clear state temps.
1065:                        state.removeAttribute(STATE_OPTION_PAGESIZE);
1066:                        state.removeAttribute(STATE_OPTION_OPEN);
1067:                        state.removeAttribute(STATE_OPTION_ALIAS);
1068:
1069:                        // re-enable auto-updates when going back to list mode
1070:                        enableObserver(state);
1071:                    }
1072:                }
1073:
1074:                // before leaving, make sure the edit was cleared
1075:                if (edit != null) {
1076:                    MailArchiveService.cancelChannel(edit);
1077:                    edit = null;
1078:                }
1079:
1080:            } // doUpdate
1081:
1082:            /**
1083:             * doCancel called for form input tags type="submit" named="eventSubmit_doCancel" cancel the options process
1084:             */
1085:            public void doCancel(RunData data, Context context) {
1086:                // access the portlet element id to find our state
1087:                String peid = ((JetspeedRunData) data).getJs_peid();
1088:                SessionState state = ((JetspeedRunData) data)
1089:                        .getPortletSessionState(peid);
1090:
1091:                // cancel the options
1092:                cancelOptions();
1093:
1094:                // we are done with customization... back to the main (list) mode
1095:                state.setAttribute(STATE_MODE, "list");
1096:
1097:                // clear state temps.
1098:                state.removeAttribute(STATE_OPTION_PAGESIZE);
1099:                state.removeAttribute(STATE_OPTION_OPEN);
1100:                state.removeAttribute(STATE_OPTION_ALIAS);
1101:
1102:                // re-enable auto-updates when going back to list mode
1103:                enableObserver(state);
1104:
1105:            } // doCancel
1106:
1107:            /**
1108:             * Fire up the permissions editor
1109:             */
1110:            public void doPermissions(RunData data, Context context) {
1111:                // get into helper mode with this helper tool
1112:                startHelper(data.getRequest(), "sakai.permissions.helper");
1113:
1114:                SessionState state = ((JetspeedRunData) data)
1115:                        .getPortletSessionState(((JetspeedRunData) data)
1116:                                .getJs_peid());
1117:
1118:                String channelRefStr = (String) state
1119:                        .getAttribute(STATE_CHANNEL_REF);
1120:                Reference channelRef = EntityManager
1121:                        .newReference(channelRefStr);
1122:                String siteRef = SiteService.siteReference(channelRef
1123:                        .getContext());
1124:
1125:                // setup for editing the permissions of the site for this tool, using the roles of this site, too
1126:                state.setAttribute(PermissionsHelper.TARGET_REF, siteRef);
1127:
1128:                // ... with this description
1129:                state.setAttribute(PermissionsHelper.DESCRIPTION, rb
1130:                        .getString("setperm")
1131:                        + SiteService.getSiteDisplay(channelRef.getContext()));
1132:
1133:                // ... showing only locks that are prpefixed with this
1134:                state.setAttribute(PermissionsHelper.PREFIX, "mail.");
1135:
1136:            } // doPermissions
1137:
1138:        } // MailboxAction
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.