001: package org.apache.ojb.broker.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.io.Serializable;
025: import java.net.HttpURLConnection;
026: import java.net.MalformedURLException;
027: import java.net.ProtocolException;
028: import java.net.URL;
029:
030: import org.apache.ojb.broker.util.configuration.Configurable;
031: import org.apache.ojb.broker.util.configuration.Configuration;
032: import org.apache.ojb.broker.util.configuration.ConfigurationException;
033: import org.apache.ojb.broker.util.logging.Logger;
034: import org.apache.ojb.broker.util.logging.LoggerFactory;
035:
036: /**
037: * This implementation of the {@link LockManager} interface supports locking
038: * in distributed environments in combination with a specific lock servlet.
039: *
040: * @see LockManagerServlet
041: * @version $Id: LockManagerRemoteImpl.java,v 1.1.2.2 2005/12/21 22:25:32 tomdz Exp $
042: */
043: public class LockManagerRemoteImpl implements LockManager, Configurable {
044: private Logger log = LoggerFactory
045: .getLogger(LockManagerRemoteImpl.class);
046:
047: public static final byte METHOD_READ_LOCK = 'a';
048: public static final byte METHOD_WRITE_LOCK = 's';
049: public static final byte METHOD_UPGRADE_LOCK = 'u';
050: public static final byte METHOD_CHECK_READ = 'r';
051: public static final byte METHOD_CHECK_WRITE = 'w';
052: public static final byte METHOD_CHECK_UPGRADE = 'v';
053: public static final byte METHOD_RELEASE_SINGLE_LOCK = 'e';
054: public static final byte METHOD_RELEASE_LOCKS = 'x';
055: public static final byte METHOD_LOCK_INFO = 'i';
056: public static final byte METHOD_LOCK_TIMEOUT = 't';
057: public static final byte METHOD_LOCK_TIMEOUT_SET = 'y';
058: public static final byte METHOD_BLOCK_TIMEOUT = 'c';
059: public static final byte METHOD_BLOCK_TIMEOUT_SET = 'd';
060:
061: private static URL lockservlet = null;
062:
063: public LockManagerRemoteImpl() {
064: }
065:
066: /**
067: * @see org.apache.ojb.broker.util.configuration.Configurable#configure(org.apache.ojb.broker.util.configuration.Configuration)
068: */
069: public void configure(Configuration pConfig)
070: throws ConfigurationException {
071: String url = pConfig.getString("LockServletUrl",
072: "http://127.0.0.1:8080/ojb-lockserver");
073: log.info("Lock server servlet URL: " + url);
074: try {
075: lockservlet = new URL(url);
076: } catch (MalformedURLException e) {
077: throw new ConfigurationException(
078: "Invalid LockServlet Url was specified: " + url, e);
079: }
080:
081: }
082:
083: /**
084: * noop
085: * @param timeout
086: */
087: public void setLockTimeout(long timeout) {
088: // LockInfo info = new LockInfo(timeout, METHOD_LOCK_TIMEOUT_SET);
089: // try
090: // {
091: // byte[] requestBarr = serialize(info);
092: // performRequestObject(requestBarr);
093: // }
094: // catch(Throwable t)
095: // {
096: // throw new LockRuntimeException("Can't set locking timeout", t);
097: // }
098: }
099:
100: public long getLockTimeout() {
101: LockInfo info = new LockInfo(METHOD_LOCK_TIMEOUT);
102: try {
103: byte[] requestBarr = serialize(info);
104: return performRequestLong(requestBarr);
105: } catch (Throwable t) {
106: throw new LockRuntimeException("Can't get locking info", t);
107: }
108: }
109:
110: public long getBlockTimeout() {
111: LockInfo info = new LockInfo(METHOD_BLOCK_TIMEOUT);
112: try {
113: byte[] requestBarr = serialize(info);
114: return performRequestLong(requestBarr);
115: } catch (Throwable t) {
116: throw new LockRuntimeException(
117: "Can't get block timeout value", t);
118: }
119: }
120:
121: /**
122: * noop
123: */
124: public void setBlockTimeout(long timeout) {
125: // LockInfo info = new LockInfo(timeout, METHOD_BLOCK_TIMEOUT_SET);
126: // try
127: // {
128: // byte[] requestBarr = serialize(info);
129: // performRequestObject(requestBarr);
130: // }
131: // catch(Throwable t)
132: // {
133: // throw new LockRuntimeException("Can't set block timeout value", t);
134: // }
135: }
136:
137: public String getLockInfo() {
138: LockInfo info = new LockInfo(METHOD_LOCK_INFO);
139: try {
140: byte[] requestBarr = serialize(info);
141: return performRequestString(requestBarr);
142: } catch (Throwable t) {
143: throw new LockRuntimeException("Can't get locking info", t);
144: }
145: }
146:
147: public boolean readLock(Object key, Object resourceId,
148: int isolationLevel) {
149: LockInfo info = new LockInfo(key, resourceId, isolationLevel,
150: METHOD_READ_LOCK);
151: try {
152: byte[] requestBarr = serialize(info);
153: return performRequest(requestBarr);
154: } catch (Throwable t) {
155: throw new LockRuntimeException(
156: "Cannot check read lock for '" + resourceId
157: + "' using key '" + key + "'", t);
158: }
159: }
160:
161: public boolean releaseLock(Object key, Object resourceId) {
162: LockInfo info = new LockInfo(key, resourceId,
163: METHOD_RELEASE_SINGLE_LOCK);
164: try {
165: byte[] requestBarr = serialize(info);
166: return performRequest(requestBarr);
167: } catch (Throwable t) {
168: throw new LockRuntimeException(
169: "Cannot remove write lock for '" + resourceId
170: + "' using key '" + key + "'", t);
171: }
172: }
173:
174: // public boolean removeReader(Object key, Object resourceId)
175: // {
176: // LockInfo info = new LockInfo(key, resourceId, METHOD_RELEASE_SINGLE_LOCK);
177: // try
178: // {
179: // byte[] requestBarr = serialize(info);
180: // return performRequest(requestBarr);
181: // }
182: // catch(Throwable t)
183: // {
184: // throw new LockRuntimeException("Cannot remove read lock for '"
185: // + resourceId + "' using key '" + key + "'", t);
186: // }
187: // }
188:
189: public void releaseLocks(Object key) {
190: LockInfo info = new LockInfo(key, null, METHOD_RELEASE_LOCKS);
191: try {
192: byte[] requestBarr = serialize(info);
193: performRequest(requestBarr);
194: } catch (Throwable t) {
195: throw new LockRuntimeException(
196: "Cannot release locks using owner key '" + key
197: + "'", t);
198: }
199: }
200:
201: public boolean writeLock(Object key, Object resourceId,
202: int isolationLevel) {
203: LockInfo info = new LockInfo(key, resourceId, isolationLevel,
204: METHOD_WRITE_LOCK);
205: try {
206: byte[] requestBarr = serialize(info);
207: return performRequest(requestBarr);
208: } catch (Throwable t) {
209: throw new LockRuntimeException(
210: "Cannot set write lock for '" + resourceId
211: + "' using key '" + key + "'", t);
212: }
213: }
214:
215: public boolean upgradeLock(Object key, Object resourceId,
216: int isolationLevel) {
217: LockInfo info = new LockInfo(key, resourceId, isolationLevel,
218: METHOD_UPGRADE_LOCK);
219: try {
220: byte[] requestBarr = serialize(info);
221: return performRequest(requestBarr);
222: } catch (Throwable t) {
223: throw new LockRuntimeException(
224: "Cannot set write lock for '" + resourceId
225: + "' using key '" + key + "'", t);
226: }
227: }
228:
229: public boolean hasRead(Object key, Object resourceId) {
230: try {
231: byte[] requestBarr = serialize(new LockInfo(key,
232: resourceId, METHOD_CHECK_READ));
233: return performRequest(requestBarr);
234: } catch (Throwable t) {
235: throw new LockRuntimeException(
236: "Cannot check read lock for '" + resourceId
237: + "' using key '" + key + "'", t);
238: }
239: }
240:
241: public boolean hasWrite(Object key, Object resourceId) {
242: try {
243: byte[] requestBarr = serialize(new LockInfo(key,
244: resourceId, METHOD_CHECK_WRITE));
245: return performRequest(requestBarr);
246: } catch (Throwable t) {
247: throw new LockRuntimeException(
248: "Cannot check write lock for '" + resourceId
249: + "' using key '" + key + "'", t);
250: }
251: }
252:
253: public boolean hasUpgrade(Object key, Object resourceId) {
254: try {
255: byte[] requestBarr = serialize(new LockInfo(key,
256: resourceId, METHOD_CHECK_UPGRADE));
257: return performRequest(requestBarr);
258: } catch (Throwable t) {
259: throw new LockRuntimeException(
260: "Cannot check write lock for '" + resourceId
261: + "' using key '" + key + "'", t);
262: }
263: }
264:
265: private HttpURLConnection getHttpUrlConnection()
266: throws MalformedURLException, IOException,
267: ProtocolException {
268: URL lockserver = getLockserverUrl();
269: HttpURLConnection conn = (HttpURLConnection) lockserver
270: .openConnection();
271:
272: conn.setDoInput(true);
273: conn.setDoOutput(true);
274: conn.setRequestMethod("POST");
275: conn.setAllowUserInteraction(false);
276: conn.setUseCaches(false);
277: return conn;
278: }
279:
280: private URL getLockserverUrl() {
281: return lockservlet;
282: }
283:
284: public byte[] serialize(Object obj) throws IOException {
285: ByteArrayOutputStream bao = new ByteArrayOutputStream();
286: ObjectOutputStream oos = new ObjectOutputStream(bao);
287: oos.writeObject(obj);
288: oos.close();
289: bao.close();
290: byte[] result = bao.toByteArray();
291: return result;
292: }
293:
294: private boolean performRequest(byte[] requestBarr)
295: throws IOException, ClassNotFoundException {
296: Object result = performRequestObject(requestBarr);
297: if (result instanceof Boolean) {
298: return ((Boolean) result).booleanValue();
299: } else {
300: throw new LockRuntimeException(
301: "Remote lock server error, expect return value of type 'Boolean'");
302: }
303: }
304:
305: private String performRequestString(byte[] requestBarr)
306: throws IOException, ClassNotFoundException {
307: Object result = performRequestObject(requestBarr);
308: if (result instanceof String) {
309: return (String) result;
310: } else {
311: throw new LockRuntimeException(
312: "Remote lock server error, expect return value of type 'String'");
313: }
314: }
315:
316: private long performRequestLong(byte[] requestBarr)
317: throws IOException, ClassNotFoundException {
318: Object result = performRequestObject(requestBarr);
319: if (result instanceof Long) {
320: return ((Long) result).longValue();
321: } else {
322: throw new LockRuntimeException(
323: "Remote lock server error, expect return value of type 'String'");
324: }
325: }
326:
327: private Object performRequestObject(byte[] requestBarr)
328: throws IOException, ClassNotFoundException {
329: HttpURLConnection conn = getHttpUrlConnection();
330:
331: //post request
332: BufferedOutputStream out = new BufferedOutputStream(conn
333: .getOutputStream());
334: out.write(requestBarr, 0, requestBarr.length);
335: out.flush();
336:
337: // read result from
338: InputStream in = conn.getInputStream();
339: ObjectInputStream ois = new ObjectInputStream(in);
340: Object result = ois.readObject();
341:
342: // cleanup
343: ois.close();
344: out.close();
345: conn.disconnect();
346:
347: if (result instanceof Throwable) {
348: throw new LockRuntimeException("Remote lock server error",
349: (Throwable) result);
350: } else {
351: return result;
352: }
353: }
354:
355: public static final class LockInfo implements Serializable {
356: public Object key;
357: public Object resourceId;
358: public int isolationLevel;
359: public byte methodName;
360: public long lockTimeout;
361: public long blockTimeout;
362:
363: public LockInfo(byte methodName) {
364: this .methodName = methodName;
365: }
366:
367: public LockInfo(Object key, Object resourceId, byte methodName) {
368: this .key = key;
369: this .resourceId = resourceId;
370: this .methodName = methodName;
371: }
372:
373: public LockInfo(Object key, Object resourceId,
374: int isolationLevel, byte methodName) {
375: this .key = key;
376: this .resourceId = resourceId;
377: this .isolationLevel = isolationLevel;
378: this .methodName = methodName;
379: }
380:
381: // public LockInfo(long timeout, byte methodName)
382: // {
383: // if(methodName == METHOD_LOCK_TIMEOUT_SET)
384: // {
385: // this.lockTimeout = timeout;
386: // }
387: // else
388: // {
389: // this.blockTimeout = timeout;
390: // }
391: // this.methodName = methodName;
392: // }
393: }
394: }
|