KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > interceptors > OptimisticCreateIfNotExistsInterceptor


1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.cache.interceptors;
8
9 import org.jboss.cache.CacheException;
10 import org.jboss.cache.CacheSPI;
11 import org.jboss.cache.Fqn;
12 import org.jboss.cache.GlobalTransaction;
13 import org.jboss.cache.InvocationContext;
14 import org.jboss.cache.NodeSPI;
15 import org.jboss.cache.OptimisticTransactionEntry;
16 import org.jboss.cache.TransactionEntry;
17 import org.jboss.cache.factories.NodeFactory;
18 import org.jboss.cache.marshall.MethodCall;
19 import org.jboss.cache.marshall.MethodDeclarations;
20 import org.jboss.cache.notifications.Notifier;
21 import org.jboss.cache.optimistic.DataVersion;
22 import org.jboss.cache.optimistic.TransactionWorkspace;
23 import org.jboss.cache.optimistic.WorkspaceNode;
24
25 import java.util.ArrayList JavaDoc;
26 import java.util.List JavaDoc;
27
28 /**
29  * Used to make copies of nodes from the main tree into the {@see TransactionWorkspace} as and when needed.
30  *
31  * @author <a HREF="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
32  * @author <a HREF="mailto:stevew@jofti.com">Steve Woodcock (stevew@jofti.com)</a>
33  */

34 public class OptimisticCreateIfNotExistsInterceptor extends OptimisticInterceptor
35 {
36    private NodeFactory nodeFactory;
37
38    public void setCache(CacheSPI cache)
39    {
40       super.setCache(cache);
41       nodeFactory = cache.getConfiguration().getRuntimeConfig().getNodeFactory();
42    }
43
44    public Object JavaDoc invoke(MethodCall m) throws Throwable JavaDoc
45    {
46
47       //should this be just put methods
48
if (MethodDeclarations.isPutMethod(m.getMethodId()))
49       {
50          Object JavaDoc[] args = m.getArgs();
51          Fqn fqn = (Fqn) (args != null ? args[1] : null);
52
53          if (!cache.getRoot().hasChild(fqn))
54          {
55             createNode(fqn, false);
56          }
57       }
58       else if (m.getMethodId() == MethodDeclarations.moveMethodLocal_id)
59       {
60          Object JavaDoc[] args = m.getArgs();
61          move((Fqn) args[0], (Fqn) args[1]);
62       }
63
64       return super.invoke(m);
65    }
66
67    private void move(Fqn nodeFqn, Fqn newParent)
68    {
69       List JavaDoc<Fqn> fqns = new ArrayList JavaDoc<Fqn>();
70       fqns.add(newParent);
71
72       // peek into Node and get a hold of all child fqns as these need to be in the workspace.
73
NodeSPI node = cache.peek(nodeFqn);
74       greedyGetFqns(fqns, node, newParent);
75
76
77       if (log.isTraceEnabled()) log.trace("Adding Fqns to workspace " + fqns);
78
79
80       for (Fqn f : fqns)
81       {
82          if (!cache.getRoot().hasChild(f)) createNode(f, true);
83       }
84    }
85
86    /**
87     * The only method that should be creating nodes.
88     *
89     * @param fqn
90     * @throws CacheException
91     */

92    private void createNode(Fqn fqn, boolean suppressNotification) throws CacheException
93    {
94       // we do nothing if fqn is null
95
if (fqn == null) return;
96
97       // get the transaction to create the nodes in
98
GlobalTransaction gtx = cache.getInvocationContext().getGlobalTransaction();
99       TransactionEntry baseTransactionEntry = txTable.get(gtx);
100       OptimisticTransactionEntry transactionEntry = (OptimisticTransactionEntry) baseTransactionEntry;
101
102       if (transactionEntry == null)
103       {
104          throw new CacheException("Unable to map global transaction " + gtx + " to transaction entry");
105       }
106
107       WorkspaceNode workspaceNode, childWorkspaceNode;
108       Object JavaDoc childName;
109
110       List JavaDoc<Fqn> nodesCreated = new ArrayList JavaDoc<Fqn>();
111       // how many levels do we have?
112
int treeNodeSize = fqn.size();
113
114       InvocationContext ctx = cache.getInvocationContext();
115
116       // try and get the root from the transaction
117
TransactionWorkspace workspace = transactionEntry.getTransactionWorkSpace();
118
119       boolean debug = log.isDebugEnabled();
120       synchronized (workspace)
121       {
122          DataVersion version = null;
123          if (ctx.getOptionOverrides() != null && ctx.getOptionOverrides().getDataVersion() != null)
124          {
125             version = ctx.getOptionOverrides().getDataVersion();
126             workspace.setVersioningImplicit(false);
127          }
128
129          workspaceNode = workspace.getNode(Fqn.ROOT);
130          if (debug) log.debug("Global TX: " + gtx + " Root: " + workspaceNode);
131
132          // we do not have the root so lets wrap it in case we need to add it
133
// to the transaction
134
if (workspaceNode == null)
135          {
136             NodeSPI node = cache.getRoot();
137             workspaceNode = nodeFactory.createWorkspaceNode(node, workspace);
138             workspace.addNode(workspaceNode);
139             if (debug) log.debug("Created root node: " + workspaceNode);
140          }
141          else
142          {
143             if (debug) log.debug("Found root node: " + workspaceNode);
144          }
145
146          // we will always have one root node here, by this stage
147
Fqn tmpFqn = Fqn.ROOT;
148          for (int i = 0; i < treeNodeSize; i++)
149          {
150             boolean isTargetFqn = (i == (treeNodeSize - 1));
151             childName = fqn.get(i);
152
153             // build up intermediate node fqn from original Fqn
154
tmpFqn = new Fqn(tmpFqn, childName);
155
156             // current workspace node canot be null.
157
// try and get the child of current node
158

159             if (debug)
160             {
161                log.debug("workspaceNode.getChild(" + childName + ")");
162             }
163             NodeSPI tempchildNode = workspaceNode.getChild(new Fqn(childName));
164
165             // if (log.isDebugEnabled()) log.debug(" Entered synchronized workspaceNode " + workspaceNode + " access for gtx " + gtx);
166

167             // no child exists with this name
168
if (tempchildNode == null)
169             {
170                if (debug) log.debug("Creating new child, doesn't exist");
171                // we put the parent node into the workspace as we are changing it's children
172
WorkspaceNode tempCheckWrapper = workspace.getNode(workspaceNode.getFqn());
173                if (tempCheckWrapper == null || tempCheckWrapper.isDeleted())
174                {
175                   //add a new one or overwrite an existing one that has been deleted
176
if (debug)
177                   {
178                      log.debug("Parent node doesn't exist in workspace or has been deleted. Adding to workspace.");
179                   }
180                   workspace.addNode(workspaceNode);
181                }
182                else
183                {
184                   if (debug)
185                   {
186                      log.debug("Parent node exists: " + workspaceNode);
187                   }
188                }
189                // this does not add it into the real child nodes - but in its
190
// local child map for the transaction
191

192                // get the version passed in, if we need to use explicit versioning.
193
DataVersion versionToPassIn = null;
194                if (isTargetFqn && !workspace.isVersioningImplicit())
195                {
196                   versionToPassIn = version;
197                }
198
199                NodeSPI tempNode = workspaceNode.createChild(childName, workspaceNode.getNode(), cache, versionToPassIn);
200
201                childWorkspaceNode = nodeFactory.createWorkspaceNode(tempNode, workspace);
202                childWorkspaceNode.setVersioningImplicit(versionToPassIn == null || !isTargetFqn);
203                if (log.isTraceEnabled())
204                {
205                   log.trace("setting versioning of " + childWorkspaceNode.getFqn() + " to be " + (childWorkspaceNode.isVersioningImplicit() ? "implicit" : "explicit"));
206                }
207
208                // now add the wrapped child node into the transaction space
209
workspace.addNode(childWorkspaceNode);
210                childWorkspaceNode.markAsCreated();
211                // save in list so we can broadcast our created nodes outside
212
// the synch block
213
nodesCreated.add(tmpFqn);
214
215             }
216             else
217             {
218                // node does exist but might not be in the workspace
219
childWorkspaceNode = workspace.getNode(tempchildNode.getFqn());
220                // wrap it up so we can put it in later if we need to
221
if (childWorkspaceNode == null || childWorkspaceNode.isDeleted())
222                {
223                   if (debug)
224                   {
225                      log.debug("Child node " + tempchildNode.getFqn() + " doesn't exist in workspace or has been deleted. Adding to workspace in gtx " + gtx);
226                   }
227                   childWorkspaceNode = nodeFactory.createWorkspaceNode(tempchildNode, workspace);
228                   if (isTargetFqn && !workspace.isVersioningImplicit())
229                   {
230                      childWorkspaceNode.setVersion(version);
231                      childWorkspaceNode.setVersioningImplicit(false);
232                   }
233                   else
234                   {
235                      childWorkspaceNode.setVersioningImplicit(true);
236                   }
237                   if (log.isTraceEnabled())
238                   {
239                      log.trace("setting versioning of " + childWorkspaceNode.getFqn() + " to be " + (childWorkspaceNode.isVersioningImplicit() ? "implicit" : "explicit"));
240                   }
241
242                }
243                else
244                {
245                   if (debug)
246                   {
247                      log.debug("Found child node: " + tempchildNode);
248                   }
249
250                }
251             }
252             workspaceNode = childWorkspaceNode;
253          }
254
255       }// end sync block
256
if (debug) log.debug("done synchronized access of GlobalTX");
257
258       if (!suppressNotification)
259       {
260          if (nodesCreated.size() > 0)
261          {
262             Notifier n = cache.getNotifier();
263             for (Fqn temp : nodesCreated)
264             {
265                n.notifyNodeCreated(temp, true, false);
266                n.notifyNodeCreated(temp, false, false);
267                if (log.isDebugEnabled()) log.debug("Notifying cache of node created in workspace " + temp);
268             }
269          }
270       }
271    }
272
273 }
274
Popular Tags