KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > web > bean > repository > Repository


1 /*
2  * Copyright (C) 2005 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.web.bean.repository;
18
19 import java.io.Serializable JavaDoc;
20 import java.text.MessageFormat JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import javax.faces.context.FacesContext;
27 import javax.servlet.ServletContext JavaDoc;
28 import javax.transaction.UserTransaction JavaDoc;
29
30 import org.alfresco.error.AlfrescoRuntimeException;
31 import org.alfresco.model.ContentModel;
32 import org.alfresco.repo.configuration.ConfigurableService;
33 import org.alfresco.repo.content.MimetypeMap;
34 import org.alfresco.repo.content.metadata.MetadataExtracter;
35 import org.alfresco.repo.content.metadata.MetadataExtracterRegistry;
36 import org.alfresco.service.ServiceRegistry;
37 import org.alfresco.service.cmr.lock.LockService;
38 import org.alfresco.service.cmr.lock.LockStatus;
39 import org.alfresco.service.cmr.repository.ChildAssociationRef;
40 import org.alfresco.service.cmr.repository.ContentReader;
41 import org.alfresco.service.cmr.repository.InvalidNodeRefException;
42 import org.alfresco.service.cmr.repository.MimetypeService;
43 import org.alfresco.service.cmr.repository.NodeRef;
44 import org.alfresco.service.cmr.repository.NodeService;
45 import org.alfresco.service.cmr.repository.Path;
46 import org.alfresco.service.cmr.repository.StoreRef;
47 import org.alfresco.service.cmr.search.SearchService;
48 import org.alfresco.service.cmr.security.PersonService;
49 import org.alfresco.service.namespace.NamespaceService;
50 import org.alfresco.service.namespace.QName;
51 import org.alfresco.service.transaction.TransactionService;
52 import org.alfresco.web.app.Application;
53 import org.alfresco.web.ui.common.Utils;
54 import org.apache.log4j.Logger;
55 import org.springframework.web.context.support.WebApplicationContextUtils;
56 import org.springframework.web.jsf.FacesContextUtils;
57
58 /**
59  * Helper class for accessing repository objects, convert values, escape values and service utilities.
60  *
61  * @author gavinc
62  * @author kevinr
63  */

64 public final class Repository
65 {
66    /** I18N error messages */
67    public static final String JavaDoc ERROR_NODEREF = "error_noderef";
68    public static final String JavaDoc ERROR_GENERIC = "error_generic";
69    public static final String JavaDoc ERROR_NOHOME = "error_homespace";
70    public static final String JavaDoc ERROR_SEARCH = "error_search";
71    
72    private static final String JavaDoc METADATA_EXTACTER_REGISTRY = "metadataExtracterRegistry";
73
74    private static Logger logger = Logger.getLogger(Repository.class);
75    
76    /** cache of client StoreRef */
77    private static StoreRef storeRef = null;
78    
79    /** reference to Person folder */
80    private static NodeRef peopleRef = null;
81    
82    /** reference to System folder */
83    private static NodeRef systemRef = null;
84    
85    /** reference to the NamespaceService */
86    private static NamespaceService namespaceService = null;
87    
88    /** reference to the ServiceRegistry */
89    private static ServiceRegistry serviceRegistry = null;
90    
91    /**
92     * Private constructor
93     */

94    private Repository()
95    {
96    }
97    
98    /**
99     * Returns a store reference object
100     *
101     * @return A StoreRef object
102     */

103    public static StoreRef getStoreRef()
104    {
105       return storeRef;
106    }
107    
108    /**
109     * Returns a store reference object.
110     * This method is used to setup the cached value by the ContextListener initialisation methods
111     *
112     * @return The StoreRef object
113     */

114    public static StoreRef getStoreRef(ServletContext JavaDoc context)
115    {
116       storeRef = Application.getRepositoryStoreRef(context);
117       
118       return storeRef;
119    }
120
121    /**
122     * Helper to get the display name for a Node.
123     * The method will attempt to use the "name" attribute, if not found it will revert to using
124     * the QName.getLocalName() retrieved from the primary parent relationship.
125     *
126     * @param ref NodeRef
127     *
128     * @return display name string for the specified Node.
129     */

130    public static String JavaDoc getNameForNode(NodeService nodeService, NodeRef ref)
131    {
132       String JavaDoc name = null;
133       
134       // try to find a display "name" property for this node
135
Object JavaDoc nameProp = nodeService.getProperty(ref, ContentModel.PROP_NAME);
136       if (nameProp != null)
137       {
138          name = nameProp.toString();
139       }
140       else
141       {
142          // revert to using QName if not found
143
QName qname = nodeService.getPrimaryParent(ref).getQName();
144          if (qname != null)
145          {
146             name = qname.getLocalName();
147          }
148       }
149       
150       return name;
151    }
152
153    /**
154     * Escape a QName value so it can be used in lucene search strings
155     *
156     * @param qName QName to escape
157     *
158     * @return escaped value
159     */

160    public static String JavaDoc escapeQName(QName qName)
161    {
162        String JavaDoc string = qName.toString();
163        StringBuilder JavaDoc buf = new StringBuilder JavaDoc(string.length() + 4);
164        for (int i = 0; i < string.length(); i++)
165        {
166            char c = string.charAt(i);
167            if ((c == '{') || (c == '}') || (c == ':') || (c == '-'))
168            {
169               buf.append('\\');
170            }
171    
172            buf.append(c);
173        }
174        return buf.toString();
175    }
176
177    /**
178     * Return whether a Node is currently locked
179     *
180     * @param node The Node wrapper to test against
181     * @param lockService The LockService to use
182     *
183     * @return whether a Node is currently locked
184     */

185    public static Boolean JavaDoc isNodeLocked(Node node, LockService lockService)
186    {
187       Boolean JavaDoc locked = Boolean.FALSE;
188       
189       if (node.hasAspect(ContentModel.ASPECT_LOCKABLE))
190       {
191          LockStatus lockStatus = lockService.getLockStatus(node.getNodeRef());
192          if (lockStatus == LockStatus.LOCKED || lockStatus == LockStatus.LOCK_OWNER)
193          {
194             locked = Boolean.TRUE;
195          }
196       }
197       
198       return locked;
199    }
200    
201    /**
202     * Return whether a Node is currently locked by the current user
203     *
204     * @param node The Node wrapper to test against
205     * @param lockService The LockService to use
206     *
207     * @return whether a Node is currently locked by the current user
208     */

209    public static Boolean JavaDoc isNodeOwnerLocked(Node node, LockService lockService)
210    {
211       Boolean JavaDoc locked = Boolean.FALSE;
212       
213       if (node.hasAspect(ContentModel.ASPECT_LOCKABLE) &&
214           lockService.getLockStatus(node.getNodeRef()) == LockStatus.LOCK_OWNER)
215       {
216          locked = Boolean.TRUE;
217       }
218       
219       return locked;
220    }
221    
222    /**
223     * Return whether a WorkingCopy Node is owned by the current User
224     *
225     * @param node The Node wrapper to test against
226     * @param lockService The LockService to use
227     *
228     * @return whether a WorkingCopy Node is owned by the current User
229     */

230    public static Boolean JavaDoc isNodeOwner(Node node, LockService lockService)
231    {
232       Boolean JavaDoc locked = Boolean.FALSE;
233       
234       if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
235       {
236          Object JavaDoc obj = node.getProperties().get("workingCopyOwner");
237          if (obj instanceof String JavaDoc)
238          {
239             User user = Application.getCurrentUser(FacesContext.getCurrentInstance());
240             if ( ((String JavaDoc)obj).equals(user.getUserName()))
241             {
242                locked = Boolean.TRUE;
243             }
244          }
245       }
246       
247       return locked;
248    }
249    
250    /**
251     * Return the human readable form of the specified node Path. Fast version of the method that
252     * simply converts QName localname components to Strings.
253     *
254     * @param path Path to extract readable form from, excluding the final element
255     *
256     * @return human readable form of the Path excluding the final element
257     */

258    public static String JavaDoc getDisplayPath(Path path)
259    {
260       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(64);
261       
262       for (int i=0; i<path.size()-1; i++)
263       {
264          String JavaDoc elementString = null;
265          Path.Element element = path.get(i);
266          if (element instanceof Path.ChildAssocElement)
267          {
268             ChildAssociationRef elementRef = ((Path.ChildAssocElement)element).getRef();
269             if (elementRef.getParentRef() != null)
270             {
271                elementString = elementRef.getQName().getLocalName();
272             }
273          }
274          else
275          {
276             elementString = element.getElementString();
277          }
278          
279          if (elementString != null)
280          {
281             buf.append("/");
282             buf.append(elementString);
283          }
284       }
285       
286       return buf.toString();
287    }
288    
289    /**
290     * Resolve a Path by converting each element into its display NAME attribute
291     *
292     * @param path Path to convert
293     * @param separator Separator to user between path elements
294     * @param prefix To prepend to the path
295     *
296     * @return Path converted using NAME attribute on each element
297     */

298    public static String JavaDoc getNamePath(NodeService nodeService, Path path, NodeRef rootNode, String JavaDoc separator, String JavaDoc prefix)
299    {
300       StringBuilder JavaDoc buf = new StringBuilder JavaDoc(128);
301       
302       // ignore root node check if not passed in
303
boolean foundRoot = (rootNode == null);
304       
305       buf.append(prefix);
306       
307       // skip first element as it represents repo root '/'
308
for (int i=1; i<path.size(); i++)
309       {
310          Path.Element element = path.get(i);
311          String JavaDoc elementString = null;
312          if (element instanceof Path.ChildAssocElement)
313          {
314             ChildAssociationRef elementRef = ((Path.ChildAssocElement)element).getRef();
315             if (elementRef.getParentRef() != null)
316             {
317                // only append if we've found the root already
318
if (foundRoot == true)
319                {
320                   Object JavaDoc nameProp = nodeService.getProperty(elementRef.getChildRef(), ContentModel.PROP_NAME);
321                   if (nameProp != null)
322                   {
323                      elementString = nameProp.toString();
324                   }
325                   else
326                   {
327                      elementString = element.getElementString();
328                   }
329                }
330                
331                // either we've found root already or may have now
332
// check after as we want to skip the root as it represents the CIFS share name
333
foundRoot = (foundRoot || elementRef.getChildRef().equals(rootNode));
334             }
335          }
336          else
337          {
338             elementString = element.getElementString();
339          }
340          
341          if (elementString != null)
342          {
343             buf.append(separator);
344             buf.append(elementString);
345          }
346       }
347       
348       return buf.toString();
349    }
350
351    /**
352     * Return the mimetype code for the specified file name.
353     * <p>
354     * The file extension will be extracted from the filename and used to lookup the mimetype.
355     *
356     * @param context FacesContext
357     * @param filename Non-null filename to process
358     *
359     * @return mimetype for the specified filename - falls back to 'application/octet-stream' if not found.
360     */

361    public static String JavaDoc getMimeTypeForFileName(FacesContext context, String JavaDoc filename)
362    {
363       // base the mimetype from the file extension
364
MimetypeService mimetypeService = (MimetypeService)getServiceRegistry(context).getMimetypeService();
365       
366       // fall back to binary mimetype if no match found
367
String JavaDoc mimetype = MimetypeMap.MIMETYPE_BINARY;
368       int extIndex = filename.lastIndexOf('.');
369       if (extIndex != -1)
370       {
371          String JavaDoc ext = filename.substring(extIndex + 1).toLowerCase();
372          String JavaDoc mt = mimetypeService.getMimetypesByExtension().get(ext);
373          if (mt != null)
374          {
375             mimetype = mt;
376          }
377       }
378       
379       return mimetype;
380    }
381
382    /**
383     * Return a UserTransaction instance
384     *
385     * @param context FacesContext
386     *
387     * @return UserTransaction
388     */

389    public static UserTransaction JavaDoc getUserTransaction(FacesContext context)
390    {
391       TransactionService transactionService = getServiceRegistry(context).getTransactionService();
392       return transactionService.getUserTransaction();
393    }
394    
395    /**
396     * Return a UserTransaction instance
397     *
398     * @param context FacesContext
399     * @param readonly Transaction readonly state
400     *
401     * @return UserTransaction
402     */

403    public static UserTransaction JavaDoc getUserTransaction(FacesContext context, boolean readonly)
404    {
405       TransactionService transactionService = getServiceRegistry(context).getTransactionService();
406       return transactionService.getUserTransaction(readonly);
407    }
408
409    /**
410     * Return the Repository Service Registry
411     *
412     * @param context Faces Context
413     * @return the Service Registry
414     */

415    public static ServiceRegistry getServiceRegistry(FacesContext context)
416    {
417       if (serviceRegistry == null)
418       {
419          serviceRegistry = (ServiceRegistry)FacesContextUtils.getRequiredWebApplicationContext(
420                context).getBean(ServiceRegistry.SERVICE_REGISTRY);
421       }
422       return serviceRegistry;
423    }
424    
425    /**
426     * Return the Repository Service Registry
427     *
428     * @param context Servlet Context
429     * @return the Service Registry
430     */

431    public static ServiceRegistry getServiceRegistry(ServletContext JavaDoc context)
432    {
433       if (serviceRegistry == null)
434       {
435          serviceRegistry = (ServiceRegistry)WebApplicationContextUtils.getRequiredWebApplicationContext(
436                context).getBean(ServiceRegistry.SERVICE_REGISTRY);
437       }
438       return serviceRegistry;
439    }
440    
441    /**
442     * Return the Configurable Service
443     *
444     * @return the configurable service
445     */

446    public static ConfigurableService getConfigurableService(FacesContext context)
447    {
448       return (ConfigurableService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("configurableService");
449    }
450    
451    /**
452     * Return the Metadata Extracter Registry
453     *
454     * @param context Faces Context
455     * @return the MetadataExtracterRegistry
456     */

457    public static MetadataExtracterRegistry getMetadataExtracterRegistry(FacesContext context)
458    {
459       return (MetadataExtracterRegistry)FacesContextUtils.getRequiredWebApplicationContext(
460             context).getBean(METADATA_EXTACTER_REGISTRY);
461    }
462    
463    /**
464     * Extracts the metadata of a "raw" piece of content into a map.
465     *
466     * @param context Faces Context
467     * @param reader Content reader for the source content to extract from
468     * @param destination Map of metadata to set metadata values into
469     * @return True if an extracter was found
470     */

471    public static boolean extractMetadata(FacesContext context, ContentReader reader, Map JavaDoc<QName, Serializable JavaDoc> destination)
472    {
473       // check that source mimetype is available
474
String JavaDoc mimetype = reader.getMimetype();
475       if (mimetype == null)
476       {
477          throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader);
478       }
479
480       // look for a transformer
481
MetadataExtracter extracter = getMetadataExtracterRegistry(context).getExtracter(mimetype);
482       if (extracter == null)
483       {
484          // No metadata extracter is not a failure, but we flag it
485
return false;
486       }
487       
488       try
489       {
490           // we have a transformer, so do it
491
extracter.extract(reader, destination);
492           return true;
493       }
494       catch (Throwable JavaDoc e)
495       {
496           // it failed
497
logger.warn("Metadata extraction failed: \n" +
498                   " reader: " + reader + "\n" +
499                   " extracter: " + extracter);
500           return false;
501       }
502    }
503
504    /**
505     * Query a list of Person type nodes from the repo
506     * It is currently assumed that all Person nodes exist below the Repository root node
507     *
508     * @param context Faces Context
509     * @param nodeService The node service
510     * @param searchService used to perform the search
511     * @return List of Person node objects
512     */

513    public static List JavaDoc<Node> getUsers(FacesContext context, NodeService nodeService, SearchService searchService)
514    {
515       List JavaDoc<Node> personNodes = null;
516       
517       UserTransaction JavaDoc tx = null;
518       try
519       {
520          tx = Repository.getUserTransaction(context, true);
521          tx.begin();
522          
523          PersonService personService = (PersonService)FacesContextUtils.getRequiredWebApplicationContext(context).getBean("personService");
524          NodeRef peopleRef = personService.getPeopleContainer();
525          
526          // TODO: better to perform an XPath search or a get for a specific child type here?
527
List JavaDoc<ChildAssociationRef> childRefs = nodeService.getChildAssocs(peopleRef);
528          personNodes = new ArrayList JavaDoc<Node>(childRefs.size());
529          for (ChildAssociationRef ref: childRefs)
530          {
531             // create our Node representation from the NodeRef
532
NodeRef nodeRef = ref.getChildRef();
533             
534             if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_PERSON))
535             {
536                // create our Node representation
537
MapNode node = new MapNode(nodeRef);
538                
539                // set data binding properties
540
// this will also force initialisation of the props now during the UserTransaction
541
// it is much better for performance to do this now rather than during page bind
542
Map JavaDoc<String JavaDoc, Object JavaDoc> props = node.getProperties();
543                String JavaDoc lastName = (String JavaDoc)props.get("lastName");
544                props.put("fullName", ((String JavaDoc)props.get("firstName")) + ' ' + (lastName != null ? lastName : ""));
545                NodeRef homeFolderNodeRef = (NodeRef)props.get("homeFolder");
546                if (homeFolderNodeRef != null)
547                {
548                   props.put("homeSpace", homeFolderNodeRef);
549                }
550                
551                personNodes.add(node);
552             }
553          }
554          
555          // commit the transaction
556
tx.commit();
557       }
558       catch (InvalidNodeRefException refErr)
559       {
560          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
561                context, Repository.ERROR_NODEREF), new Object JavaDoc[] {"root"}) );
562          personNodes = Collections.<Node>emptyList();
563          try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
564       }
565       catch (Throwable JavaDoc err)
566       {
567          Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
568                context, Repository.ERROR_GENERIC), err.getMessage()), err );
569          personNodes = Collections.<Node>emptyList();
570          try { if (tx != null) {tx.rollback();} } catch (Exception JavaDoc tex) {}
571       }
572       
573       return personNodes;
574    }
575    
576    /**
577     * Convert a property of unknown type to a String value. A native String value will be
578     * returned directly, else toString() will be executed, null is returned as null.
579     *
580     * @param value Property value
581     *
582     * @return value to String or null
583     */

584    public static String JavaDoc safePropertyToString(Serializable JavaDoc value)
585    {
586       if (value == null)
587       {
588          return null;
589       }
590       else if (value instanceof String JavaDoc)
591       {
592          return (String JavaDoc)value;
593       }
594       else
595       {
596          return value.toString();
597       }
598    }
599    
600    /**
601     * Creates a QName representation for the given String.
602     * If the String has no namespace the Alfresco namespace is added.
603     * If the String has a prefix an attempt to resolve the prefix to the
604     * full URI will be made.
605     *
606     * @param str The string to convert
607     * @return A QName representation of the given string
608     */

609    public static QName resolveToQName(String JavaDoc str)
610    {
611       return QName.resolveToQName(getNamespaceService(), str);
612    }
613    
614    /**
615     * Creates a string representation of a QName for the given string.
616     * If the given string already has a namespace, either a URL or a prefix,
617     * nothing the given string is returned. If it does not have a namespace
618     * the Alfresco namespace is added.
619     *
620     * @param str The string to convert
621     * @return A QName String representation of the given string
622     */

623    public static String JavaDoc resolveToQNameString(String JavaDoc str)
624    {
625       return QName.resolveToQNameString(getNamespaceService(), str);
626    }
627    
628    /**
629     * Returns an instance of the namespace service
630     *
631     * @return The NamespaceService
632     */

633    private static NamespaceService getNamespaceService()
634    {
635       if (namespaceService == null)
636       {
637          ServiceRegistry svcReg = getServiceRegistry(FacesContext.getCurrentInstance());
638          namespaceService = svcReg.getNamespaceService();
639       }
640       
641       return namespaceService;
642    }
643 }
644
Popular Tags