View Javadoc
1   /*
2    * Copyright (C) 2003-2009 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.services.cms.link;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.OutputStream;
22  import java.security.AccessControlException;
23  import java.util.HashSet;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import javax.jcr.AccessDeniedException;
28  import javax.jcr.Credentials;
29  import javax.jcr.InvalidItemStateException;
30  import javax.jcr.InvalidSerializedDataException;
31  import javax.jcr.Item;
32  import javax.jcr.ItemExistsException;
33  import javax.jcr.ItemNotFoundException;
34  import javax.jcr.LoginException;
35  import javax.jcr.NamespaceException;
36  import javax.jcr.Node;
37  import javax.jcr.PathNotFoundException;
38  import javax.jcr.Repository;
39  import javax.jcr.RepositoryException;
40  import javax.jcr.Session;
41  import javax.jcr.UnsupportedRepositoryOperationException;
42  import javax.jcr.ValueFactory;
43  import javax.jcr.Workspace;
44  import javax.jcr.lock.LockException;
45  import javax.jcr.nodetype.ConstraintViolationException;
46  import javax.jcr.nodetype.NoSuchNodeTypeException;
47  import javax.jcr.version.VersionException;
48  import javax.transaction.xa.XAResource;
49  
50  import org.exoplatform.services.jcr.core.ExtendedSession;
51  import org.exoplatform.services.jcr.core.NamespaceAccessor;
52  import org.exoplatform.services.jcr.core.SessionLifecycleListener;
53  import org.exoplatform.services.jcr.impl.core.LocationFactory;
54  import org.exoplatform.services.jcr.impl.core.SessionImpl;
55  import org.exoplatform.services.log.ExoLogger;
56  import org.exoplatform.services.log.Log;
57  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
58  import org.xml.sax.ContentHandler;
59  import org.xml.sax.SAXException;
60  
61  /**
62   * Created by The eXo Platform SAS
63   * Author : eXoPlatform
64   *          nicolas.filotto@exoplatform.com
65   * 4 avr. 2009
66   */
67  public class SessionLinkAware implements ExtendedSession, NamespaceAccessor {
68  
69    /**
70     * Logger.
71     */
72    private static final Log LOG  = ExoLogger.getLogger(SessionLinkAware.class.getName());
73  
74    private ItemLinkAware itemLA;
75  
76    private final String originalWorkspace;
77  
78    private volatile ExtendedSession[] sessions;
79  
80    SessionLinkAware (ItemLinkAware itemLA) throws RepositoryException {
81      this.itemLA = itemLA;
82      this.originalWorkspace = itemLA.originalWorkspaceName;
83    }
84  
85    private ExtendedSession[] getSessions() throws RepositoryException {
86      if (sessions == null) {
87        synchronized (this) {
88          if (sessions == null) {
89            Set<ExtendedSession> sSessions = new HashSet<ExtendedSession>(3, 1f);
90            sSessions.add(getOriginalSession());
91            sSessions.add((ExtendedSession)itemLA.getItemSession());
92            sSessions.add(getTargetSession());
93            sessions = sSessions.toArray(new ExtendedSession[sSessions.size()]);
94          }
95        }
96      }
97      return sessions;
98    }
99  
100   private ExtendedSession getSession() throws RepositoryException {
101     return (ExtendedSession)itemLA.getItemSession();
102   }
103 
104   private ExtendedSession getOriginalSession() throws RepositoryException {
105     return (ExtendedSession)WCMCoreUtils.getUserSessionProvider().
106                     getSession(originalWorkspace, WCMCoreUtils.getRepository());
107   }
108 
109   private ExtendedSession getTargetSession() throws RepositoryException {
110     return getTargetSession(itemLA);
111   }
112 
113   private ExtendedSession getTargetSession(String absPath, Item item) throws RepositoryException {
114     return getTargetSession(ItemLinkAware.newInstance(originalWorkspace, absPath, item));
115   }
116 
117   private ExtendedSession getTargetSession(ItemLinkAware itemLA) throws RepositoryException {
118     if (itemLA instanceof NodeLinkAware) {
119       return (ExtendedSession) ((NodeLinkAware) itemLA).getTargetNode().getRealNode().getSession();
120     }
121     return (ExtendedSession) itemLA.getItemSession();
122   }
123 
124   private ExtendedSession getTargetSession(String absPath) throws RepositoryException {
125     Item item = getItem(absPath);
126     return getTargetSession(absPath, item);
127   }
128 
129   /**
130    * {@inheritDoc}
131    */
132   public void addLockToken(String lt) {
133     try {
134       getTargetSession().addLockToken(lt);
135     } catch (RepositoryException e) {
136       if (LOG.isErrorEnabled()) {
137         LOG.error(e);
138       }
139     }
140   }
141 
142   /**
143    * {@inheritDoc}
144    */
145   public void checkPermission(String absPath, String actions) throws AccessControlException,
146                                                        RepositoryException {
147     getTargetSession(absPath).checkPermission(absPath, actions);
148   }
149 
150   /**
151    * {@inheritDoc}
152    */
153   public void exportDocumentView(String absPath,
154                                  ContentHandler contentHandler,
155                                  boolean skipBinary,
156                                  boolean noRecurse) throws PathNotFoundException,
157                                                    SAXException,
158                                                    RepositoryException {
159     getTargetSession(absPath).exportDocumentView(absPath, contentHandler, skipBinary, noRecurse);
160   }
161 
162   /**
163    * {@inheritDoc}
164    */
165   public void exportDocumentView(String absPath,
166                                  OutputStream out,
167                                  boolean skipBinary,
168                                  boolean noRecurse) throws IOException,
169                                                    PathNotFoundException,
170                                                    RepositoryException {
171     getTargetSession(absPath).exportDocumentView(absPath, out, skipBinary, noRecurse);
172   }
173 
174   /**
175    * {@inheritDoc}
176    */
177   public void exportSystemView(String absPath,
178                                ContentHandler contentHandler,
179                                boolean skipBinary,
180                                boolean noRecurse) throws PathNotFoundException,
181                                                  SAXException,
182                                                  RepositoryException {
183     getTargetSession(absPath).exportSystemView(absPath, contentHandler, skipBinary, noRecurse);
184   }
185 
186   /**
187    * {@inheritDoc}
188    */
189   public void exportSystemView(String absPath,
190                                OutputStream out,
191                                boolean skipBinary,
192                                boolean noRecurse) throws IOException,
193                                                  PathNotFoundException,
194                                                  RepositoryException {
195     getTargetSession(absPath).exportSystemView(absPath, out, skipBinary, noRecurse);
196   }
197 
198   /**
199    * {@inheritDoc}
200    */
201   public Object getAttribute(String name) {
202     try {
203       return getTargetSession().getAttribute(name);
204     } catch (RepositoryException e) {
205       if (LOG.isErrorEnabled()) {
206         LOG.error(e);
207       }
208     }
209     return null;
210   }
211 
212   /**
213    * {@inheritDoc}
214    */
215   public String[] getAttributeNames() {
216     try {
217       return getTargetSession().getAttributeNames();
218     } catch (RepositoryException e) {
219       if (LOG.isErrorEnabled()) {
220         LOG.error(e);
221       }
222     }
223     return null;
224   }
225 
226   /**
227    * {@inheritDoc}
228    */
229   public ContentHandler getImportContentHandler(String parentAbsPath, int uuidBehavior) throws PathNotFoundException,
230                                                                                        ConstraintViolationException,
231                                                                                        VersionException,
232                                                                                        LockException,
233                                                                                        RepositoryException {
234     return getTargetSession(parentAbsPath).getImportContentHandler(parentAbsPath, uuidBehavior);
235   }
236 
237   /**
238    * {@inheritDoc}
239    */
240   public Item getItem(String absPath) throws PathNotFoundException, RepositoryException {
241     NodeFinder nodeFinder = LinkUtils.getNodeFinder();
242     return nodeFinder.getItem(getOriginalSession(), absPath);
243   }
244 
245   /**
246    * {@inheritDoc}
247    */
248   public String[] getLockTokens() {
249     try {
250       return getTargetSession().getLockTokens();
251     } catch (RepositoryException e) {
252       if (LOG.isErrorEnabled()) {
253         LOG.error(e);
254       }
255     }
256     return null;
257   }
258 
259   /**
260    * {@inheritDoc}
261    */
262   public String getNamespacePrefix(String uri) throws NamespaceException, RepositoryException {
263     return getTargetSession().getNamespacePrefix(uri);
264   }
265 
266   /**
267    * {@inheritDoc}
268    */
269   public String[] getNamespacePrefixes() throws RepositoryException {
270     return getTargetSession().getNamespacePrefixes();
271   }
272 
273   /**
274    * {@inheritDoc}
275    */
276   public String getNamespaceURI(String prefix) throws NamespaceException, RepositoryException {
277     return getTargetSession().getNamespaceURI(prefix);
278   }
279 
280   /**
281    * {@inheritDoc}
282    */
283   public Node getNodeByUUID(String uuid) throws ItemNotFoundException, RepositoryException {
284     ExtendedSession[] sessions = getSessions();
285     for (int i = 0, length = sessions.length; i < length; i++) {
286       Session session = sessions[i];
287       try {
288         return session.getNodeByUUID(uuid);
289       } catch (ItemNotFoundException e) {
290         continue;
291       }
292     }
293     throw new ItemNotFoundException("No node with uuid ='" + uuid + "' can be found");
294   }
295 
296   /**
297    * {@inheritDoc}
298    */
299   public Repository getRepository() {
300     try {
301       return getSession().getRepository();
302     } catch (Exception e) {
303       return null;
304     }
305   }
306 
307   /**
308    * {@inheritDoc}
309    */
310   public Node getRootNode() throws RepositoryException {
311     return getOriginalSession().getRootNode();
312   }
313 
314   /**
315    * {@inheritDoc}
316    */
317   public String getUserID() {
318     try {
319       return getSession().getUserID();
320     } catch (Exception e) {
321       return null;
322     }
323   }
324 
325   /**
326    * {@inheritDoc}
327    */
328   public ValueFactory getValueFactory() throws UnsupportedRepositoryOperationException,
329                                        RepositoryException {
330     return getOriginalSession().getValueFactory();
331   }
332 
333   /**
334    * {@inheritDoc}
335    */
336   public Workspace getWorkspace() {
337     try {
338       return getOriginalSession().getWorkspace();
339     } catch (Exception e) {
340       return null;
341     }
342   }
343 
344   /**
345    * {@inheritDoc}
346    */
347   public boolean hasPendingChanges() throws RepositoryException {
348     ExtendedSession[] sessions = getSessions();
349     for (int i = 0, length = sessions.length; i < length; i++) {
350       Session session = sessions[i];
351       if (session.hasPendingChanges()) {
352         return true;
353       }
354     }
355     return false;
356   }
357 
358   /**
359    * {@inheritDoc}
360    */
361   public Session impersonate(Credentials credentials) throws LoginException, RepositoryException {
362     return getOriginalSession().impersonate(credentials);
363   }
364 
365   /**
366    * {@inheritDoc}
367    */
368   public void importXML(String parentAbsPath, InputStream in, int uuidBehavior) throws IOException,
369                                                                                PathNotFoundException,
370                                                                                ItemExistsException,
371                                                                                ConstraintViolationException,
372                                                                                VersionException,
373                                                                                InvalidSerializedDataException,
374                                                                                LockException,
375                                                                                RepositoryException {
376     getTargetSession(parentAbsPath).importXML(parentAbsPath, in, uuidBehavior);
377   }
378 
379   /**
380    * {@inheritDoc}
381    */
382   public boolean isLive() {
383     ExtendedSession[] sessions;
384     try {
385       sessions = getSessions();
386     } catch (RepositoryException e) {
387       if (LOG.isErrorEnabled()) {
388         LOG.error(e);
389       }
390       return false;
391     }
392     for (int i = 0, length = sessions.length; i < length; i++) {
393       Session session = sessions[i];
394       if (session.isLive()) {
395         return true;
396       }
397     }
398     return false;
399   }
400 
401   /**
402    * {@inheritDoc}
403    */
404   public boolean itemExists(String absPath) throws RepositoryException {
405     NodeFinder nodeFinder = LinkUtils.getNodeFinder();
406     return nodeFinder.itemExists(getOriginalSession(), absPath);
407   }
408 
409   /**
410    * {@inheritDoc}
411    */
412   public void logout() {
413     ExtendedSession[] sessions;
414     try {
415       sessions = getSessions();
416     } catch (RepositoryException e) {
417       if (LOG.isErrorEnabled()) {
418         LOG.error(e);
419       }
420       return;
421     }
422     for (int i = 0, length = sessions.length; i < length; i++) {
423       Session session = sessions[i];
424       session.logout();
425     }
426   }
427 
428   /**
429    * {@inheritDoc}
430    */
431   public void move(String srcAbsPath, String destAbsPath) throws ItemExistsException,
432                                                          PathNotFoundException,
433                                                          VersionException,
434                                                          ConstraintViolationException,
435                                                          LockException,
436                                                          RepositoryException {
437     Item srcItem = getItem(srcAbsPath);
438     Session srcSession = getTargetSession(srcAbsPath, srcItem);
439     Session destParentSession = getTargetSession(LinkUtils.getParentPath(destAbsPath));
440     if (srcSession.getWorkspace().equals(destParentSession.getWorkspace())) {
441       srcSession.move(srcAbsPath, srcAbsPath);
442     } else {
443       destParentSession.getWorkspace().clone(srcSession.getWorkspace().getName(),
444                                              srcAbsPath,
445                                              destAbsPath,
446                                              false);
447     }
448   }
449 
450   /**
451    * {@inheritDoc}
452    */
453   public void refresh(boolean keepChanges) throws RepositoryException {
454     ExtendedSession[] sessions = getSessions();
455     for (int i = 0, length = sessions.length; i < length; i++) {
456       Session session = sessions[i];
457       session.refresh(keepChanges);
458     }
459   }
460 
461   /**
462    * {@inheritDoc}
463    */
464   public void removeLockToken(String lt) {
465     try {
466       getTargetSession().removeLockToken(lt);
467     } catch (RepositoryException e) {
468       if (LOG.isErrorEnabled()) {
469         LOG.error(e);
470       }
471     }
472   }
473 
474   /**
475    * {@inheritDoc}
476    */
477   public void save() throws AccessDeniedException,
478                     ItemExistsException,
479                     ConstraintViolationException,
480                     InvalidItemStateException,
481                     VersionException,
482                     LockException,
483                     NoSuchNodeTypeException,
484                     RepositoryException {
485     ExtendedSession[] sessions = getSessions();
486     for (int i = 0, length = sessions.length; i < length; i++) {
487       Session session = sessions[i];
488       session.save();
489     }
490   }
491 
492   /**
493    * {@inheritDoc}
494    */
495   public void setNamespacePrefix(String prefix, String uri) throws NamespaceException,
496                                                           RepositoryException {
497     getTargetSession().setNamespacePrefix(prefix, uri);
498   }
499 
500   /**
501    * {@inheritDoc}
502    */
503   public String getId() {
504     try {
505       return getTargetSession().getId();
506     } catch (RepositoryException e) {
507       if (LOG.isErrorEnabled()) {
508         LOG.error(e);
509       }
510     }
511     return null;
512   }
513 
514   /**
515    * {@inheritDoc}
516    */
517   public LocationFactory getLocationFactory() {
518     try {
519       return getTargetSession().getLocationFactory();
520     } catch (RepositoryException e) {
521       if (LOG.isErrorEnabled()) {
522         LOG.error(e);
523       }
524     }
525     return null;
526   }
527 
528   /**
529    * {@inheritDoc}
530    */
531   public void importXML(String parentAbsPath,
532                         InputStream in,
533                         int uuidBehavior,
534                         Map<String, Object> context) throws IOException,
535                                                     PathNotFoundException,
536                                                     ItemExistsException,
537                                                     ConstraintViolationException,
538                                                     InvalidSerializedDataException,
539                                                     RepositoryException {
540     getTargetSession(parentAbsPath).importXML(parentAbsPath, in, uuidBehavior, context);
541   }
542 
543   /**
544    * {@inheritDoc}
545    */
546   public void registerLifecycleListener(SessionLifecycleListener listener) {
547     try {
548       getTargetSession().registerLifecycleListener(listener);
549     } catch (RepositoryException e) {
550       if (LOG.isErrorEnabled()) {
551         LOG.error(e);
552       }
553     }
554   }
555 
556   /**
557    * {@inheritDoc}
558    */
559   public String[] getAllNamespacePrefixes() throws RepositoryException {
560     return ((NamespaceAccessor) getTargetSession()).getAllNamespacePrefixes();
561   }
562 
563   /**
564    * {@inheritDoc}
565    */
566   public String getNamespacePrefixByURI(String uri) throws NamespaceException, RepositoryException {
567     return ((NamespaceAccessor) getTargetSession()).getNamespacePrefixByURI(uri);
568   }
569 
570   /**
571    * {@inheritDoc}
572    */
573   public String getNamespaceURIByPrefix(String prefix) throws NamespaceException,
574                                                       RepositoryException {
575     return ((NamespaceAccessor) getTargetSession()).getNamespaceURIByPrefix(prefix);
576   }
577 
578   /**
579    * {@inheritDoc}}
580    */
581   public Node getNodeByIdentifier(String identifier) throws ItemNotFoundException, RepositoryException {
582     return getTargetSession().getNodeByIdentifier(identifier);
583   }
584 
585   @Override
586   public void exportSystemView(String absPath, OutputStream out, boolean skipBinary, boolean noRecurse,
587       boolean exportChildVersionHisotry) throws IOException, PathNotFoundException, RepositoryException {
588     getTargetSession().exportSystemView(absPath, out, skipBinary, noRecurse, exportChildVersionHisotry);
589   }
590 
591   @Override
592   public XAResource getXAResource() {
593     try {
594       return getTargetSession().getXAResource();
595     } catch (RepositoryException e) {
596       return null;
597     }
598   }
599 
600   @Override
601   public boolean hasExpired() {
602     try {
603       return getTargetSession().hasExpired();
604     } catch (RepositoryException e) {
605       return true;
606     }
607   }
608 
609   @Override
610   public void setTimeout(long timeout) {
611     try {
612       getTargetSession().setTimeout(timeout);
613     } catch (RepositoryException e) {
614       LOG.warn(e.getMessage());
615     }
616   }
617 
618   @Override
619   public long getTimeout() {
620     try {
621       return getTargetSession().getTimeout();
622     } catch (RepositoryException e) {
623       return 0;
624     }
625   }
626 
627   @Override
628   public void move(String srcAbsPath,
629                    String destAbsPath,
630                    boolean triggerEventsForDescendentsOnRename) throws ItemExistsException,
631                                                                PathNotFoundException,
632                                                                VersionException,
633                                                                ConstraintViolationException,
634                                                                LockException,
635                                                                RepositoryException {
636     Item srcItem = getItem(srcAbsPath);
637     Session srcSession = getTargetSession(srcAbsPath, srcItem);
638     Session destParentSession = getTargetSession(LinkUtils.getParentPath(destAbsPath));
639     if (srcSession.getWorkspace().equals(destParentSession.getWorkspace())) {
640       ((SessionImpl)srcSession).move(srcAbsPath, srcAbsPath, triggerEventsForDescendentsOnRename);
641     } else {
642       destParentSession.getWorkspace().clone(srcSession.getWorkspace().getName(),
643                                              srcAbsPath,
644                                              destAbsPath,
645                                              false);
646     }
647   }
648 }