Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.spi / src / main / java / org / gvsig / fmap / dal / resource / spi / AbstractResource.java @ 44376

History | View | Annotate | Download (9.63 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.resource.spi;
25

    
26
import java.lang.ref.WeakReference;
27
import java.util.ArrayList;
28
import java.util.Iterator;
29
import java.util.List;
30

    
31
import org.gvsig.fmap.dal.exception.CopyParametersException;
32
import org.gvsig.fmap.dal.exception.InitializeException;
33
import org.gvsig.fmap.dal.resource.Resource;
34
import org.gvsig.fmap.dal.resource.ResourceAction;
35
import org.gvsig.fmap.dal.resource.ResourceNotification;
36
import org.gvsig.fmap.dal.resource.ResourceParameters;
37
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
38
import org.gvsig.fmap.dal.resource.exception.PrepareResourceException;
39
import org.gvsig.fmap.dal.resource.exception.ResourceException;
40
import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException;
41
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyChangesException;
42
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyCloseException;
43
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyDisposeException;
44
import org.gvsig.fmap.dal.resource.exception.ResourceNotifyOpenException;
45
import org.gvsig.fmap.dal.resource.impl.DefaultResourceNotification;
46
import org.gvsig.tools.observer.Observer;
47
import org.gvsig.tools.observer.WeakReferencingObservable;
48
import org.gvsig.tools.observer.impl.BaseWeakReferencingObservable;
49
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
/**
54
 * <p>
55
 * Base implementation for Resource
56
 * </p>
57
 *
58
 * <p>
59
 * This implementation not define the {@link Resource#begin()} and
60
 * {@link Resource#end()}
61
 * </p>
62
 *
63
 * @author jmvivo
64
 *
65
 */
66
public abstract class AbstractResource implements ResourceProvider,
67
                WeakReferencingObservable {
68

    
69
        private static Logger logger = LoggerFactory.getLogger(AbstractResource.class);
70

    
71
        private DelegateWeakReferencingObservable delegateObservable;
72

    
73
        private List consumers;
74

    
75
        private long lastTimeOpen;
76
        private long lastTimeUsed;
77

    
78
        private ResourceParameters parameters;
79
        private ResourceParameters preparedParameters;
80

    
81
        private Object data;
82

    
83
        private int openCount;
84

    
85
        /**
86
         * Number of times an execute is being simultaneously performed with this
87
         * resource.
88
         */
89
        private int executeCount = 0;
90

    
91
        protected final Object lock;
92

    
93
        protected Object multiResourcelock;
94

    
95
        protected AbstractResource(ResourceParameters parameters)
96
                        throws InitializeException {
97
                consumers = new ArrayList();
98
                lastTimeOpen = System.currentTimeMillis();
99
                lastTimeUsed = lastTimeOpen;
100

    
101
                openCount = 0;
102

    
103
                preparedParameters = null;
104
                delegateObservable = new DelegateWeakReferencingObservable(this);
105
                lock = new Object();
106
                multiResourcelock = new Object();
107
        this.parameters = null;
108
        if( parameters != null ) {
109
            try {
110
                this.parameters = (ResourceParameters) parameters.getCopy();
111
            } catch (CopyParametersException e) {
112
                throw new InitializeException(e);
113
            }
114
        }
115
        }
116

    
117
        protected final void updateLastTimeUsed() {
118
                lastTimeUsed = System.currentTimeMillis();
119
        }
120

    
121
        protected final void updateLastTimeOpen() {
122
                lastTimeOpen = System.currentTimeMillis();
123
                lastTimeUsed = lastTimeOpen;
124
        }
125

    
126
        public final long getLastTimeOpen() {
127
                return lastTimeOpen;
128
        }
129

    
130
        public final long getLastTimeUsed() {
131
                return lastTimeUsed;
132
        }
133

    
134
        public ResourceParameters getParameters() {
135
                if (preparedParameters != null) {
136
                        return preparedParameters;
137
                }
138
                return this.parameters;
139
        }
140

    
141
        public void prepare(ResourceParameters params)
142
                        throws PrepareResourceException {
143
                ResourceNotification notification =
144
                                new DefaultResourceNotification(this,
145
                                                ResourceNotification.PREPARE, params);
146
                this.delegateObservable.notifyObservers(notification);
147
        }
148

    
149
        public void prepare() throws PrepareResourceException {
150
                if (preparedParameters == null && this.parameters!=null ) {
151
                        try {
152
                                ResourceParameters params =
153
                                                (ResourceParameters) parameters.getCopy();
154
                                prepare(params);
155
                                preparedParameters = params;
156
                        } catch (CopyParametersException e) {
157
                                throw new PrepareResourceException(this, e);
158
                        }
159
                }
160

    
161
        }
162

    
163
        public void notifyOpen() throws ResourceNotifyOpenException {
164
                this.notifyObserver(ResourceNotification.OPEN);
165
                updateLastTimeOpen();
166
                openCount++;
167
        }
168

    
169
        public void notifyClose() throws ResourceNotifyCloseException {
170
                if (openCount <= 0) {
171
                    try {
172
                        throw new IllegalStateException();
173
                    } catch(IllegalStateException ex) {
174
                        logger.warn("notify close in a resource already closed ("+this.parameters==null? "null": this.parameters.toString()+").", ex);
175
                    }
176
                    this.notifyObserver(ResourceNotification.CLOSE);
177
                } else {
178
                    this.notifyObserver(ResourceNotification.CLOSE);
179
                    openCount--;
180
                }
181
        }
182

    
183
        public void notifyChanges() throws ResourceNotifyChangesException {
184
                this.notifyObserver(ResourceNotification.CHANGED);
185

    
186
                Iterator it = consumers.iterator();
187
                while (it.hasNext()) {
188
                        ResourceConsumer consumer =
189
                                        (ResourceConsumer) ((WeakReference) it.next()).get();
190
                        if (consumer != null) {
191
                                consumer.resourceChanged(this);
192
                        } else {
193
                                it.remove();
194
                        }
195
                }
196
        }
197

    
198
        public boolean isOpen() {
199
                return this.openCount > 0;
200
        }
201

    
202
        public int openCount() {
203
                return this.openCount;
204
        }
205

    
206
        public void addObserver(Observer o) {
207
                this.delegateObservable.addObserver(o);
208
        }
209

    
210
        public void deleteObserver(Observer o) {
211
                this.delegateObservable.deleteObserver(o);
212
        }
213

    
214
        public void deleteObservers() {
215
                this.delegateObservable.deleteObservers();
216

    
217
        }
218

    
219
        public final void addObservers(BaseWeakReferencingObservable observers) {
220
                this.delegateObservable.addObservers(observers);
221
        }
222

    
223
        public final void addConsumer(ResourceConsumer consumer) {
224
                this.updateConsumersList();
225
                consumers.add(new WeakReference(consumer));
226
        }
227

    
228
        public final void removeConsumer(ResourceConsumer consumer) {
229
                ResourceConsumer cur;
230
                Iterator it = consumers.iterator();
231
                while (it.hasNext()) {
232
                        cur = (ResourceConsumer) ((WeakReference) it.next()).get();
233
                        if (cur == null || (cur == consumer)) {
234
                                it.remove();
235
                        }
236
                }
237

    
238
        }
239

    
240
        public int getConsumersCount() {
241
                this.updateConsumersList();
242
                return consumers.size();
243
        }
244

    
245
        public ResourceConsumer getConsumerAt(int i){
246
            this.updateConsumersList();
247
            if (consumers==null){
248
                return null;
249
            }else{
250
                return (ResourceConsumer)consumers.get(i);
251
            }
252
        }
253

    
254
        private synchronized void updateConsumersList() {
255
                Iterator it = consumers.iterator();
256
                WeakReference ref;
257
                while (it.hasNext()) {
258
                        ref = (WeakReference) it.next();
259
                        if (ref.get() == null) {
260
                                it.remove();
261
                        }
262
                }
263
        }
264

    
265
        public void closeRequest() throws ResourceException {
266
                if (inUse()) {
267
                        return;
268
                }
269

    
270
                if (consumers != null) {
271
                        Iterator it = consumers.iterator();
272
                        while (it.hasNext()) {
273
                                ResourceConsumer consumer =
274
                                                (ResourceConsumer) ((WeakReference) it.next()).get();
275
                                if (consumer != null) {
276
                                        consumer.closeResourceRequested(this);
277
                                } else {
278
                                        it.remove();
279
                                }
280
                        }
281
                }
282
        }
283

    
284
        public void setData(Object data) {
285
                this.data = data;
286
        }
287

    
288
        public Object getData() {
289
                return this.data;
290
        }
291

    
292
        protected void notifyObserver(String type) {
293
                if (delegateObservable != null) {
294
                        this.delegateObservable.notifyObservers(new DefaultResourceNotification(
295
                                        this, type));
296
                }
297
        }
298

    
299
        public void notifyDispose() throws ResourceNotifyDisposeException {
300
                this.notifyObserver(ResourceNotification.DISPOSE);
301

    
302
                if (consumers != null) {
303
                        consumers.clear();
304
                }
305

    
306
                lastTimeOpen = 0l;
307
                lastTimeUsed = 0l;
308

    
309
                data = null;
310

    
311
                if (delegateObservable != null) {
312
                        delegateObservable.deleteObservers();
313
                }
314
        }
315

    
316
        public final boolean inUse() {
317
                return executeCount > 0;
318
        }
319

    
320
        public Object execute(ResourceAction action)
321
                        throws ResourceExecuteException {
322
                Object value = null;
323
                synchronized (lock) {
324
                    synchronized (multiResourcelock) {
325
                            executeBegins();
326
                            try {
327
                                    value = performExecution(action);
328
                            } catch (Exception e) {
329
                                    throw new ResourceExecuteException(this, e);
330
                            } finally {
331
                                    executeEnds();
332
                            }
333
                    }
334
                }
335
                return value;
336
        }
337

    
338
        protected Object performExecution(ResourceAction action) throws Exception {
339
                return action.run();
340
        }
341

    
342
        protected final void executeBegins() {
343
                executeCount++;
344
        }
345

    
346
        protected final void executeEnds() {
347
                updateLastTimeUsed();
348
                executeCount--;
349
        }
350

    
351
        /**
352
         * Returns the name of the {@link Resource}.
353
         *
354
         * @throws AccessResourceException
355
         *             if there is an error while accessing the resource
356
         */
357
        public abstract String getName() throws AccessResourceException;
358

    
359
        /**
360
         * Returns the real resource represented by this object.
361
         *
362
         * @throws AccessResourceException
363
         *             if there is an error while accessing the resource
364
         */
365
        public abstract Object get() throws AccessResourceException;
366

    
367
}