VirtualConnection.java 6.56 KB
Newer Older
1
/*
2
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
Gaston Dombiak's avatar
Gaston Dombiak committed
3
 *
4 5 6 7 8 9 10 11 12 13 14
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
Gaston Dombiak's avatar
Gaston Dombiak committed
15 16
 */

17
package org.jivesoftware.openfire.net;
Gaston Dombiak's avatar
Gaston Dombiak committed
18

19 20 21
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.Map;
22
import java.util.concurrent.atomic.AtomicReference;
23

24 25 26
import org.jivesoftware.openfire.Connection;
import org.jivesoftware.openfire.ConnectionCloseListener;
import org.jivesoftware.openfire.PacketDeliverer;
27
import org.jivesoftware.openfire.session.LocalSession;
28
import org.jivesoftware.openfire.session.Session;
29
import org.jivesoftware.openfire.spi.ConnectionConfiguration;
30
import org.jivesoftware.util.LocaleUtils;
31 32
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Gaston Dombiak's avatar
Gaston Dombiak committed
33 34 35 36 37 38 39 40 41 42 43 44 45

/**
 * Abstract implementation of the Connection interface that models abstract connections. Abstract
 * connections are connections that don't have a physical connection counterpart. Instead they
 * can be seen as conceptual or just 'abstract' connections.<p>
 *
 * Default values and common behavior of virtual connections are modeled in this class. Subclasses
 * should just need to specify how packets are delivered and what means closing the connection.
 *
 * @author Gaston Dombiak
 */
public abstract class VirtualConnection implements Connection {

46 47
	private static final Logger Log = LoggerFactory.getLogger(VirtualConnection.class);

48
    protected LocalSession session;
Gaston Dombiak's avatar
Gaston Dombiak committed
49 50

    final private Map<ConnectionCloseListener, Object> listeners =
51
            new HashMap<>();
Gaston Dombiak's avatar
Gaston Dombiak committed
52

53
   private AtomicReference<State> state = new AtomicReference<State>(State.OPEN);
Gaston Dombiak's avatar
Gaston Dombiak committed
54

55
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
56 57 58 59 60
    public int getMajorXMPPVersion() {
        // Information not available. Return any value. This is not actually used.
        return 0;
    }

61
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
62 63 64 65 66
    public int getMinorXMPPVersion() {
        // Information not available. Return any value. This is not actually used.
        return 0;
    }

67
    @Override
68 69 70 71 72
    public Certificate[] getLocalCertificates() {
        // Ignore
        return new Certificate[0];
    }

73
    @Override
74
    public Certificate[] getPeerCertificates() {
75
        // Ignore
76
        return new Certificate[0];
77 78
    }

79
    @Override
80 81 82
    public void setUsingSelfSignedCertificate(boolean isSelfSigned) {
    }

83
    @Override
84 85 86 87
    public boolean isUsingSelfSignedCertificate() {
        return false;
    }

88
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
89
    public boolean isClosed() {
90
    	return state.get() == State.CLOSED;
Gaston Dombiak's avatar
Gaston Dombiak committed
91 92
    }

93
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
94 95 96 97 98
    public Connection.CompressionPolicy getCompressionPolicy() {
        // Return null since compression is not used for virtual connections
        return null;
    }

99
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
100 101 102 103 104
    public Connection.TLSPolicy getTlsPolicy() {
        // Return null since TLS is not used for virtual connections
        return null;
    }

105
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
106 107 108 109 110
    public boolean isCompressed() {
        // Return false since compression is not used for virtual connections
        return false;
    }

111
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
112 113 114 115 116
    public boolean isFlashClient() {
        // Return false since flash clients is not used for virtual connections
        return false;
    }

117
    @Override
118 119 120 121
    public void setFlashClient(boolean flashClient) {
        //Ignore
    }

122
    @Override
123 124 125 126
    public void setXMPPVersion(int majorVersion, int minorVersion) {
        //Ignore
    }

127
    @Override
128 129 130 131
    public void setCompressionPolicy(CompressionPolicy compressionPolicy) {
        //Ignore
    }

132
    @Override
133 134 135 136
    public void setTlsPolicy(TLSPolicy tlsPolicy) {
        //Ignore
    }

137
    @Override
138 139 140 141 142
    public PacketDeliverer getPacketDeliverer() {
        //Ignore
        return null;
    }

143
    @Deprecated
144
    @Override
145
    public void startTLS(boolean clientMode, String remoteServer, ClientAuth authentication) throws Exception {
146 147 148
        //Ignore
    }

149 150 151
    public void startTLS(boolean clientMode) throws Exception {
        //Ignore
    }
152

153 154 155 156
    public void addCompression() {
        //Ignore
    }

157
    @Override
158 159 160 161
    public void startCompression() {
        //Ignore
    }

162
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
163 164 165 166 167
    public boolean isSecure() {
        // Return false since TLS is not used for virtual connections
        return false;
    }

168
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
169 170 171 172 173
    public boolean validate() {
        // Return true since the virtual connection is valid until it no longer exists
        return true;
    }

174
    @Override
175
    public void init(LocalSession session) {
Gaston Dombiak's avatar
Gaston Dombiak committed
176 177 178 179 180 181 182
        this.session = session;
    }

    /**
     * Closes the session, the virtual connection and notifies listeners that the connection
     * has been closed.
     */
183
    @Override
Gaston Dombiak's avatar
Gaston Dombiak committed
184
    public void close() {
185 186
    	if (state.compareAndSet(State.OPEN, State.CLOSED)) {
    		
187 188
            if (session != null) {
                session.setStatus(Session.STATUS_CLOSED);
Gaston Dombiak's avatar
Gaston Dombiak committed
189
            }
190 191 192 193 194 195 196 197 198
            
            try {
                closeVirtualConnection();
            } catch (Exception e) {
                Log.error(LocaleUtils.getLocalizedString("admin.error.close") + "\n" + toString(), e);
            }
            
            notifyCloseListeners();
            
Gaston Dombiak's avatar
Gaston Dombiak committed
199 200 201
        }
    }

202
    @Override
203
    public void registerCloseListener(ConnectionCloseListener listener, Object handbackMessage) {
Gaston Dombiak's avatar
Gaston Dombiak committed
204 205 206 207
        if (isClosed()) {
            listener.onConnectionClose(handbackMessage);
        }
        else {
208
            listeners.put(listener, handbackMessage);
Gaston Dombiak's avatar
Gaston Dombiak committed
209 210 211
        }
    }

212
    @Override
213 214
    public void removeCloseListener(ConnectionCloseListener listener) {
        listeners.remove(listener);
Gaston Dombiak's avatar
Gaston Dombiak committed
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    }

    /**
     * Notifies all close listeners that the connection has been closed.
     */
    private void notifyCloseListeners() {
        synchronized (listeners) {
            for (ConnectionCloseListener listener : listeners.keySet()) {
                try {
                    listener.onConnectionClose(listeners.get(listener));
                }
                catch (Exception e) {
                    Log.error("Error notifying listener: " + listener, e);
                }
            }
        }
    }

    /**
     * Closes the virtual connection. Subsclasses should indicate what closing a virtual
     * connection means. At this point the session has a CLOSED state.
     */
    public abstract void closeVirtualConnection();
}