View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.connector.infinispan;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ObjectInputStream;
28  import java.util.Enumeration;
29  import java.util.HashMap;
30  import java.util.Hashtable;
31  import java.util.List;
32  import java.util.Map;
33  import javax.naming.BinaryRefAddr;
34  import javax.naming.Context;
35  import javax.naming.RefAddr;
36  import javax.naming.Reference;
37  import javax.naming.Referenceable;
38  import javax.naming.StringRefAddr;
39  import net.jcip.annotations.ThreadSafe;
40  import org.infinispan.client.hotrod.RemoteCacheManager;
41  import org.infinispan.manager.CacheContainer;
42  import org.modeshape.common.annotation.Category;
43  import org.modeshape.common.annotation.Description;
44  import org.modeshape.common.annotation.Label;
45  import org.modeshape.common.util.HashCode;
46  import org.modeshape.common.util.StringUtil;
47  import org.modeshape.graph.cache.CachePolicy;
48  import org.modeshape.graph.connector.RepositorySource;
49  
50  /**
51   * A repository source that uses an Infinispan instance to manage the content. This source is capable of using an existing
52   * {@link CacheContainer} or creating a new cache container. This process is controlled entirely by the JavaBean properties of the
53   * InfinispanSource instance.
54   * <p>
55   * This source attempts to use the {@link RemoteCacheManager} with the supplied {@link #getRemoteInfinispanServerList() server
56   * list}.
57   * </p>
58   * <p>
59   * Like other {@link RepositorySource} classes, instances of RemoteInfinispanCacheSource can be placed into JNDI and do support
60   * the creation of {@link Referenceable JNDI referenceable} objects and resolution of references into JBossCacheSource.
61   * </p>
62   */
63  @ThreadSafe
64  public class RemoteInfinispanSource extends BaseInfinispanSource {
65      private static final long serialVersionUID = 1L;
66  
67      protected static final String INFINISPAN_SERVER_LIST = "remoteInfinispanServerList";
68  
69      @Description( i18n = InfinispanConnectorI18n.class, value = "remoteInfinispanServerListPropertyDescription" )
70      @Label( i18n = InfinispanConnectorI18n.class, value = "remoteInfinispanServerListPropertyLabel" )
71      @Category( i18n = InfinispanConnectorI18n.class, value = "remoteInfinispanServerListPropertyCategory" )
72      private volatile String remoteInfinispanServerList;
73  
74      /**
75       * Get the list of remote servers that make up the Infinispan cluster. The servers must be Infinispan HotRod servers. The list
76       * must be in the appropriate format of <code>host:port[;host:port...]</code> that would be used when defining an Infinispan
77       * {@link RemoteCacheManager} instance. If the value is missing, <code>localhost:11311</code> is assumed.
78       * 
79       * @return the names of the remote servers
80       */
81      public String getRemoteInfinispanServerList() {
82          return remoteInfinispanServerList;
83      }
84  
85      /**
86       * Set the list of remote servers that make up the Infinispan cluster. The servers must be Infinispan HotRod servers. The list
87       * must be in the appropriate format of <code>host:port[;host:port...]</code> that would be used when defining an Infinispan
88       * {@link RemoteCacheManager} instance. If the value is missing, <code>localhost:11311</code> is assumed.
89       * 
90       * @param remoteInfinispanServerList the server list in appropriate <code>server:port;server2:port2</code> format.
91       */
92      public synchronized void setRemoteInfinispanServerList( String remoteInfinispanServerList ) {
93          if (this.remoteInfinispanServerList == remoteInfinispanServerList || this.remoteInfinispanServerList != null
94              && this.remoteInfinispanServerList.equals(remoteInfinispanServerList)) return; // unchanged
95          this.remoteInfinispanServerList = remoteInfinispanServerList;
96      }
97  
98      @Override
99      protected CacheContainer createCacheContainer() {
100         if (this.getRemoteInfinispanServerList() == null || this.getRemoteInfinispanServerList().equals("")) {
101             return new RemoteCacheManager();
102         }
103         return new RemoteCacheManager(this.getRemoteInfinispanServerList());
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
109     @Override
110     public synchronized Reference getReference() {
111         Reference ref = super.getReference();
112         ref.add(new StringRefAddr(INFINISPAN_SERVER_LIST, getRemoteInfinispanServerList()));
113         return ref;
114     }
115 
116     /**
117      * {@inheritDoc}
118      */
119     @Override
120     public Object getObjectInstance( Object obj,
121                                      javax.naming.Name name,
122                                      Context nameCtx,
123                                      Hashtable<?, ?> environment ) throws Exception {
124         if (obj instanceof Reference) {
125             Map<String, Object> values = new HashMap<String, Object>();
126             Reference ref = (Reference)obj;
127             Enumeration<?> en = ref.getAll();
128             while (en.hasMoreElements()) {
129                 RefAddr subref = (RefAddr)en.nextElement();
130                 if (subref instanceof StringRefAddr) {
131                     String key = subref.getType();
132                     Object value = subref.getContent();
133                     if (value != null) values.put(key, value.toString());
134                 } else if (subref instanceof BinaryRefAddr) {
135                     String key = subref.getType();
136                     Object value = subref.getContent();
137                     if (value instanceof byte[]) {
138                         // Deserialize ...
139                         ByteArrayInputStream bais = new ByteArrayInputStream((byte[])value);
140                         ObjectInputStream ois = new ObjectInputStream(bais);
141                         value = ois.readObject();
142                         values.put(key, value);
143                     }
144                 }
145             }
146             String sourceName = (String)values.get(SOURCE_NAME);
147             String rootNodeUuidString = (String)values.get(ROOT_NODE_UUID);
148             String remoteServerList = (String)values.get(INFINISPAN_SERVER_LIST);
149             Object defaultCachePolicy = values.get(DEFAULT_CACHE_POLICY);
150             String retryLimit = (String)values.get(RETRY_LIMIT);
151             String defaultWorkspace = (String)values.get(DEFAULT_WORKSPACE);
152             String createWorkspaces = (String)values.get(ALLOW_CREATING_WORKSPACES);
153             String updatesAllowed = (String)values.get(UPDATES_ALLOWED);
154 
155             String combinedWorkspaceNames = (String)values.get(PREDEFINED_WORKSPACE_NAMES);
156             String[] workspaceNames = null;
157             if (combinedWorkspaceNames != null) {
158                 List<String> paths = StringUtil.splitLines(combinedWorkspaceNames);
159                 workspaceNames = paths.toArray(new String[paths.size()]);
160             }
161 
162             // Create the source instance ...
163             RemoteInfinispanSource source = new RemoteInfinispanSource();
164             if (sourceName != null) source.setName(sourceName);
165             if (rootNodeUuidString != null) source.setRootNodeUuid(rootNodeUuidString);
166             if (remoteServerList != null) source.setRemoteInfinispanServerList(remoteServerList);
167             if (defaultCachePolicy instanceof CachePolicy) {
168                 source.setDefaultCachePolicy((CachePolicy)defaultCachePolicy);
169             }
170             if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
171             if (defaultWorkspace != null) source.setDefaultWorkspaceName(defaultWorkspace);
172             if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces));
173             if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames);
174             if (updatesAllowed != null) source.setUpdatesAllowed(Boolean.valueOf(updatesAllowed));
175             return source;
176         }
177         return null;
178     }
179 
180     /**
181      * {@inheritDoc}
182      */
183     @Override
184     public boolean equals( Object obj ) {
185         if (obj == this) return true;
186         if (obj instanceof RemoteInfinispanSource) {
187             RemoteInfinispanSource that = (RemoteInfinispanSource)obj;
188             if (this.getName() == null) {
189                 if (that.getName() != null) return false;
190             } else {
191                 if (!this.getName().equals(that.getName())) return false;
192             }
193             return true;
194         }
195         return false;
196     }
197 
198     @Override
199     public int hashCode() {
200         return HashCode.compute(getName());
201     }
202 
203 }