001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tc.net.protocol.tcm;
005:
006: import org.apache.commons.lang.ArrayUtils;
007:
008: import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
009:
010: import com.tc.bytes.TCByteBuffer;
011: import com.tc.io.TCByteBufferOutput;
012: import com.tc.io.TCByteBufferOutputStream;
013: import com.tc.object.session.SessionID;
014: import com.tc.object.session.SessionProvider;
015:
016: import java.lang.reflect.Constructor;
017: import java.util.Map;
018:
019: public class TCMessageFactoryImpl implements TCMessageFactory {
020: private static final Class[] SIG1 = new Class[] { SessionID.class,
021: MessageMonitor.class, TCByteBufferOutput.class,
022: MessageChannel.class, TCMessageType.class };
023: private static final Class[] SIG2 = new Class[] { SessionID.class,
024: MessageMonitor.class, MessageChannel.class,
025: TCMessageHeader.class, TCByteBuffer[].class };
026: private static final TCMessageFinalizer NULL_FINALIZER = new NullFinalizer();
027:
028: private final Map typeOnlyCstr = new ConcurrentReaderHashMap();
029: private final Map typeAndDataCstr = new ConcurrentReaderHashMap();
030: private final TCMessageFinalizer finalizer;
031: private final MessageMonitor monitor;
032: private final SessionProvider sessionProvider;
033:
034: public TCMessageFactoryImpl(SessionProvider sessionProvider,
035: MessageMonitor monitor) {
036: this (sessionProvider, monitor, NULL_FINALIZER);
037: }
038:
039: public TCMessageFactoryImpl(SessionProvider sessionProvider,
040: MessageMonitor monitor, TCMessageFinalizer finalizer) {
041: this .sessionProvider = sessionProvider;
042: this .monitor = monitor;
043: this .finalizer = finalizer;
044: }
045:
046: public TCMessage createMessage(MessageChannel source,
047: TCMessageType type) throws UnsupportedMessageTypeException {
048: return createMessage(lookupConstructor(type, typeOnlyCstr),
049: new Object[] { sessionProvider.getSessionID(), monitor,
050: new TCByteBufferOutputStream(4, 4096, false),
051: source, type });
052: }
053:
054: public TCMessage createMessage(MessageChannel source,
055: TCMessageType type, TCMessageHeader header,
056: TCByteBuffer[] data) {
057: return createMessage(lookupConstructor(type, typeAndDataCstr),
058: new Object[] { sessionProvider.getSessionID(), monitor,
059: source, header, data });
060: }
061:
062: public void addClassMapping(TCMessageType type, Class msgClass) {
063: if ((type == null) || (msgClass == null)) {
064: throw new IllegalArgumentException();
065: }
066:
067: Constructor cstr1 = getConstructor(msgClass, SIG1);
068: Constructor cstr2 = getConstructor(msgClass, SIG2);
069:
070: synchronized (this ) {
071: typeOnlyCstr.put(type, cstr1);
072: typeAndDataCstr.put(type, cstr2);
073: }
074: }
075:
076: private static Constructor lookupConstructor(TCMessageType type,
077: Map map) {
078: Constructor rv = (Constructor) map.get(type);
079: if (rv == null) {
080: throw new RuntimeException("No class registerted for type "
081: + type);
082: }
083: return rv;
084: }
085:
086: private static Constructor getConstructor(Class msgClass,
087: Class[] signature) {
088: try {
089: return msgClass.getDeclaredConstructor(signature);
090: } catch (Exception e) {
091: throw new IllegalArgumentException(e.getClass().getName()
092: + ": " + e.getMessage());
093: }
094: }
095:
096: private TCMessage createMessage(Constructor cstr, Object[] args) {
097: try {
098: TCMessage rv = (TCMessage) cstr.newInstance(args);
099: finalizer.finalizeMessage(rv);
100: return rv;
101: } catch (Exception e) {
102: System.err.println("Args; " + ArrayUtils.toString(args));
103: throw new RuntimeException(e);
104: }
105: }
106:
107: private static final class NullFinalizer implements
108: TCMessageFinalizer {
109: public final void finalizeMessage(TCMessage message) {
110: return;
111: }
112: }
113:
114: }
|