001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cluster;
016    
017    import com.liferay.portal.kernel.cluster.Address;
018    import com.liferay.portal.kernel.io.Serializer;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.InetAddressUtil;
024    import com.liferay.portal.kernel.util.SocketUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.util.PropsValues;
027    
028    import java.io.Serializable;
029    
030    import java.net.InetAddress;
031    import java.net.NetworkInterface;
032    
033    import java.nio.ByteBuffer;
034    
035    import java.util.ArrayList;
036    import java.util.Collections;
037    import java.util.List;
038    
039    import org.jgroups.JChannel;
040    import org.jgroups.Receiver;
041    import org.jgroups.View;
042    
043    /**
044     * @author Shuyang Zhou
045     */
046    public abstract class ClusterBase {
047    
048            public void afterPropertiesSet() {
049                    if (!isEnabled()) {
050                            return;
051                    }
052    
053                    if (!_initialized) {
054                            initSystemProperties();
055    
056                            try {
057                                    initBindAddress();
058                            }
059                            catch (Exception e) {
060                                    if (_log.isWarnEnabled()) {
061                                            _log.warn("Failed to initialize outgoing IP address", e);
062                                    }
063                            }
064    
065                            _initialized = true;
066                    }
067    
068                    try {
069                            initChannels();
070                    }
071                    catch (Exception e) {
072                            if (_log.isErrorEnabled()) {
073                                    _log.error("Unable to initialize channels", e);
074                            }
075    
076                            throw new IllegalStateException(e);
077                    }
078            }
079    
080            public abstract void destroy();
081    
082            public boolean isEnabled() {
083                    return PropsValues.CLUSTER_LINK_ENABLED;
084            }
085    
086            protected void sendJGroupsMessage(
087                            JChannel jChannel, org.jgroups.Address destAddress,
088                            Serializable serializable)
089                    throws Exception {
090    
091                    Serializer serializer = new Serializer();
092    
093                    serializer.writeObject(serializable);
094    
095                    ByteBuffer byteBuffer = serializer.toByteBuffer();
096    
097                    jChannel.send(
098                            destAddress, byteBuffer.array(), byteBuffer.position(),
099                            byteBuffer.remaining());
100    
101                    if (_log.isDebugEnabled()) {
102                            _log.debug("Send message " + serializable);
103                    }
104            }
105    
106            protected JChannel createJChannel(
107                            String properties, Receiver receiver, String clusterName)
108                    throws Exception {
109    
110                    JChannel jChannel = new JChannel(properties);
111    
112                    jChannel.setReceiver(receiver);
113    
114                    jChannel.connect(clusterName);
115    
116                    if (_log.isInfoEnabled()) {
117                            _log.info(
118                                    "Create a new channel with properties " +
119                                            jChannel.getProperties());
120                    }
121    
122                    return jChannel;
123            }
124    
125            protected List<Address> getAddresses(JChannel channel) {
126                    BaseReceiver baseReceiver = (BaseReceiver)channel.getReceiver();
127    
128                    View view = baseReceiver.getView();
129    
130                    List<org.jgroups.Address> jGroupsAddresses = view.getMembers();
131    
132                    if (jGroupsAddresses == null) {
133                            return Collections.emptyList();
134                    }
135    
136                    List<Address> addresses = new ArrayList<Address>(
137                            jGroupsAddresses.size());
138    
139                    for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
140                            addresses.add(new AddressImpl(jgroupsAddress));
141                    }
142    
143                    return addresses;
144            }
145    
146            protected void initBindAddress() throws Exception {
147                    String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
148    
149                    if (Validator.isNull(autodetectAddress)) {
150                            bindInetAddress = InetAddressUtil.getLocalInetAddress();
151    
152                            return;
153                    }
154    
155                    String host = autodetectAddress;
156                    int port = 80;
157    
158                    int index = autodetectAddress.indexOf(CharPool.COLON);
159    
160                    if (index != -1) {
161                            host = autodetectAddress.substring(0, index);
162                            port = GetterUtil.getInteger(
163                                    autodetectAddress.substring(index + 1), port);
164                    }
165    
166                    if (_log.isInfoEnabled()) {
167                            _log.info(
168                                    "Autodetecting JGroups outgoing IP address and interface for " +
169                                            host + ":" + port);
170                    }
171    
172                    SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
173    
174                    bindInetAddress = bindInfo.getInetAddress();
175                    NetworkInterface networkInterface = bindInfo.getNetworkInterface();
176    
177                    System.setProperty(
178                            "jgroups.bind_addr", bindInetAddress.getHostAddress());
179                    System.setProperty(
180                            "jgroups.bind_interface", networkInterface.getName());
181    
182                    if (_log.isInfoEnabled()) {
183                            _log.info(
184                                    "Setting JGroups outgoing IP address to " +
185                                            bindInetAddress.getHostAddress() + " and interface to " +
186                                                    networkInterface.getName());
187                    }
188            }
189    
190            protected abstract void initChannels() throws Exception;
191    
192            protected void initSystemProperties() {
193                    for (String systemProperty :
194                                    PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
195    
196                            int index = systemProperty.indexOf(CharPool.COLON);
197    
198                            if (index == -1) {
199                                    continue;
200                            }
201    
202                            String key = systemProperty.substring(0, index);
203                            String value = systemProperty.substring(index + 1);
204    
205                            System.setProperty(key, value);
206    
207                            if (_log.isDebugEnabled()) {
208                                    _log.debug(
209                                            "Setting system property {key=" + key + ", value=" + value +
210                                                    "}");
211                            }
212                    }
213            }
214    
215            protected static InetAddress bindInetAddress;
216    
217            private static Log _log = LogFactoryUtil.getLog(ClusterBase.class);
218    
219            private static boolean _initialized;
220    
221    }