001: package org.apache.ojb.odmg.locking;
002:
003: /* Copyright 2004-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import java.io.BufferedOutputStream;
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.ObjectInputStream;
023: import java.io.ObjectOutputStream;
024: import java.net.HttpURLConnection;
025: import java.net.MalformedURLException;
026: import java.net.ProtocolException;
027: import java.net.URL;
028: import java.util.Collection;
029:
030: import org.apache.ojb.broker.Identity;
031: import org.apache.ojb.broker.PersistenceBroker;
032: import org.apache.ojb.broker.PersistenceBrokerException;
033: import org.apache.ojb.broker.util.configuration.Configurable;
034: import org.apache.ojb.broker.util.configuration.Configuration;
035: import org.apache.ojb.broker.util.configuration.ConfigurationException;
036: import org.apache.ojb.broker.util.logging.Logger;
037: import org.apache.ojb.broker.util.logging.LoggerFactory;
038: import org.apache.ojb.odmg.TransactionImpl;
039: import org.apache.ojb.odmg.TxManagerFactory;
040:
041: /**
042: * Servlet based lock mechanism for usage in distributed environment.
043: * @author Thomas Mahler
044: * @version $Id: RemoteLockMapImpl.java,v 1.4.2.3 2005/12/21 22:29:51 tomdz Exp $
045: */
046: public class RemoteLockMapImpl implements LockMap, Configurable {
047: private Logger log = LoggerFactory
048: .getLogger(RemoteLockMapImpl.class);
049:
050: private static URL lockservlet = null;
051:
052: /**
053: * obtain a PersistenceBroker instance.
054: */
055: private PersistenceBroker getBroker() {
056: return TxManagerFactory.instance().getCurrentTransaction()
057: .getBroker();
058: }
059:
060: /**
061: * returns the LockEntry for the Writer of object obj.
062: * If now writer exists, null is returned.
063: */
064: public LockEntry getWriter(Object obj) {
065: PersistenceBroker broker = getBroker();
066: Identity oid = new Identity(obj, broker);
067:
068: LockEntry result = null;
069: try {
070: result = getWriterRemote(oid);
071: } catch (Throwable e) {
072: log.error(e);
073: }
074: return result;
075: }
076:
077: private LockEntry getWriterRemote(Identity oid)
078: throws MalformedURLException, IOException,
079: ProtocolException, ClassNotFoundException {
080: byte selector = (byte) 'w';
081: byte[] requestBarr = buildRequestArray(oid, selector);
082:
083: HttpURLConnection conn = getHttpUrlConnection();
084:
085: //post request
086: BufferedOutputStream out = new BufferedOutputStream(conn
087: .getOutputStream());
088: out.write(requestBarr, 0, requestBarr.length);
089: out.flush();
090: out.close();
091:
092: // read result from
093: InputStream in = conn.getInputStream();
094: ObjectInputStream ois = new ObjectInputStream(in);
095: LockEntry result = (LockEntry) ois.readObject();
096:
097: // cleanup
098: ois.close();
099: conn.disconnect();
100: return result;
101: }
102:
103: private HttpURLConnection getHttpUrlConnection()
104: throws MalformedURLException, IOException,
105: ProtocolException {
106: URL lockserver = getLockserverUrl();
107: HttpURLConnection conn = (HttpURLConnection) lockserver
108: .openConnection();
109:
110: conn.setDoInput(true);
111: conn.setDoOutput(true);
112: conn.setRequestMethod("POST");
113: conn.setAllowUserInteraction(false);
114: conn.setUseCaches(false);
115: return conn;
116: }
117:
118: private byte[] buildRequestArray(Object object, byte selector)
119: throws IOException {
120: byte[] serialObj = serialize(object);
121: int len = serialObj.length;
122: byte[] requestBarr = new byte[len + 1];
123: requestBarr[0] = selector;
124: System.arraycopy(serialObj, 0, requestBarr, 1, len);
125: return requestBarr;
126: }
127:
128: private URL getLockserverUrl() throws MalformedURLException {
129: return lockservlet;
130: }
131:
132: /**
133: * returns a collection of Reader LockEntries for object obj.
134: * If now LockEntries could be found an empty Vector is returned.
135: */
136: public Collection getReaders(Object obj) {
137: Collection result = null;
138: try {
139: Identity oid = new Identity(obj, getBroker());
140: byte selector = (byte) 'r';
141: byte[] requestBarr = buildRequestArray(oid, selector);
142:
143: HttpURLConnection conn = getHttpUrlConnection();
144:
145: //post request
146: BufferedOutputStream out = new BufferedOutputStream(conn
147: .getOutputStream());
148: out.write(requestBarr, 0, requestBarr.length);
149: out.flush();
150:
151: // read result from
152: InputStream in = conn.getInputStream();
153: ObjectInputStream ois = new ObjectInputStream(in);
154: result = (Collection) ois.readObject();
155:
156: // cleanup
157: ois.close();
158: out.close();
159: conn.disconnect();
160: } catch (Throwable t) {
161: throw new PersistenceBrokerException(t);
162: }
163: return result;
164: }
165:
166: /**
167: * Add a reader lock entry for transaction tx on object obj
168: * to the persistent storage.
169: */
170: public boolean addReader(TransactionImpl tx, Object obj) {
171: try {
172: LockEntry lock = new LockEntry(new Identity(obj,
173: getBroker()).toString(), tx.getGUID(), System
174: .currentTimeMillis(), LockStrategyFactory
175: .getIsolationLevel(obj), LockEntry.LOCK_READ);
176: addReaderRemote(lock);
177: return true;
178: } catch (Throwable t) {
179: log.error("Cannot store LockEntry for object " + obj
180: + " in transaction " + tx, t);
181: return false;
182: }
183: }
184:
185: private void addReaderRemote(LockEntry lock) throws IOException,
186: ClassNotFoundException {
187: byte selector = (byte) 'a';
188: byte[] requestBarr = buildRequestArray(lock, selector);
189:
190: HttpURLConnection conn = getHttpUrlConnection();
191:
192: //post request
193: BufferedOutputStream out = new BufferedOutputStream(conn
194: .getOutputStream());
195: out.write(requestBarr, 0, requestBarr.length);
196: out.flush();
197:
198: // read result from
199: InputStream in = conn.getInputStream();
200: ObjectInputStream ois = new ObjectInputStream(in);
201: Boolean result = (Boolean) ois.readObject();
202:
203: // cleanup
204: ois.close();
205: out.close();
206: conn.disconnect();
207: if (!result.booleanValue()) {
208: throw new PersistenceBrokerException(
209: "could not add reader!");
210: }
211: }
212:
213: public byte[] serialize(Object obj) throws IOException {
214: ByteArrayOutputStream bao = new ByteArrayOutputStream();
215: ObjectOutputStream oos = new ObjectOutputStream(bao);
216: oos.writeObject(obj);
217: oos.close();
218: bao.close();
219: byte[] result = bao.toByteArray();
220: return result;
221: }
222:
223: /**
224: * remove a reader lock entry for transaction tx on object obj
225: * from the persistent storage.
226: */
227: public void removeReader(TransactionImpl tx, Object obj) {
228: try {
229: LockEntry lock = new LockEntry(new Identity(obj,
230: getBroker()).toString(), tx.getGUID());
231: removeReaderRemote(lock);
232: } catch (Throwable t) {
233: log.error("Cannot remove LockEntry for object " + obj
234: + " in transaction " + tx);
235: }
236: }
237:
238: private void removeReaderRemote(LockEntry lock) throws IOException,
239: ClassNotFoundException {
240: byte selector = (byte) 'e';
241: byte[] requestBarr = buildRequestArray(lock, selector);
242:
243: HttpURLConnection conn = getHttpUrlConnection();
244:
245: //post request
246: BufferedOutputStream out = new BufferedOutputStream(conn
247: .getOutputStream());
248: out.write(requestBarr, 0, requestBarr.length);
249: out.flush();
250:
251: // read result from
252: InputStream in = conn.getInputStream();
253: ObjectInputStream ois = new ObjectInputStream(in);
254: Boolean result = (Boolean) ois.readObject();
255:
256: // cleanup
257: ois.close();
258: out.close();
259: conn.disconnect();
260: if (!result.booleanValue()) {
261: throw new PersistenceBrokerException(
262: "could not remove reader!");
263: }
264:
265: }
266:
267: /**
268: * remove a writer lock entry for transaction tx on object obj
269: * from the persistent storage.
270: */
271: public void removeWriter(LockEntry writer) {
272: try {
273: removeWriterRemote(writer);
274: } catch (Throwable t) {
275: log.error("Cannot remove LockEntry", t);
276: }
277: }
278:
279: private void removeWriterRemote(LockEntry lock) throws IOException,
280: ClassNotFoundException {
281: byte selector = (byte) 'm';
282: byte[] requestBarr = buildRequestArray(lock, selector);
283:
284: HttpURLConnection conn = getHttpUrlConnection();
285:
286: //post request
287: BufferedOutputStream out = new BufferedOutputStream(conn
288: .getOutputStream());
289: out.write(requestBarr, 0, requestBarr.length);
290: out.flush();
291:
292: // read result from
293: InputStream in = conn.getInputStream();
294: ObjectInputStream ois = new ObjectInputStream(in);
295: Boolean result = (Boolean) ois.readObject();
296:
297: // cleanup
298: ois.close();
299: out.close();
300: conn.disconnect();
301: if (!result.booleanValue()) {
302: throw new PersistenceBrokerException(
303: "could not remove writer!");
304: }
305:
306: }
307:
308: /**
309: * upgrade a reader lock entry for transaction tx on object obj
310: * and write it to the persistent storage.
311: */
312: public boolean upgradeLock(LockEntry reader) {
313: try {
314: upgradeLockRemote(reader);
315: reader.setLockType(LockEntry.LOCK_WRITE);
316: return true;
317: } catch (Throwable t) {
318: log.error("Cannot upgrade LockEntry " + reader, t);
319: return false;
320: }
321: }
322:
323: private void upgradeLockRemote(LockEntry lock) throws IOException,
324: ClassNotFoundException {
325: byte selector = (byte) 'u';
326: byte[] requestBarr = buildRequestArray(lock, selector);
327:
328: HttpURLConnection conn = getHttpUrlConnection();
329:
330: //post request
331: BufferedOutputStream out = new BufferedOutputStream(conn
332: .getOutputStream());
333: out.write(requestBarr, 0, requestBarr.length);
334: out.flush();
335:
336: // read result from
337: InputStream in = conn.getInputStream();
338: ObjectInputStream ois = new ObjectInputStream(in);
339: Boolean result = (Boolean) ois.readObject();
340:
341: // cleanup
342: ois.close();
343: out.close();
344: conn.disconnect();
345: if (!result.booleanValue()) {
346: throw new PersistenceBrokerException(
347: "could not remove writer!");
348: }
349:
350: }
351:
352: /**
353: * generate a writer lock entry for transaction tx on object obj
354: * and write it to the persistent storage.
355: */
356: public boolean setWriter(TransactionImpl tx, Object obj) {
357: try {
358: LockEntry lock = new LockEntry(new Identity(obj,
359: getBroker()).toString(), tx.getGUID(), System
360: .currentTimeMillis(), LockStrategyFactory
361: .getIsolationLevel(obj), LockEntry.LOCK_WRITE);
362:
363: setWriterRemote(lock);
364: return true;
365: } catch (Throwable t) {
366: log.error("Cannot set LockEntry for object " + obj
367: + " in transaction " + tx);
368: return false;
369: }
370: }
371:
372: private void setWriterRemote(LockEntry lock) throws IOException,
373: ClassNotFoundException {
374: byte selector = (byte) 's';
375: byte[] requestBarr = buildRequestArray(lock, selector);
376:
377: HttpURLConnection conn = getHttpUrlConnection();
378:
379: //post request
380: BufferedOutputStream out = new BufferedOutputStream(conn
381: .getOutputStream());
382: out.write(requestBarr, 0, requestBarr.length);
383: out.flush();
384:
385: // read result from
386: InputStream in = conn.getInputStream();
387: ObjectInputStream ois = new ObjectInputStream(in);
388: Boolean result = (Boolean) ois.readObject();
389:
390: // cleanup
391: ois.close();
392: out.close();
393: conn.disconnect();
394: if (!result.booleanValue()) {
395: throw new PersistenceBrokerException(
396: "could not set writer!");
397: }
398:
399: }
400:
401: /**
402: * check if there is a reader lock entry for transaction tx on object obj
403: * in the persistent storage.
404: */
405: public boolean hasReadLock(TransactionImpl tx, Object obj) {
406: try {
407: LockEntry lock = new LockEntry(new Identity(obj,
408: getBroker()).toString(), tx.getGUID());
409: boolean result = hasReadLockRemote(lock);
410: return result;
411: } catch (Throwable t) {
412: log.error("Cannot check read lock for object " + obj
413: + " in transaction " + tx, t);
414: return false;
415: }
416: }
417:
418: private boolean hasReadLockRemote(LockEntry lock)
419: throws IOException, ClassNotFoundException {
420: byte selector = (byte) 'h';
421: byte[] requestBarr = buildRequestArray(lock, selector);
422:
423: HttpURLConnection conn = getHttpUrlConnection();
424:
425: //post request
426: BufferedOutputStream out = new BufferedOutputStream(conn
427: .getOutputStream());
428: out.write(requestBarr, 0, requestBarr.length);
429: out.flush();
430:
431: // read result from
432: InputStream in = conn.getInputStream();
433: ObjectInputStream ois = new ObjectInputStream(in);
434: Boolean result = (Boolean) ois.readObject();
435:
436: // cleanup
437: ois.close();
438: out.close();
439: conn.disconnect();
440: return result.booleanValue();
441: }
442:
443: /**
444: * @see org.apache.ojb.broker.util.configuration.Configurable#configure(org.apache.ojb.broker.util.configuration.Configuration)
445: */
446: public void configure(Configuration pConfig)
447: throws ConfigurationException {
448: String url = pConfig.getString("LockServletUrl",
449: "http://127.0.0.1:8080/ojb-lockserver");
450: try {
451: lockservlet = new URL(url);
452: } catch (MalformedURLException e) {
453: throw new ConfigurationException(
454: "Invalid LockServlet Url was specified: " + url, e);
455: }
456:
457: }
458:
459: }
|