001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data.postgis;
017:
018: import java.io.IOException;
019: import java.util.NoSuchElementException;
020: import java.util.logging.Logger;
021:
022: import org.geotools.data.DataSourceException;
023: import org.geotools.data.DefaultQuery;
024: import org.geotools.data.FeatureLock;
025: import org.geotools.data.FeatureLockException;
026: import org.geotools.data.FeatureLocking;
027: import org.geotools.data.FeatureReader;
028: import org.geotools.data.LockingManager;
029: import org.geotools.data.Query;
030: import org.geotools.feature.Feature;
031: import org.geotools.feature.FeatureIterator;
032: import org.geotools.feature.FeatureType;
033: import org.geotools.feature.IllegalAttributeException;
034: import org.opengis.filter.Filter;
035:
036: /**
037: * Extends PostgisFeatureLocking with support for Locking.
038: *
039: * <p>
040: * This class will be, horror, modey. While the are plenty of Object Oriented
041: * ways to fix this I have a deadline right now.
042: * </p>
043: *
044: * <p>
045: * When the DataStore is constructed it will create a LockingManager only if
046: * the Postgis implementation does not support database locking. If the
047: * lockingManger is present it will be used.
048: * </p>
049: *
050: * <p>
051: * If the lockingManger is not present, the this class will use Database
052: * locking
053: * </p>
054: *
055: * @author Jody Garnett, Refractions Research, Inc
056: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/postgis/src/main/java/org/geotools/data/postgis/PostgisFeatureLocking.java $
057: * @version $Id: PostgisFeatureLocking.java 27862 2007-11-12 19:51:19Z desruisseaux $
058: */
059: public class PostgisFeatureLocking extends PostgisFeatureStore
060: implements FeatureLocking {
061: /** The logger for the postgis module. */
062: private static final Logger LOGGER = org.geotools.util.logging.Logging
063: .getLogger("org.geotools.data.postgis");
064: FeatureLock featureLock = FeatureLock.TRANSACTION;
065:
066: public PostgisFeatureLocking(PostgisDataStore postgisDataStore,
067: FeatureType featureType) throws IOException {
068: super (postgisDataStore, featureType);
069: }
070:
071: /**
072: * Provide a FeatureLock for locking opperations to opperate against.
073: *
074: * <p>
075: * Initial Transactional duration locks can be restored with
076: * setFeatureLock( FetaureLock.TRANSACTION )
077: * </p>
078: *
079: * @param lock FeatureLock (or FeatureLock.TRANSACTION );
080: *
081: * @throws NullPointerException If lock was <code>null</code>
082: *
083: * @see org.geotools.data.FeatureLocking#setFeatureLock(org.geotools.data.FeatureLock)
084: */
085: public void setFeatureLock(FeatureLock lock) {
086: if (lock == null) {
087: throw new NullPointerException(
088: "A FeatureLock is required - did you mean FeatureLock.TRANSACTION?");
089: }
090:
091: featureLock = lock;
092: }
093:
094: /**
095: * Lock all Features
096: *
097: * @return Number of Locked features
098: *
099: * @throws IOException
100: *
101: * @see org.geotools.data.FeatureLocking#lockFeatures()
102: */
103: public int lockFeatures() throws IOException {
104: return lockFeatures(Filter.INCLUDE);
105: }
106:
107: /**
108: * Lock features matching <code>filter</code>.
109: *
110: * @param filter
111: *
112: * @return Number of locked Features
113: *
114: * @throws IOException
115: *
116: * @see org.geotools.data.FeatureLocking#lockFeatures(org.geotools.filter.Filter)
117: */
118: public int lockFeatures(Filter filter) throws IOException {
119: return lockFeatures(new DefaultQuery(getSchema().getTypeName(),
120: filter));
121: }
122:
123: public int lockFeatures(org.geotools.filter.Filter filter)
124: throws IOException {
125: return lockFeatures(new DefaultQuery(getSchema().getTypeName(),
126: filter));
127: }
128:
129: /**
130: * Lock features matching Query.
131: *
132: * <p>
133: * FeatureStores that have provided their own locking to will need to
134: * override this method.
135: * </p>
136: *
137: * @param query
138: *
139: * @return Number of locked Features
140: *
141: * @throws IOException If we could not determine which feature to lock
142: * based on Query
143: * @throws UnsupportedOperationException When DataStore does not provide a
144: * LockingManager
145: * @throws DataSourceException If feature to be locked does not exist
146: *
147: * @see org.geotools.data.FeatureLocking#lockFeatures(org.geotools.data.Query)
148: */
149: public int lockFeatures(Query query) throws IOException {
150: LockingManager lockingManager = getDataStore()
151: .getLockingManager();
152:
153: if (lockingManager == null) {
154: throw new UnsupportedOperationException(
155: "DataStore not using lockingManager, must provide alternate implementation");
156: }
157:
158: String typeName = getSchema().getTypeName();
159:
160: if ((query.getTypeName() != null)
161: && !typeName.equals(query.getTypeName())) {
162: throw new IOException("Query typeName does not match "
163: + getSchema().getTypeName() + ":" + query);
164: }
165:
166: // Reduce the Query to only return the FetureID here?
167: // Good idea, but it's not working right now, so we're just using the query passed in.
168: Query optimizedQuery = new DefaultQuery(typeName, query
169: .getFilter(), query.getMaxFeatures(), Query.NO_NAMES,
170: query.getHandle());
171: FeatureIterator reader = getFeatures(query).features();
172: Feature feature;
173: int count = 0;
174: LOGGER.info("got reader from query " + optimizedQuery
175: + ", reader has next " + reader.hasNext());
176:
177: try {
178: while (reader.hasNext()) {
179: try {
180: feature = reader.next();
181: lockingManager.lockFeatureID(typeName, feature
182: .getID(), transaction, featureLock);
183: count++;
184: LOGGER.info("locked feature " + feature);
185: } catch (FeatureLockException locked) {
186: LOGGER.info("feature lock exception");
187:
188: // could not aquire - don't increment count
189: } catch (NoSuchElementException nosuch) {
190: throw new DataSourceException("Problem with "
191: + query.getHandle() + " while locking",
192: nosuch);
193: }
194: }
195: } finally {
196: reader.close();
197: }
198:
199: return count;
200: }
201:
202: /**
203: * HACK HACK HACK!!! Don't use unless you're working on geoserver. just
204: * using ints for return now, to easily swap out with what we've got going
205: * on right now.
206: *
207: * @param feature DOCUMENT ME!
208: *
209: * @return DOCUMENT ME!
210: *
211: * @throws IOException DOCUMENT ME!
212: * @throws UnsupportedOperationException DOCUMENT ME!
213: */
214: public int lockFeature(Feature feature) throws IOException {
215: LockingManager lockingManager = getDataStore()
216: .getLockingManager();
217:
218: if (lockingManager == null) {
219: throw new UnsupportedOperationException(
220: "DataStore not using lockingManager, must provide alternate implementation");
221: }
222:
223: try {
224: //TODO: more checking here, check feature.typename == this.typename
225: //perhaps even feature.getFeatureType == this.featureType.
226: lockingManager.lockFeatureID(tableName, feature.getID(),
227: getTransaction(), featureLock);
228:
229: return 1;
230: } catch (FeatureLockException locked) {
231: return 0;
232: }
233: }
234:
235: /**
236: * Unlock all Features.
237: *
238: * @throws IOException
239: *
240: * @see org.geotools.data.FeatureLocking#unLockFeatures()
241: */
242: public void unLockFeatures() throws IOException {
243: unLockFeatures(Filter.INCLUDE);
244: }
245:
246: /**
247: * Unlock Features specified by <code>filter</code>.
248: *
249: * @param filter
250: *
251: * @throws IOException
252: *
253: * @see org.geotools.data.FeatureLocking#unLockFeatures(org.geotools.filter.Filter)
254: */
255: public void unLockFeatures(Filter filter) throws IOException {
256: unLockFeatures(new DefaultQuery(getSchema().getTypeName(),
257: filter));
258: }
259:
260: /**
261: * Unlock features specified by the <code>query</code>.
262: *
263: * <p>
264: * FeatureStores that have provided their own locking to will need to
265: * override this method.
266: * </p>
267: *
268: * @param query
269: *
270: * @throws IOException
271: * @throws UnsupportedOperationException If lockingManager is not provided
272: * by DataStore subclass
273: * @throws DataSourceException Filter describes an unlocked Feature, or
274: * authorization not held
275: *
276: * @see org.geotools.data.FeatureLocking#unLockFeatures(org.geotools.data.Query)
277: */
278: public void unLockFeatures(Query query) throws IOException {
279: LockingManager lockingManager = getDataStore()
280: .getLockingManager();
281:
282: if (lockingManager == null) {
283: throw new UnsupportedOperationException(
284: "DataStore not using lockingManager, must provide alternate implementation");
285: }
286:
287: // Could we reduce the Query to only return the FetureID here?
288: //
289: FeatureIterator reader = getFeatures(query).features();
290: String typeName = getSchema().getTypeName();
291: Feature feature;
292:
293: try {
294: while (reader.hasNext()) {
295: try {
296: feature = reader.next();
297: lockingManager.unLockFeatureID(typeName, feature
298: .getID(), getTransaction(), featureLock);
299: } catch (NoSuchElementException nosuch) {
300: throw new DataSourceException("Problem with "
301: + query.getHandle() + " while locking",
302: nosuch);
303: }
304: }
305: } finally {
306: reader.close();
307: }
308: }
309: }
|