Source Code Cross Referenced for Session.java in  » J2EE » wicket » wicket » 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 » J2EE » wicket » wicket 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: Session.java 5063 2006-03-21 11:21:19 -0800 (Tue, 21 Mar 2006)
0003:         * jonathanlocke $ $Revision: 529917 $ $Date: 2006-03-21 11:21:19 -0800 (Tue, 21
0004:         * Mar 2006) $
0005:         * 
0006:         * ==============================================================================
0007:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
0008:         * use this file except in compliance with the License. You may obtain a copy of
0009:         * the License at
0010:         * 
0011:         * http://www.apache.org/licenses/LICENSE-2.0
0012:         * 
0013:         * Unless required by applicable law or agreed to in writing, software
0014:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0015:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0016:         * License for the specific language governing permissions and limitations under
0017:         * the License.
0018:         */
0019:        package wicket;
0020:
0021:        import java.io.Serializable;
0022:        import java.util.ArrayList;
0023:        import java.util.HashMap;
0024:        import java.util.Iterator;
0025:        import java.util.LinkedList;
0026:        import java.util.List;
0027:        import java.util.Locale;
0028:        import java.util.Map;
0029:        import java.util.Map.Entry;
0030:
0031:        import org.apache.commons.logging.Log;
0032:        import org.apache.commons.logging.LogFactory;
0033:
0034:        import wicket.application.IClassResolver;
0035:        import wicket.authorization.IAuthorizationStrategy;
0036:        import wicket.feedback.FeedbackMessage;
0037:        import wicket.feedback.FeedbackMessages;
0038:        import wicket.request.ClientInfo;
0039:        import wicket.session.ISessionStore;
0040:        import wicket.util.concurrent.CopyOnWriteArrayList;
0041:        import wicket.util.convert.IConverter;
0042:        import wicket.util.lang.Objects;
0043:        import wicket.util.string.Strings;
0044:        import wicket.util.time.Duration;
0045:
0046:        /**
0047:         * Holds information about a user session, including some fixed number of most
0048:         * recent pages (and all their nested component information).
0049:         * <ul>
0050:         * <li><b>Access via RequestCycle </b>- The Session for a {@link RequestCycle}
0051:         * can be retrieved by calling {@link RequestCycle#getSession()}.
0052:         * 
0053:         * <li><b>Access via Component </b>- If a RequestCycle object is not available,
0054:         * the Session can be retrieved for a Component by calling
0055:         * {@link Component#getSession()}. As currently implemented, each Component
0056:         * does not itself have a reference to the session that contains it. However,
0057:         * the Page component at the root of the containment hierarchy does have a
0058:         * reference to the Session that holds the Page. So
0059:         * {@link Component#getSession()} traverses the component hierarchy to the root
0060:         * Page and then calls {@link Page#getSession()}.
0061:         * 
0062:         * <li><b>Access via Thread Local </b>- In the odd case where neither a
0063:         * RequestCycle nor a Component is available, the currently active Session for
0064:         * the calling thread can be retrieved by calling the static method
0065:         * Session.get(). This last form should only be used if the first two forms
0066:         * cannot be used since thread local access can involve a potentially more
0067:         * expensive hash map lookup.
0068:         * 
0069:         * <li><b>Locale </b>- A session has a Locale property to support localization.
0070:         * The Locale for a session can be set by calling
0071:         * {@link Session#setLocale(Locale)}. The Locale for a Session determines how
0072:         * localized resources are found and loaded.
0073:         * 
0074:         * <li><b>Style </b>- Besides having an appearance based on locale, resources
0075:         * can also have different looks in the same locale (a.k.a. "skins"). The style
0076:         * for a session determines the look which is used within the appopriate locale.
0077:         * The session style ("skin") can be set with the setStyle() method.
0078:         * 
0079:         * <li><b>Resource Loading </b>- Based on the Session locale and style,
0080:         * searching for resources occurs in the following order (where sourcePath is
0081:         * set via the ApplicationSettings object for the current Application, and style
0082:         * and locale are Session properties):
0083:         * <ul>
0084:         * 1. [sourcePath]/name[style][locale].[extension] <br>
0085:         * 2. [sourcePath]/name[locale].[extension] <br>
0086:         * 3. [sourcePath]/name[style].[extension] <br>
0087:         * 4. [sourcePath]/name.[extension] <br>
0088:         * 5. [classPath]/name[style][locale].[extension] <br>
0089:         * 6. [classPath]/name[locale].[extension] <br>
0090:         * 7. [classPath]/name[style].[extension] <br>
0091:         * 8. [classPath]/name.[extension] <br>
0092:         * </ul>
0093:         * 
0094:         * <li><b>Session Properties </b>- Arbitrary objects can be attached to a
0095:         * Session by installing a session factory on your Application class which
0096:         * creates custom Session subclasses that have typesafe properties specific to
0097:         * the application (see {@link Application} for details). To discourage
0098:         * non-typesafe access to Session properties, no setProperty() or getProperty()
0099:         * method is provided. In a clustered environment, you should take care to call
0100:         * the dirty() method when you change a property or youre own. This way the
0101:         * session will be reset again in the http session so that the http session
0102:         * knows the session is changed.
0103:         * 
0104:         * <li><b>Class Resolver </b>- Sessions have a class resolver (
0105:         * {@link IClassResolver}) implementation that is used to locate classes for
0106:         * components such as pages.
0107:         * 
0108:         * <li><b>Page Factory </b>- A pluggable implementation of {@link IPageFactory}
0109:         * is used to instantiate pages for the session.
0110:         * 
0111:         * <li><b>Removal </b>- Pages can be removed from the Session forcibly by
0112:         * calling remove(Page) or removeAll(), although such an action should rarely be
0113:         * necessary.
0114:         * 
0115:         * <li><b>Flash Messages</b>- Flash messages are messages that are stored in
0116:         * session and are removed after they are displayed to the user. Session acts as
0117:         * a store for these messages because they can last across requests.
0118:         * 
0119:         * @author Jonathan Locke
0120:         * @author Eelco Hillenius
0121:         * @author Igor Vaynberg (ivaynberg)
0122:         */
0123:        public abstract class Session implements  Serializable {
0124:            private static final long serialVersionUID = 1L;
0125:
0126:            /** Name of session attribute under which this session is stored */
0127:            public static final String SESSION_ATTRIBUTE_NAME = "session";
0128:
0129:            /** Prefix for attributes holding page map entries */
0130:            static final String pageMapEntryAttributePrefix = "p:";
0131:
0132:            /** Thread-local current session. */
0133:            private static final ThreadLocal current = new ThreadLocal();
0134:
0135:            /** A store for dirty objects for one request */
0136:            private static final ThreadLocal dirtyObjects = new ThreadLocal();
0137:
0138:            /** Logging object */
0139:            private static final Log log = LogFactory.getLog(Session.class);
0140:
0141:            /** Attribute prefix for page maps stored in the session */
0142:            private static final String pageMapAttributePrefix = "m:";
0143:
0144:            /**
0145:             * Cached instance of agent info which is typically designated by calling
0146:             * {@link RequestCycle#newClientInfo()}.
0147:             */
0148:            private ClientInfo clientInfo;
0149:
0150:            /** The converter instance. */
0151:            private transient IConverter converter;
0152:
0153:            /** True if session state has been changed */
0154:            private transient boolean dirty = false;
0155:
0156:            /** The locale to use when loading resources for this session. */
0157:            private Locale locale;
0158:
0159:            /** A number to generate names for auto create pagemaps */
0160:            private int autoCreatePageMapCounter = 0;
0161:
0162:            /** A linked list for last used pagemap queue */
0163:            private LinkedList/* <PageMap> */usedPageMaps = new LinkedList();
0164:
0165:            /** Any special "skin" style to use when loading resources. */
0166:            private String style;
0167:
0168:            /** feedback messages */
0169:            private FeedbackMessages feedbackMessages = new FeedbackMessages(
0170:                    new CopyOnWriteArrayList());
0171:
0172:            private transient Map pageMapsUsedInRequest;
0173:
0174:            /** cached id because you can't access the id after session unbound */
0175:            private String id = null;
0176:
0177:            /**
0178:             * Temporary instance of the session store. Should be set on each request as
0179:             * it is not supposed to go in the session.
0180:             */
0181:            private transient ISessionStore sessionStore;
0182:
0183:            /** Application level meta data. */
0184:            private MetaDataEntry[] metaData;
0185:
0186:            /**
0187:             * Visitor interface for visiting page maps
0188:             * 
0189:             * @author Jonathan Locke
0190:             */
0191:            public static interface IPageMapVisitor {
0192:                /**
0193:                 * @param pageMap
0194:                 *            The page map
0195:                 */
0196:                public void pageMap(final PageMap pageMap);
0197:            }
0198:
0199:            /**
0200:             * Get the session for the calling thread.
0201:             * 
0202:             * @return Session for calling thread
0203:             */
0204:            public static Session get() {
0205:                final Session session = (Session) current.get();
0206:                if (session == null) {
0207:                    throw new WicketRuntimeException(
0208:                            "there is no session attached to current thread "
0209:                                    + Thread.currentThread().getName());
0210:                }
0211:                return session;
0212:            }
0213:
0214:            /**
0215:             * Checks if the <code>Session</code> threadlocal is set in this thread
0216:             * 
0217:             * @return true if {@link Session#get()} can return the instance of session,
0218:             *         false otherwise
0219:             */
0220:            public static boolean exists() {
0221:                return current.get() != null;
0222:            }
0223:
0224:            /**
0225:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0226:             * <p>
0227:             * Sets session for calling thread.
0228:             * 
0229:             * @param session
0230:             *            The session
0231:             */
0232:            public static void set(final Session session) {
0233:                if (session == null) {
0234:                    throw new IllegalArgumentException(
0235:                            "Argument session can not be null");
0236:                }
0237:                current.set(session);
0238:            }
0239:
0240:            /**
0241:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0242:             * <p>
0243:             * Clears the session for calling thread.
0244:             * 
0245:             */
0246:            public static void unset() {
0247:                current.set(null);
0248:            }
0249:
0250:            /**
0251:             * Constructor.
0252:             * 
0253:             * @param application
0254:             *            The application that this is a session of
0255:             */
0256:            protected Session(final Application application) {
0257:                // Set locale to default locale
0258:                setLocale(application.getApplicationSettings()
0259:                        .getDefaultLocale());
0260:            }
0261:
0262:            /**
0263:             * Removes all pages from the session. Although this method should rarely be
0264:             * needed, it is available (possibly for security reasons).
0265:             */
0266:            public final void clear() {
0267:                visitPageMaps(new IPageMapVisitor() {
0268:                    public void pageMap(PageMap pageMap) {
0269:                        pageMap.clear();
0270:                    }
0271:                });
0272:            }
0273:
0274:            /**
0275:             * Get the application that is currently working with this session.
0276:             * 
0277:             * @return Returns the application.
0278:             */
0279:            public final Application getApplication() {
0280:                return Application.get();
0281:            }
0282:
0283:            /**
0284:             * @return The authorization strategy for this session
0285:             */
0286:            public IAuthorizationStrategy getAuthorizationStrategy() {
0287:                return getApplication().getSecuritySettings()
0288:                        .getAuthorizationStrategy();
0289:            }
0290:
0291:            /**
0292:             * @return The class resolver for this Session
0293:             */
0294:            public final IClassResolver getClassResolver() {
0295:                return getApplication().getApplicationSettings()
0296:                        .getClassResolver();
0297:            }
0298:
0299:            /**
0300:             * Gets the client info object for this session. This method lazily gets the
0301:             * new agent info object for this session. It uses any cached or set ({@link #setClientInfo(ClientInfo)})
0302:             * client info object or uses {@link RequestCycle#newClientInfo()} to get
0303:             * the info object based on the current request when no client info object
0304:             * was set yet, and then caches the returned object; we can expect the
0305:             * client to stay the same for the whole session, and implementations of
0306:             * {@link RequestCycle#newClientInfo()} might be relatively expensive.
0307:             * 
0308:             * @return the client info object based on this request
0309:             */
0310:            public ClientInfo getClientInfo() {
0311:                if (clientInfo == null) {
0312:                    this .clientInfo = RequestCycle.get().newClientInfo();
0313:                }
0314:                return clientInfo;
0315:            }
0316:
0317:            /**
0318:             * @return The default page map
0319:             */
0320:            public final PageMap getDefaultPageMap() {
0321:                return pageMapForName(PageMap.DEFAULT_NAME, true);
0322:            }
0323:
0324:            /**
0325:             * Gets the unique id for this session from the underlying SessionStore
0326:             * 
0327:             * @return The unique id for this session
0328:             */
0329:            public final String getId() {
0330:                if (id == null) {
0331:                    id = getSessionStore().getSessionId(
0332:                            RequestCycle.get().getRequest());
0333:
0334:                    // we have one?
0335:                    if (id != null) {
0336:                        dirty();
0337:                    }
0338:                }
0339:                return id;
0340:            }
0341:
0342:            /**
0343:             * Get this session's locale.
0344:             * 
0345:             * @return This session's locale
0346:             */
0347:            public Locale getLocale() {
0348:                return locale;
0349:            }
0350:
0351:            /**
0352:             * Gets metadata for this session using the given key.
0353:             * 
0354:             * @param key
0355:             *            The key for the data
0356:             * @return The metadata
0357:             * @see MetaDataKey
0358:             */
0359:            public final Serializable getMetaData(final MetaDataKey key) {
0360:                return key.get(metaData);
0361:            }
0362:
0363:            /**
0364:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0365:             * 
0366:             * Get the page for the given path.
0367:             * 
0368:             * @param pageMapName
0369:             *            The name of the page map where the page is
0370:             * @param path
0371:             *            Component path
0372:             * @param versionNumber
0373:             *            The version of the page required
0374:             * @return The page based on the first path component (the page id), or null
0375:             *         if the requested version of the page cannot be found.
0376:             */
0377:            public final Page getPage(final String pageMapName,
0378:                    final String path, final int versionNumber) {
0379:                if (log.isDebugEnabled()) {
0380:                    log.debug("Getting page [path = " + path
0381:                            + ", versionNumber = " + versionNumber + "]");
0382:                }
0383:
0384:                // Get page map by name, creating the default page map automatically
0385:                PageMap pageMap = pageMapForName(pageMapName,
0386:                        pageMapName == PageMap.DEFAULT_NAME);
0387:                if (pageMap != null) {
0388:                    synchronized (usedPageMaps) // get a lock so be sure that only one
0389:                    // is made
0390:                    {
0391:                        if (pageMapsUsedInRequest == null) {
0392:                            pageMapsUsedInRequest = new HashMap(3);
0393:                        }
0394:                    }
0395:                    synchronized (pageMapsUsedInRequest) {
0396:                        long startTime = System.currentTimeMillis();
0397:
0398:                        // TODO For now only use the setting. Might be extended with
0399:                        // something overridable on request/ page/ request target level
0400:                        // later
0401:                        Duration timeout = Application.get()
0402:                                .getRequestCycleSettings().getTimeout();
0403:
0404:                        // Get page entry for id and version
0405:                        Thread t = (Thread) pageMapsUsedInRequest.get(pageMap);
0406:                        while (t != null && t != Thread.currentThread()) {
0407:                            try {
0408:                                pageMapsUsedInRequest.wait(timeout
0409:                                        .getMilliseconds());
0410:                            } catch (InterruptedException ex) {
0411:                                throw new WicketRuntimeException(ex);
0412:                            }
0413:                            t = (Thread) pageMapsUsedInRequest.get(pageMap);
0414:                            if (t != null
0415:                                    && t != Thread.currentThread()
0416:                                    && (startTime + timeout.getMilliseconds()) < System
0417:                                            .currentTimeMillis()) {
0418:                                // if it is still not the right thread..
0419:                                // This either points to long running code (a report
0420:                                // page?) or a deadlock or such
0421:                                throw new WicketRuntimeException(
0422:                                        "After "
0423:                                                + timeout
0424:                                                + " the Pagemap "
0425:                                                + pageMapName
0426:                                                + " is still locked by: "
0427:                                                + t
0428:                                                + ", giving up trying to get the page for path: "
0429:                                                + path);
0430:                            }
0431:                        }
0432:                        pageMapsUsedInRequest.put(pageMap, Thread
0433:                                .currentThread());
0434:                        final String id = Strings.firstPathComponent(path,
0435:                                Component.PATH_SEPARATOR);
0436:                        Page page = pageMap.get(Integer.parseInt(id),
0437:                                versionNumber);
0438:                        if (page == null) {
0439:                            pageMapsUsedInRequest.remove(pageMap);
0440:                            pageMapsUsedInRequest.notifyAll();
0441:                        }
0442:                        return page;
0443:                    }
0444:                }
0445:                return null;
0446:            }
0447:
0448:            /**
0449:             * @return The page factory for this session
0450:             */
0451:            public final IPageFactory getPageFactory() {
0452:                return getApplication().getSessionSettings().getPageFactory();
0453:            }
0454:
0455:            /**
0456:             * @param page
0457:             *            The page, or null if no page context is available
0458:             * @return The page factory for the page, or the default page factory if
0459:             *         page was null
0460:             */
0461:            public final IPageFactory getPageFactory(final Page page) {
0462:                if (page != null) {
0463:                    return page.getPageFactory();
0464:                }
0465:                return getPageFactory();
0466:            }
0467:
0468:            /**
0469:             * Gets a page map for the given name, automatically creating it if need be.
0470:             * 
0471:             * @param pageMapName
0472:             *            Name of page map, or null for default page map
0473:             * @param autoCreate
0474:             *            True if the page map should be automatically created if it
0475:             *            does not exist
0476:             * @return PageMap for name
0477:             */
0478:            public final PageMap pageMapForName(String pageMapName,
0479:                    final boolean autoCreate) {
0480:                PageMap pageMap = (PageMap) getAttribute(attributeForPageMapName(pageMapName));
0481:                if (pageMap == null && autoCreate) {
0482:                    pageMap = newPageMap(pageMapName);
0483:                }
0484:                return pageMap;
0485:            }
0486:
0487:            /**
0488:             * Automatically creates a page map, giving it a session unique name.
0489:             * 
0490:             * @return Created PageMap
0491:             */
0492:            public synchronized final PageMap createAutoPageMap() {
0493:                return newPageMap(createAutoPageMapName());
0494:            }
0495:
0496:            /**
0497:             * With this call you can create a pagemap name but not create the pagemap
0498:             * itself already. It will give the first pagemap name where it couldn't
0499:             * find a current pagemap for.
0500:             * 
0501:             * It will return the same name if you call it 2 times in a row.
0502:             * 
0503:             * @return The created pagemap name
0504:             */
0505:            public synchronized final String createAutoPageMapName() {
0506:                String name = "wicket-" + autoCreatePageMapCounter;
0507:                PageMap pm = pageMapForName(name, false);
0508:                while (pm != null) {
0509:                    autoCreatePageMapCounter++;
0510:                    name = "wicket-" + autoCreatePageMapCounter;
0511:                    pm = pageMapForName(name, false);
0512:                }
0513:                return name;
0514:            }
0515:
0516:            /**
0517:             * @return A list of all PageMaps in this session.
0518:             */
0519:            public final List getPageMaps() {
0520:                final List list = new ArrayList();
0521:                for (final Iterator iterator = getAttributeNames().iterator(); iterator
0522:                        .hasNext();) {
0523:                    final String attribute = (String) iterator.next();
0524:                    if (attribute.startsWith(pageMapAttributePrefix)) {
0525:                        list.add(getAttribute(attribute));
0526:                    }
0527:                }
0528:                return list;
0529:            }
0530:
0531:            /**
0532:             * @return Size of this session, including all the pagemaps it contains
0533:             */
0534:            public final long getSizeInBytes() {
0535:                long size = Objects.sizeof(this );
0536:                for (final Iterator iterator = getPageMaps().iterator(); iterator
0537:                        .hasNext();) {
0538:                    final PageMap pageMap = (PageMap) iterator.next();
0539:                    size += pageMap.getSizeInBytes();
0540:                }
0541:                return size;
0542:            }
0543:
0544:            /**
0545:             * Get the style (see {@link wicket.Session}).
0546:             * 
0547:             * @return Returns the style (see {@link wicket.Session})
0548:             */
0549:            public final String getStyle() {
0550:                return style;
0551:            }
0552:
0553:            /**
0554:             * Set the session for each PageMap
0555:             */
0556:            public final void init() {
0557:                // Set session on each page map
0558:                visitPageMaps(new IPageMapVisitor() {
0559:                    public void pageMap(PageMap pageMap) {
0560:                        if (log.isDebugEnabled()) {
0561:                            log
0562:                                    .debug("updateSession(): Attaching session to PageMap "
0563:                                            + pageMap);
0564:                        }
0565:                        pageMap.setSession(Session.this );
0566:                    }
0567:                });
0568:            }
0569:
0570:            /**
0571:             * Invalidates this session.
0572:             */
0573:            public void invalidate() {
0574:                getSessionStore().invalidate(RequestCycle.get().getRequest());
0575:            }
0576:
0577:            /**
0578:             * Creates a new page map with a given name
0579:             * 
0580:             * @param name
0581:             *            The name for the new page map
0582:             * @return The newly created page map
0583:             */
0584:            public final PageMap newPageMap(final String name) {
0585:                // Check that session doesn't have too many page maps already
0586:                final int maxPageMaps = getApplication().getSessionSettings()
0587:                        .getMaxPageMaps();
0588:                if (usedPageMaps.size() >= maxPageMaps) {
0589:                    PageMap pm = (PageMap) usedPageMaps.getFirst();
0590:                    pm.remove();
0591:                }
0592:
0593:                // Create new page map
0594:                final PageMap pageMap = new PageMap(name, this );
0595:                setAttribute(attributeForPageMapName(name), pageMap);
0596:                dirty();
0597:                return pageMap;
0598:            }
0599:
0600:            /**
0601:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0602:             * 
0603:             * Creates a new RequestCycle for the given request and response using the
0604:             * session's request cycle factory.
0605:             * 
0606:             * @param request
0607:             *            The request
0608:             * @param response
0609:             *            The response
0610:             * @return The new request cycle.
0611:             */
0612:            public final RequestCycle newRequestCycle(final Request request,
0613:                    final Response response) {
0614:                return getRequestCycleFactory().newRequestCycle(this , request,
0615:                        response);
0616:            }
0617:
0618:            /**
0619:             * @param pageMap
0620:             *            Page map to remove
0621:             */
0622:            public final void removePageMap(final PageMap pageMap) {
0623:                usedPageMaps.remove(pageMap);
0624:                removeAttribute(attributeForPageMapName(pageMap.getName()));
0625:                dirty();
0626:            }
0627:
0628:            /**
0629:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0630:             * <p>
0631:             * Sets the application that this session is associated with.
0632:             * 
0633:             * @param application
0634:             *            The application
0635:             */
0636:            public final void setApplication(final Application application) {
0637:            }
0638:
0639:            /**
0640:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0641:             * <p>
0642:             * Sets the client info object for this session. This will only work when
0643:             * {@link #getClientInfo()} is not overriden.
0644:             * 
0645:             * @param clientInfo
0646:             *            the client info object
0647:             */
0648:            public final void setClientInfo(ClientInfo clientInfo) {
0649:                this .clientInfo = clientInfo;
0650:                dirty();
0651:            }
0652:
0653:            /**
0654:             * Set the locale for this session.
0655:             * 
0656:             * @param locale
0657:             *            New locale
0658:             */
0659:            public final void setLocale(final Locale locale) {
0660:                if (locale == null) {
0661:                    throw new IllegalArgumentException(
0662:                            "Parameter 'locale' must not be null");
0663:                }
0664:                this .locale = locale;
0665:                this .converter = null;
0666:                dirty();
0667:            }
0668:
0669:            /**
0670:             * Sets the metadata for this session using the given key. If the metadata
0671:             * object is not of the correct type for the metadata key, an
0672:             * IllegalArgumentException will be thrown. For information on creating
0673:             * MetaDataKeys, see {@link MetaDataKey}.
0674:             * 
0675:             * @param key
0676:             *            The singleton key for the metadata
0677:             * @param object
0678:             *            The metadata object
0679:             * @throws IllegalArgumentException
0680:             * @see MetaDataKey
0681:             */
0682:            public final void setMetaData(final MetaDataKey key,
0683:                    final Serializable object) {
0684:                metaData = key.set(metaData, object);
0685:            }
0686:
0687:            /**
0688:             * Set the style (see {@link wicket.Session}).
0689:             * 
0690:             * @param style
0691:             *            The style to set.
0692:             * @return the Session object
0693:             */
0694:            public final Session setStyle(final String style) {
0695:                this .style = style;
0696:                dirty();
0697:                return this ;
0698:            }
0699:
0700:            /**
0701:             * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
0702:             * <p>
0703:             * The page will be 'touched' in the session. If it wasn't added yet to the
0704:             * pagemap, it will be added to the page map else it will set this page to
0705:             * the front.
0706:             * 
0707:             * If another page was removed because of this it will be cleaned up.
0708:             * 
0709:             * @param page
0710:             */
0711:            public final void touch(Page page) {
0712:                // Touch the page in its pagemap.
0713:                page.getPageMap().put(page);
0714:            }
0715:
0716:            /**
0717:             * @param visitor
0718:             *            The visitor to call at each Page in this PageMap.
0719:             */
0720:            public final void visitPageMaps(final IPageMapVisitor visitor) {
0721:                for (final Iterator iterator = getAttributeNames().iterator(); iterator
0722:                        .hasNext();) {
0723:                    final String attribute = (String) iterator.next();
0724:                    if (attribute.startsWith(pageMapAttributePrefix)) {
0725:                        visitor.pageMap((PageMap) getAttribute(attribute));
0726:                    }
0727:                }
0728:            }
0729:
0730:            /**
0731:             * Registers an informational feedback message for this session
0732:             * 
0733:             * @param message
0734:             *            The feedback message
0735:             */
0736:            public final void info(final String message) {
0737:                addFeedbackMessage(message, FeedbackMessage.INFO);
0738:            }
0739:
0740:            /**
0741:             * Registers a warning feedback message for this session
0742:             * 
0743:             * @param message
0744:             *            The feedback message
0745:             */
0746:            public final void warn(final String message) {
0747:                addFeedbackMessage(message, FeedbackMessage.WARNING);
0748:            }
0749:
0750:            /**
0751:             * Registers an error feedback message for this session
0752:             * 
0753:             * @param message
0754:             *            The feedback message
0755:             */
0756:            public final void error(final String message) {
0757:                addFeedbackMessage(message, FeedbackMessage.ERROR);
0758:            }
0759:
0760:            /**
0761:             * Gets feedback messages stored in session
0762:             * 
0763:             * @return unmodifiable list of feedback messages
0764:             */
0765:            public final FeedbackMessages getFeedbackMessages() {
0766:                return feedbackMessages;
0767:            }
0768:
0769:            /**
0770:             * Gets the converter instance. This method returns the cached converter for
0771:             * the current locale. Whenever the locale is changed, the cached value is
0772:             * cleared and the converter will be recreated for the new locale on a next
0773:             * request.
0774:             * 
0775:             * @return the converter
0776:             */
0777:            public final IConverter getConverter() {
0778:                if (converter == null) {
0779:                    // Let the factory create a new converter
0780:                    converter = getApplication().getApplicationSettings()
0781:                            .getConverterFactory().newConverter(getLocale());
0782:                }
0783:                return converter;
0784:            }
0785:
0786:            /**
0787:             * Adds a feedback message to the list of messages
0788:             * 
0789:             * @param message
0790:             * @param level
0791:             * 
0792:             */
0793:            private void addFeedbackMessage(String message, int level) {
0794:                getFeedbackMessages().add(null, message, level);
0795:                dirty();
0796:            }
0797:
0798:            /**
0799:             * Any detach logic for session subclasses. This is called on the end of
0800:             * handling a request, when the RequestCycle is about to be detached from
0801:             * the current thread.
0802:             */
0803:            protected void detach() {
0804:            }
0805:
0806:            /**
0807:             * Marks session state as dirty
0808:             */
0809:            protected final void dirty() {
0810:                this .dirty = true;
0811:            }
0812:
0813:            /**
0814:             * Gets the attribute value with the given name
0815:             * 
0816:             * @param name
0817:             *            The name of the attribute to store
0818:             * @return The value of the attribute
0819:             */
0820:            protected final Object getAttribute(final String name) {
0821:                RequestCycle cycle = RequestCycle.get();
0822:                if (cycle != null) {
0823:                    return getSessionStore().getAttribute(cycle.getRequest(),
0824:                            name);
0825:                }
0826:                return null;
0827:            }
0828:
0829:            /**
0830:             * @return List of attributes for this session
0831:             */
0832:            protected final List getAttributeNames() {
0833:                RequestCycle cycle = RequestCycle.get();
0834:                if (cycle != null) {
0835:                    return getSessionStore().getAttributeNames(
0836:                            cycle.getRequest());
0837:                }
0838:                return null;
0839:            }
0840:
0841:            /**
0842:             * @return Request cycle factory for this kind of session.
0843:             */
0844:            protected abstract IRequestCycleFactory getRequestCycleFactory();
0845:
0846:            /**
0847:             * Gets the session store.
0848:             * 
0849:             * @return the session store
0850:             */
0851:            protected ISessionStore getSessionStore() {
0852:                if (sessionStore == null) {
0853:                    sessionStore = getApplication().getSessionStore();
0854:                }
0855:                return sessionStore;
0856:            }
0857:
0858:            /**
0859:             * Removes the attribute with the given name.
0860:             * 
0861:             * @param name
0862:             *            the name of the attribute to remove
0863:             */
0864:            protected final void removeAttribute(String name) {
0865:                RequestCycle cycle = RequestCycle.get();
0866:                if (cycle != null) {
0867:                    getSessionStore().removeAttribute(cycle.getRequest(), name);
0868:                }
0869:            }
0870:
0871:            /**
0872:             * Adds or replaces the attribute with the given name and value.
0873:             * 
0874:             * @param name
0875:             *            The name of the attribute
0876:             * @param value
0877:             *            The value of the attribute
0878:             */
0879:            protected final void setAttribute(String name, Object value) {
0880:                RequestCycle cycle = RequestCycle.get();
0881:                if (cycle == null) {
0882:                    throw new WicketRuntimeException(
0883:                            "Can not set the attribute. No RequestCycle available");
0884:                }
0885:
0886:                ISessionStore store = getSessionStore();
0887:                Request request = cycle.getRequest();
0888:
0889:                // extra check on session binding event
0890:                if (value == this ) {
0891:                    Object current = store.getAttribute(request, name);
0892:                    if (current == null) {
0893:                        // this is a new instance. wherever it came from, bind the
0894:                        // session now
0895:                        store.bind(request, (Session) value);
0896:                    }
0897:                }
0898:
0899:                // Set the actual attribute
0900:                store.setAttribute(request, name, value);
0901:            }
0902:
0903:            /**
0904:             * Updates the session, e.g. for replication purposes.
0905:             */
0906:            protected void update() {
0907:                // If state is dirty
0908:                if (dirty) {
0909:                    if (log.isDebugEnabled()) {
0910:                        log.debug("update: Session is dirty.  Replicating.");
0911:                    }
0912:
0913:                    // State is no longer dirty
0914:                    this .dirty = false;
0915:
0916:                    // Set attribute.
0917:                    setAttribute(SESSION_ATTRIBUTE_NAME, this );
0918:                } else {
0919:                    if (log.isDebugEnabled()) {
0920:                        log.debug("update: Session not dirty.");
0921:                    }
0922:                }
0923:            }
0924:
0925:            /**
0926:             * Removes any rendered feedback messages as well as compacts memory. This
0927:             * method is usually called at the end of the request cycle processing.
0928:             */
0929:            final void cleanupFeedbackMessages() {
0930:                int size = feedbackMessages.size();
0931:                feedbackMessages.clearRendered();
0932:
0933:                // the session is dirty when the list of feedback messages was changed
0934:                if (size != feedbackMessages.size()) {
0935:                    dirty();
0936:                }
0937:            }
0938:
0939:            /**
0940:             * @param page
0941:             *            The page to add to dirty objects list
0942:             */
0943:            void dirtyPage(final Page page) {
0944:                List dirtyObjects = getDirtyObjectsList();
0945:                if (!dirtyObjects.contains(page)) {
0946:                    dirtyObjects.add(page);
0947:                }
0948:            }
0949:
0950:            /**
0951:             * INTERNAL API. The request cycle when detached will call this.
0952:             * 
0953:             */
0954:            final void requestDetached() {
0955:                // Go through all dirty entries, replicating any dirty objects
0956:                List dirtyObjects = (List) Session.dirtyObjects.get();
0957:                if (dirtyObjects != null) {
0958:                    for (final Iterator iterator = dirtyObjects.iterator(); iterator
0959:                            .hasNext();) {
0960:                        String attribute = null;
0961:                        Object object = iterator.next();
0962:                        if (object instanceof  Page) {
0963:                            final Page page = (Page) object;
0964:                            if (page.isStateless()) {
0965:                                // check, can it be that stateless pages where added to
0966:                                // the session?
0967:                                // and should be removed now?
0968:                                continue;
0969:                            }
0970:                            attribute = page.getPageMap().attributeForId(
0971:                                    page.getNumericId());
0972:                            if (getAttribute(attribute) == null) {
0973:                                // page removed by another thread. don't add it again.
0974:                                continue;
0975:                            }
0976:                            object = page.getPageMapEntry();
0977:                        } else if (object instanceof  PageMap) {
0978:                            attribute = attributeForPageMapName(((PageMap) object)
0979:                                    .getName());
0980:                        }
0981:
0982:                        setAttribute(attribute, object);
0983:                    }
0984:                    Session.dirtyObjects.set(null);
0985:                }
0986:                if (pageMapsUsedInRequest != null) {
0987:                    synchronized (pageMapsUsedInRequest) {
0988:                        Thread t = Thread.currentThread();
0989:                        Iterator it = pageMapsUsedInRequest.entrySet()
0990:                                .iterator();
0991:                        while (it.hasNext()) {
0992:                            Entry entry = (Entry) it.next();
0993:                            if (entry.getValue() == t) {
0994:                                it.remove();
0995:                            }
0996:                        }
0997:                        pageMapsUsedInRequest.notifyAll();
0998:                    }
0999:                }
1000:            }
1001:
1002:            /**
1003:             * @param map
1004:             *            The page map to add to dirty objects list
1005:             */
1006:            void dirtyPageMap(final PageMap map) {
1007:                if (!map.isDefault()) {
1008:                    usedPageMaps.remove(map);
1009:                    usedPageMaps.addLast(map);
1010:                }
1011:                List dirtyObjects = getDirtyObjectsList();
1012:                if (!dirtyObjects.contains(map)) {
1013:                    dirtyObjects.add(map);
1014:                }
1015:            }
1016:
1017:            /**
1018:             * @param pageMapName
1019:             *            Name of page map
1020:             * @return Session attribute holding page map
1021:             */
1022:            private final String attributeForPageMapName(
1023:                    final String pageMapName) {
1024:                return pageMapAttributePrefix + pageMapName;
1025:            }
1026:
1027:            /**
1028:             * @return The current thread dirty objects list
1029:             */
1030:            List getDirtyObjectsList() {
1031:                List list = (List) dirtyObjects.get();
1032:                if (list == null) {
1033:                    list = new ArrayList(4);
1034:                    dirtyObjects.set(list);
1035:                }
1036:                return list;
1037:            }
1038:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.