📄 requestcycle.java
字号:
* @param resourceReference * The resource reference where a url must be generated for. * @return The url for the shared resource */ public final CharSequence urlFor(final ResourceReference resourceReference) { return urlFor(resourceReference, null); } /** * Returns a URL that references a shared resource through the provided resource reference. * * @param resourceReference * The resource reference where a url must be generated for. * @param parameters * The parameters to pass to the resource. * @return The url for the shared resource */ public final CharSequence urlFor(final ResourceReference resourceReference, ValueMap parameters) { RequestParameters requestParameters = new RequestParameters(); requestParameters.setResourceKey(resourceReference.getSharedResourceKey()); if (getApplication().getResourceSettings().getAddLastModifiedTimeToResourceReferenceUrl() && !Strings.isEmpty(resourceReference.getName())) { Time time = resourceReference.lastModifiedTime(); if (time != null) { if (parameters == null) { parameters = new ValueMap(); parameters.put("wicket:lm", new Long(time.getMilliseconds())); } } } requestParameters.setParameters(parameters); return encodeUrlFor(new SharedResourceRequestTarget(requestParameters)); } /** * Checks whether no processing has been done yet and throws an exception when a client tries to * reuse this instance. */ private void checkReuse() { if (currentStep != NOT_STARTED) { detach(); throw new WicketRuntimeException( "RequestCycles are non-reusable objects. This instance (" + this + ") already executed"); } } /** * THIS METHOD IS WICKET PRIVATE API. DO NOT CALL UNLESS YOU KNOW WHAT YOU ARE DOING. Clean up * the request cycle. */ public void detach() { // clean up target stack; calling detach has effects like // NOTE: don't remove the targets as testing code might need them // furthermore, the targets will be gc-ed with this cycle too for (Iterator iter = requestTargets.iterator(); iter.hasNext();) { IRequestTarget target = (IRequestTarget)iter.next(); if (target != null) { try { target.detach(this); } catch (RuntimeException e) { log.error("there was an error cleaning up target " + target + ".", e); } } } if (automaticallyClearFeedbackMessages) { // remove any rendered and otherwise obsolete feedback messages from // the session try { if (sessionExists()) { getSession().cleanupFeedbackMessages(); } } catch (RuntimeException re) { log.error("there was an error cleaning up the feedback messages", re); } } // if we have a request logger, update that now try { IRequestLogger requestLogger = getApplication().getRequestLogger(); if (requestLogger != null) { requestLogger.requestTime((System.currentTimeMillis() - startTime)); } } catch (RuntimeException re) { log.error("there was an error in the RequestLogger ending.", re); } // let the session cleanup after a request, flushing changes etc. if (sessionExists()) { try { getSession().requestDetached(); } catch (RuntimeException re) { log.error("there was an error detaching the request from the session " + session + ".", re); } } if (getResponse() instanceof BufferedWebResponse) { try { ((BufferedWebResponse)getResponse()).filter(); } catch (RuntimeException re) { log.error("there was an error filtering the response.", re); } } try { onEndRequest(); } catch (RuntimeException e) { log.error("Exception occurred during onEndRequest", e); } try { getApplication().getSessionStore().onEndRequest(getRequest()); } catch (RuntimeException e) { log.error("Exception occurred during onEndRequest of the SessionStore", e); } // Release thread local resources try { threadDetach(); } catch (RuntimeException re) { log.error("Exception occurred during threadDetach", re); } } /** * Prepare the request cycle. */ private void prepare() { try { getApplication().getSessionStore().onBeginRequest(getRequest()); } catch (RuntimeException e) { log.error("Exception occurred during onEndRequest of the SessionStore", e); } // Event callback onBeginRequest(); } /** * Call the event processing and and respond methods on the request processor and apply * synchronization if needed. */ private final void processEventsAndRespond() { // let the processor handle/ issue any events processor.processEvents(this); // set current stage manually this time currentStep = RESPOND; // generate a response processor.respond(this); } /** * Call the event processing and and respond methods on the request processor and apply * synchronization if needed. */ private final void respond() { processor.respond(this); } /** * Safe version of {@link #getProcessor()} that throws an exception when the processor is null. * * @return the request processor */ private final IRequestCycleProcessor safeGetRequestProcessor() { IRequestCycleProcessor processor = getProcessor(); if (processor == null) { throw new WicketRuntimeException("request cycle processor must be not-null"); } return processor; } /** * @return True if a session exists for the calling thread */ private boolean sessionExists() { return Session.exists(); } /** * handle the current step in the request processing. */ private final void step() { try { switch (currentStep) { case PREPARE_REQUEST : { // prepare the request prepare(); break; } case RESOLVE_TARGET : { // resolve the target of the request using the request // parameters final IRequestTarget target = processor.resolve(this, request.getRequestParameters()); // has to result in a request target if (target == null) { throw new WicketRuntimeException( "the processor did not resolve to any request target"); } // Add (inserting at the bottom) in case before or during // target resolving one or more request targets were pushed // on the stack before this. If that is the case, they // should be handled before this requestTargets.add(0, target); break; } case PROCESS_EVENTS : { processEventsAndRespond(); break; } case RESPOND : { // generate a response respond(); break; } default : { // nothing } } } catch (AbortException e) { throw e; } catch (RuntimeException e) { if (!handlingException) { // set step manually to handle exception handlingException = true; // probably our last chance the exception can be logged. // Note that a PageExpiredException should not be logged, because // it's not an internal error if (!(e instanceof PageExpiredException)) { logRuntimeException(e); } // try to play nicely and let the request processor handle the // exception response. If that doesn't work, any runtime exception // will automatically be bubbled up if (processor != null) { processor.respond(e, this); } } else { // hmmm, we were already handling an exception! give up log.error( "unexpected exception when handling another exception: " + e.getMessage(), e); } } } /** * Loop through the processing steps starting from the current one. */ private final void steps() { try { // Arbitrary maximum number of steps final int maxSteps = 100; // Loop through steps for (int totalSteps = 0; currentStep < DONE; totalSteps++) { // There is no way to catch infinite loops since the response // step can always throw an AbstractRestartResponseException and // start the process over at the RESPOND step. So we do a sanity // check here and limit the total number of steps to an // arbitrary maximum that we consider unreasonable for working // code. if (totalSteps >= maxSteps) { throw new IllegalStateException("Request processing executed " + maxSteps + " steps, which means it is probably in an infinite loop."); } try { step(); currentStep++; } catch (AbstractRestartResponseException e) { // if a redirect exception has been issued we abort what we // were doing and begin responding to the top target on the // stack currentStep = RESPOND; } } } finally { // set step manually to clean up currentStep = DETACH_REQUEST; // clean up the request detach(); // set step manually to done currentStep = DONE; } } /** * Releases the current thread local related resources. The threadlocal of this request cycle is * reset. If we are in a 'redirect' state, we do not want to lose our messages as - e.g. when * handling a form - there's a fat chance we are coming back for the rendering of it. */ private final void threadDetach() { // Detach from session if (sessionExists()) { try { getSession().detach(); } catch (RuntimeException re) { log.error("there was an error detaching the session", re); } } if (isRedirect()) { // Since we are explicitly redirecting to a page already, we do not // want a second redirect to occur automatically setRedirect(false); } // Clear ThreadLocal reference; makes sense as this object should not be // reused current.set(null); } /** * Possibly set the page parameters. Only set when the request is resolving and the parameters * are passed into a page. * * @param parameters * the parameters to set */ final void setPageParameters(PageParameters parameters) { if (currentStep == RESOLVE_TARGET) { pageParameters = parameters; } } /** * Called when an unrecoverable runtime exception during request cycle handling occurred, which * will result in displaying a user facing error page. Clients can override this method in case * they want to customize logging. NOT called for * {@link PageExpiredException page expired exceptions}. * * @param e * the runtime exception */ protected void logRuntimeException(RuntimeException e) { log.error(e.getMessage(), e); } /** * Creates a new agent info object based on this request. Typically, this method is called once * by the session and the returned object will be cached in the session after that call; we can * expect the client to stay the same for the whole session, and implementations of * {@link #newClientInfo()} might be relatively expensive. * * @return the agent info object based on this request */ protected abstract ClientInfo newClientInfo(); /** * Called when the request cycle object is beginning its response */ protected void onBeginRequest() { } /** * Called when the request cycle object has finished its response */ protected void onEndRequest() { } /** * MetaDataEntry array. */ private MetaDataEntry[] metaData; /** * Sets the metadata for this request cycle using the given key. If the metadata object is not * of the correct type for the metadata key, an IllegalArgumentException will be thrown. For * information on creating MetaDataKeys, see {@link MetaDataKey}. * * @param key * The singleton key for the metadata * @param object * The metadata object * @throws IllegalArgumentException * @see MetaDataKey */ public final void setMetaData(final MetaDataKey key, final Serializable object) { metaData = key.set(metaData, object); } /** * Gets metadata for this request cycle using the given key. * * @param key * The key for the data * @return The metadata or null if no metadata was found for the given key * @see MetaDataKey */ public final Serializable getMetaData(final MetaDataKey key) { return key.get(metaData); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -