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 }