1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
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.GetterUtil;
21  import com.liferay.portal.kernel.util.IPDetector;
22  import com.liferay.portal.kernel.util.OSDetector;
23  import com.liferay.portal.kernel.util.SocketUtil;
24  import com.liferay.portal.kernel.util.StringBundler;
25  import com.liferay.portal.kernel.util.StringPool;
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 (!PropsValues.CLUSTER_LINK_ENABLED) {
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              _log.error(e, e);
89          }
90      }
91  
92      public abstract void destroy();
93  
94      public boolean isEnabled() {
95          return PropsValues.CLUSTER_LINK_ENABLED;
96      }
97  
98      protected JChannel createChannel(
99              String properties, Receiver receiver, String clusterName)
100         throws ChannelException {
101 
102         JChannel channel = new JChannel(properties);
103 
104         channel.setReceiver(receiver);
105 
106         channel.connect(clusterName);
107 
108         if (_log.isInfoEnabled()) {
109             _log.info(
110                 "Create a new channel with properties " +
111                     channel.getProperties());
112         }
113 
114         return channel;
115     }
116 
117     protected List<Address> getAddresses(JChannel channel) {
118         View view = channel.getView();
119 
120         Vector<org.jgroups.Address> jGroupsAddresses = view.getMembers();
121 
122         if (jGroupsAddresses == null) {
123             return Collections.EMPTY_LIST;
124         }
125 
126         List<Address> addresses = new ArrayList<Address>(
127             jGroupsAddresses.size());
128 
129         for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
130             addresses.add(new AddressImpl(jgroupsAddress));
131         }
132 
133         return addresses;
134     }
135 
136     protected void initBindAddress() throws IOException {
137         String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
138 
139         if (Validator.isNull(autodetectAddress)) {
140             return;
141         }
142 
143         String host = autodetectAddress;
144         int port = 80;
145 
146         int index = autodetectAddress.indexOf(StringPool.COLON);
147 
148         if (index != -1) {
149             host = autodetectAddress.substring(0, index);
150             port = GetterUtil.getInteger(
151                 autodetectAddress.substring(index + 1), port);
152         }
153 
154         if (_log.isInfoEnabled()) {
155             _log.info(
156                 "Autodetecting JGroups outgoing IP address and interface for " +
157                     host + ":" + port);
158         }
159 
160         SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
161 
162         InetAddress inetAddress = bindInfo.getInetAddress();
163         NetworkInterface networkInterface = bindInfo.getNetworkInterface();
164 
165         System.setProperty("jgroups.bind_addr", inetAddress.getHostAddress());
166         System.setProperty(
167             "jgroups.bind_interface", networkInterface.getName());
168 
169         if (_log.isInfoEnabled()) {
170             _log.info(
171                 "Setting JGroups outgoing IP address to " +
172                     inetAddress.getHostAddress() + " and interface to " +
173                         networkInterface.getName());
174         }
175     }
176 
177     protected abstract void initChannels() throws ChannelException;
178 
179     protected void initSystemProperties() {
180         for (String systemProperty :
181                 PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
182 
183             int index = systemProperty.indexOf(StringPool.COLON);
184 
185             if (index == -1) {
186                 continue;
187             }
188 
189             String key = systemProperty.substring(0, index);
190             String value = systemProperty.substring(index + 1);
191 
192             System.setProperty(key, value);
193 
194             if (_log.isDebugEnabled()) {
195                 _log.debug(
196                     "Setting system property {key=" + key + ", value=" + value +
197                         "}");
198             }
199         }
200     }
201 
202     private static Log _log = LogFactoryUtil.getLog(ClusterBase.class);
203 
204     private static boolean _initialized;
205 
206 }