001 /*
002 * JBoss DNA (http://www.jboss.org/dna)
003 * See the COPYRIGHT.txt file distributed with this work for information
004 * regarding copyright ownership. Some portions may be licensed
005 * to Red Hat, Inc. under one or more contributor license agreements.
006 * See the AUTHORS.txt file in the distribution for a full listing of
007 * individual contributors.
008 *
009 * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010 * is licensed to you under the terms of the GNU Lesser General Public License as
011 * published by the Free Software Foundation; either version 2.1 of
012 * the License, or (at your option) any later version.
013 *
014 * JBoss DNA is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 * Lesser General Public License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this software; if not, write to the Free
021 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023 */
024 package org.jboss.dna.graph.request;
025
026 import java.io.Serializable;
027 import java.util.concurrent.atomic.AtomicBoolean;
028 import org.jboss.dna.graph.GraphI18n;
029 import org.jboss.dna.graph.connector.RepositoryConnection;
030
031 /**
032 * The abstract base class for all classes representing requests to be executed against a {@link RepositoryConnection}.
033 *
034 * @author Randall Hauch
035 */
036 public abstract class Request implements Serializable {
037
038 private static final long serialVersionUID = 1L;
039
040 private Throwable error;
041 private AtomicBoolean cancelled = new AtomicBoolean(false);
042 private final AtomicBoolean frozen = new AtomicBoolean(false);
043
044 protected Request() {
045 }
046
047 /**
048 * Set the error for this request.
049 *
050 * @param error the error to be associated with this request, or null if this request is to have no error
051 * @throws IllegalStateException if the request is frozen
052 */
053 public void setError( Throwable error ) {
054 checkNotFrozen();
055 this.error = error;
056 }
057
058 /**
059 * Return whether there is an error associated with this request
060 *
061 * @return true if there is an error, or false otherwise
062 */
063 public boolean hasError() {
064 return this.error != null;
065 }
066
067 /**
068 * Get the error associated with this request, if there is such an error.
069 *
070 * @return the error, or null if there is none
071 */
072 public Throwable getError() {
073 return error;
074 }
075
076 /**
077 * Check whether this request has been cancelled. Although it is a recommendation that the result of this method be followed
078 * wherever possible, it is not required to immediately stop processing the request if this method returns <code>true</code>.
079 * For example, if processing is almost complete, it may be appropriate to simply finish processing the request.
080 * <p>
081 * This method is safe to be called by different threads.
082 * </p>
083 *
084 * @return true if this request has been cancelled, or false otherwise.
085 */
086 public boolean isCancelled() {
087 return cancelled.get();
088 }
089
090 /**
091 * Set the cancelled state of this request. All requests are initially marked as not cancelled. Note that this is designed so
092 * that the same {@link AtomicBoolean} instance can be passed to multiple requests, allowing a single flag to dictate the
093 * cancelled state of all of those requests.
094 * <p>
095 * So, by default, each request should already be set up to not be cancelled, so for most cases this method does not need to
096 * be called at all. This method should be called when this flag is to be shared among multiple requests, usually when the
097 * requests are being initialized or assembled.
098 * </p>
099 *
100 * @param cancelled the new (potentially shared) cancelled state for the request; may not be null
101 */
102 /*package*/void setCancelledFlag( AtomicBoolean cancelled ) {
103 assert cancelled != null;
104 this.cancelled = cancelled;
105 }
106
107 /**
108 * Get this request's cancelled flag.
109 *
110 * @return the cancelled flag
111 */
112 /*package*/AtomicBoolean getCancelledFlag() {
113 return cancelled;
114 }
115
116 /**
117 * Cancel this request. After this method is called, the {@link #isCancelled() cancellation flag} is set, and any current or
118 * future processing of the request may be affected by the cancellation. (Note however, that processors may choose to not
119 * respect this request.)
120 * <p>
121 * This method is safe to be called by different threads.
122 * </p>
123 *
124 * @throws IllegalStateException if the request is frozen
125 */
126 public void cancel() {
127 checkNotFrozen();
128 this.cancelled.set(true);
129 }
130
131 /**
132 * Return whether this request only reads information.
133 *
134 * @return true if this request reads information, or false if it requests that the repository content be changed in some way
135 */
136 public abstract boolean isReadOnly();
137
138 /**
139 * Determine whether this request has been frozen, preventing any further updates.
140 *
141 * @return true if the request has been frozen, or false otherwise
142 */
143 public boolean isFrozen() {
144 return frozen.get();
145 }
146
147 /**
148 * Freeze this request to prevent any further modification. This method does nothing if the request is already frozen.
149 */
150 public void freeze() {
151 frozen.set(true);
152 }
153
154 /**
155 * Utility method to check that the request is not frozen, and if it is to throw an {@link IllegalStateException}.
156 *
157 * @throws IllegalStateException if the request is frozen
158 */
159 protected void checkNotFrozen() throws IllegalStateException {
160 if (frozen.get()) {
161 throw new IllegalStateException(GraphI18n.requestIsFrozenAndMayNotBeChanged.text(this));
162 }
163 }
164 }