All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.webflow.registry.RefreshableFlowHolder Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/*
 * Copyright 2002-2006 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.webflow.registry;

import java.io.IOException;

import org.springframework.core.io.Resource;
import org.springframework.webflow.Flow;
import org.springframework.webflow.builder.FlowAssembler;
import org.springframework.webflow.builder.FlowBuilder;
import org.springframework.webflow.builder.FlowBuilderException;
import org.springframework.webflow.builder.ResourceHolder;

/**
 * A flow definition holder that can detect changes on an underlying flow
 * definition resource and refresh that resource automatically.
 * 
 * This class is threadsafe.
 * 
 * @author Keith Donald
 */
public class RefreshableFlowHolder implements FlowHolder {

	/**
	 * The flow definition assembled by this assembler.
	 */
	private Flow flow;

	/**
	 * The flow assembler.
	 */
	private FlowAssembler assembler;

	/**
	 * A last modified date for the backing flow resource, used to support
	 * automatic reassembly on resource change.
	 */
	private long lastModified;

	/**
	 * A flag indicating whether or not this assembler is in the middle of the
	 * assembly process.
	 */
	private boolean assembling;

	/**
	 * Creates a new refreshable flow holder that uses the configured assembler (GOF director) to
	 * drive flow assembly, on initial use and on any resource change.
	 * @param assembler the flow assembler (director)
	 */
	public RefreshableFlowHolder(FlowAssembler assembler) {
		this.assembler = assembler;
	}

	public String getId() {
		return assembler.getFlowId();
	}

	/**
	 * Returns the flow builder that actually builds the Flow definition.
	 */
	public FlowBuilder getFlowBuilder() {
		return assembler.getFlowBuilder();
	}

	public synchronized Flow getFlow() throws FlowBuilderException {
		if (assembling) {
			// must return early assembly result
			return getFlowBuilder().getFlow();
		}
		if (!isAssembled()) {
			lastModified = calculateLastModified();
			assembleFlow();
		}
		else {
			refreshIfChanged();
		}
		return flow;
	}

	public synchronized void refresh() throws FlowBuilderException {
		assembleFlow();
	}

	/**
	 * Reassemble the flow if its underlying resource has changed.
	 */
	protected void refreshIfChanged() {
		if (this.lastModified == -1) {
			// just ignore, tracking last modified date not supported
			return;
		}
		if (this.lastModified < calculateLastModified()) {
			assembleFlow();
		}
	}

	/**
	 * Assemble the held flow definition, delegating to the configured
	 * FlowAssembler (director).
	 */
	protected void assembleFlow() throws FlowBuilderException {
		try {
			assembling = true;
			assembler.assembleFlow();
			flow = getFlowBuilder().getFlow();
		}
		finally {
			assembling = false;
		}
	}

	/**
	 * Helper that retrieves the last modified date by querying the backing flow
	 * resource.
	 * @return the last modified date, or -1 if it could not be retrieved
	 */
	protected long calculateLastModified() {
		if (getFlowBuilder() instanceof ResourceHolder) {
			Resource resource = ((ResourceHolder)getFlowBuilder()).getResource();
			try {
				return resource.getFile().lastModified();
			}
			catch (IOException e) {
				// ignore, last modified checks not supported
			}
		}
		return -1;
	}
	
	/**
	 * Returns a flag indicating if this holder has performed and completed
	 * Flow assembly.
	 */
	protected boolean isAssembled() {
		return flow != null;
	}

	/**
	 * Returns a flag indicating if this holder is performing assembly.
	 */
	protected boolean isAssembling() {
		return assembling;
	}
	
	/**
	 * Returns the last modifed date of the backed builder resource.
	 * @return the last modified date
	 */
	protected long getLastModified() {
		return lastModified;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy