1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.cluster;
16  
17  import com.liferay.portal.kernel.cluster.Address;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.util.CharPool;
21  import com.liferay.portal.kernel.util.GetterUtil;
22  import com.liferay.portal.kernel.util.IPDetector;
23  import com.liferay.portal.kernel.util.OSDetector;
24  import com.liferay.portal.kernel.util.SocketUtil;
25  import com.liferay.portal.kernel.util.StringBundler;
26  import com.liferay.portal.kernel.util.Validator;
27  import com.liferay.portal.util.PropsValues;
28  
29  import java.io.IOException;
30  
31  import java.net.InetAddress;
32  import java.net.NetworkInterface;
33  
34  import java.util.ArrayList;
35  import java.util.Collections;
36  import java.util.List;
37  import java.util.Vector;
38  
39  import org.jgroups.ChannelException;
40  import org.jgroups.JChannel;
41  import org.jgroups.Receiver;
42  import org.jgroups.View;
43  
44  /**
45   * <a href="ClusterBase.java.html"><b><i>View Source</i></b></a>
46   *
47   * @author Shuyang Zhou
48   */
49  public abstract class ClusterBase {
50  
51      public void afterPropertiesSet() {
52          if (!isEnabled()) {
53              return;
54          }
55  
56          if (!_initialized) {
57              if (OSDetector.isUnix() && IPDetector.isSupportsV6() &&
58                  !IPDetector.isPrefersV4() && _log.isWarnEnabled()) {
59  
60                  StringBundler sb = new StringBundler(4);
61  
62                  sb.append(
63                      "You are on an Unix server with IPv6 enabled. JGroups ");
64                  sb.append("may not work with IPv6. If you see a multicast ");
65                  sb.append("error, try adding java.net.preferIPv4Stack=true ");
66                  sb.append("as a JVM startup parameter.");
67  
68                  _log.warn(sb.toString());
69              }
70  
71              initSystemProperties();
72  
73              try {
74                  initBindAddress();
75              }
76              catch (IOException ioe) {
77                  if (_log.isWarnEnabled()) {
78                      _log.warn("Failed to initialize outgoing IP address", ioe);
79                  }
80              }
81              _initialized = true;
82          }
83  
84          try {
85              initChannels();
86          }
87          catch (Exception e) {
88              if (_log.isErrorEnabled()) {
89                  _log.error("Unable to initialize channels", e);
90              }
91  
92              throw new IllegalStateException(e);
93          }
94      }
95  
96      public abstract void destroy();
97  
98      public boolean isEnabled() {
99          return PropsValues.CLUSTER_LINK_ENABLED;
100     }
101 
102     protected JChannel createJChannel(
103             String properties, Receiver receiver, String clusterName)
104         throws ChannelException {
105 
106         JChannel jChannel = new JChannel(properties);
107 
108         jChannel.setReceiver(receiver);
109 
110         jChannel.connect(clusterName);
111 
112         if (_log.isInfoEnabled()) {
113             _log.info(
114                 "Create a new channel with properties " +
115                     jChannel.getProperties());
116         }
117 
118         return jChannel;
119     }
120 
121     protected List<Address> getAddresses(JChannel channel) {
122         View view = channel.getView();
123 
124         Vector<org.jgroups.Address> jGroupsAddresses = view.getMembers();
125 
126         if (jGroupsAddresses == null) {
127             return Collections.EMPTY_LIST;
128         }
129 
130         List<Address> addresses = new ArrayList<Address>(
131             jGroupsAddresses.size());
132 
133         for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
134             addresses.add(new AddressImpl(jgroupsAddress));
135         }
136 
137         return addresses;
138     }
139 
140     protected void initBindAddress() throws IOException {
141         String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
142 
143         if (Validator.isNull(autodetectAddress)) {
144             return;
145         }
146 
147         String host = autodetectAddress;
148         int port = 80;
149 
150         int index = autodetectAddress.indexOf(CharPool.COLON);
151 
152         if (index != -1) {
153             host = autodetectAddress.substring(0, index);
154             port = GetterUtil.getInteger(
155                 autodetectAddress.substring(index + 1), port);
156         }
157 
158         if (_log.isInfoEnabled()) {
159             _log.info(
160                 "Autodetecting JGroups outgoing IP address and interface for " +
161                     host + ":" + port);
162         }
163 
164         SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
165 
166         bindInetAddress = bindInfo.getInetAddress();
167         NetworkInterface networkInterface = bindInfo.getNetworkInterface();
168 
169         System.setProperty(
170             "jgroups.bind_addr", bindInetAddress.getHostAddress());
171         System.setProperty(
172             "jgroups.bind_interface", networkInterface.getName());
173 
174         if (_log.isInfoEnabled()) {
175             _log.info(
176                 "Setting JGroups outgoing IP address to " +
177                     bindInetAddress.getHostAddress() + " and interface to " +
178                         networkInterface.getName());
179         }
180     }
181 
182     protected abstract void initChannels() throws ChannelException;
183 
184     protected void initSystemProperties() {
185         for (String systemProperty :
186                 PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
187 
188             int index = systemProperty.indexOf(CharPool.COLON);
189 
190             if (index == -1) {
191                 continue;
192             }
193 
194             String key = systemProperty.substring(0, index);
195             String value = systemProperty.substring(index + 1);
196 
197             System.setProperty(key, value);
198 
199             if (_log.isDebugEnabled()) {
200                 _log.debug(
201                     "Setting system property {key=" + key + ", value=" + value +
202                         "}");
203             }
204         }
205     }
206 
207     private static Log _log = LogFactoryUtil.getLog(ClusterBase.class);
208 
209     private static boolean _initialized;
210 
211     protected InetAddress bindInetAddress;
212 
213 }