001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/file/wrapper/CmsObjectWrapper.java,v $
003: * Date : $Date: 2008-02-27 12:05:30 $
004: * Version: $Revision: 1.11 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.file.wrapper;
033:
034: import org.opencms.file.CmsFile;
035: import org.opencms.file.CmsObject;
036: import org.opencms.file.CmsProperty;
037: import org.opencms.file.CmsRequestContext;
038: import org.opencms.file.CmsResource;
039: import org.opencms.file.CmsResourceFilter;
040: import org.opencms.file.CmsUser;
041: import org.opencms.file.CmsResource.CmsResourceCopyMode;
042: import org.opencms.file.CmsResource.CmsResourceDeleteMode;
043: import org.opencms.file.types.CmsResourceTypeJsp;
044: import org.opencms.file.types.CmsResourceTypePlain;
045: import org.opencms.file.types.CmsResourceTypeXmlContent;
046: import org.opencms.file.types.CmsResourceTypeXmlPage;
047: import org.opencms.file.types.I_CmsResourceType;
048: import org.opencms.i18n.CmsEncoder;
049: import org.opencms.i18n.CmsLocaleManager;
050: import org.opencms.loader.CmsLoaderException;
051: import org.opencms.lock.CmsLock;
052: import org.opencms.main.CmsException;
053: import org.opencms.main.CmsIllegalArgumentException;
054: import org.opencms.main.CmsLog;
055: import org.opencms.main.OpenCms;
056: import org.opencms.util.CmsUUID;
057:
058: import java.util.ArrayList;
059: import java.util.Collections;
060: import java.util.Iterator;
061: import java.util.List;
062:
063: import org.apache.commons.logging.Log;
064:
065: /**
066: * This class contains a subset of the methods of {@link CmsObject} and uses the
067: * configured resource wrappers ({@link I_CmsResourceWrapper}) to change the view
068: * to the existing resources in the VFS.<p>
069: *
070: * Almost every method in this class iterates through the configured list of
071: * {@link I_CmsResourceWrapper} and calls the same method there. The first resource
072: * wrapper in the list which feels responsible for that action handles it and the
073: * iteration ends. So the resource wrappers should check in every method if it is
074: * responsible or not. Be careful if there are more than one resource wrapper for
075: * the same resource in the VFS, because the first in the list wins. If the iteration is
076: * finished and no resource wrapper felt responsible the default action is to call the
077: * method in the {@link CmsObject}.<p>
078: *
079: * It is possible to create an unchanged access to the resource in the VFS by creating
080: * a new instance of the CmsObjectWrapper with an empty list of resource wrappers.<p>
081: *
082: * @author Peter Bonrad
083: *
084: * @version $Revision: 1.11 $
085: *
086: * @since 6.2.4
087: */
088: public class CmsObjectWrapper {
089:
090: /** The name of the attribute in the {@link CmsRequestContext} where the current CmsObjectWrapper can be found. */
091: public static final String ATTRIBUTE_NAME = "org.opencms.file.wrapper.CmsObjectWrapper";
092:
093: /** The log object for this class. */
094: private static final Log LOG = CmsLog
095: .getLog(CmsObjectWrapper.class);
096:
097: /** The initialized CmsObject. */
098: private CmsObject m_cms;
099:
100: /** The list with the configured wrappers (entries of type {@link I_CmsResourceWrapper}). */
101: private List m_wrappers;
102:
103: /**
104: * Constructor with the CmsObject to wrap and the resource wrappers to use.<p>
105: *
106: * @param cms the initialized CmsObject
107: * @param wrappers the configured wrappers to use (entries of type {@link I_CmsResourceWrapper})
108: */
109: public CmsObjectWrapper(CmsObject cms, List wrappers) {
110:
111: m_cms = cms;
112: m_wrappers = wrappers;
113: }
114:
115: /**
116: * Copies a resource.<p>
117: *
118: * Iterates through all configured resource wrappers till the first returns <code>true</code>.<p>
119: *
120: * @see I_CmsResourceWrapper#copyResource(CmsObject, String, String, CmsResource.CmsResourceCopyMode)
121: * @see CmsObject#copyResource(String, String, CmsResource.CmsResourceCopyMode)
122: *
123: * @param source the name of the resource to copy (full path)
124: * @param destination the name of the copy destination (full path)
125: * @param siblingMode indicates how to handle siblings during copy
126: *
127: * @throws CmsException if something goes wrong
128: * @throws CmsIllegalArgumentException if the <code>destination</code> argument is null or of length 0
129: */
130: public void copyResource(String source, String destination,
131: CmsResourceCopyMode siblingMode) throws CmsException,
132: CmsIllegalArgumentException {
133:
134: boolean exec = false;
135:
136: // iterate through all wrappers and call "copyResource" till one does not return null
137: List wrappers = getWrappers();
138: Iterator iter = wrappers.iterator();
139: while (iter.hasNext()) {
140: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
141: .next();
142: exec = wrapper.copyResource(m_cms, source, destination,
143: siblingMode);
144: if (exec) {
145: break;
146: }
147: }
148:
149: // delegate the call to the CmsObject
150: if (!exec) {
151: m_cms.copyResource(source, destination, siblingMode);
152: }
153:
154: }
155:
156: /**
157: * Creates a new resource of the given resource type with empty content and no properties.<p>
158: *
159: * @see #createResource(String, int, byte[], List)
160: *
161: * @param resourcename the name of the resource to create (full path)
162: * @param type the type of the resource to create
163: *
164: * @return the created resource
165: *
166: * @throws CmsException if something goes wrong
167: * @throws CmsIllegalArgumentException if the given <code>resourcename</code> is null or of length 0
168: */
169: public CmsResource createResource(String resourcename, int type)
170: throws CmsException, CmsIllegalArgumentException {
171:
172: return createResource(resourcename, type, new byte[0],
173: Collections.EMPTY_LIST);
174: }
175:
176: /**
177: * Creates a new resource of the given resource type with the provided content and properties.<p>
178: *
179: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
180: *
181: * @see I_CmsResourceWrapper#createResource(CmsObject, String, int, byte[], List)
182: * @see CmsObject#createResource(String, int, byte[], List)
183: *
184: * @param resourcename the name of the resource to create (full path)
185: * @param type the type of the resource to create
186: * @param content the contents for the new resource
187: * @param properties the properties for the new resource
188: *
189: * @return the created resource
190: *
191: * @throws CmsException if something goes wrong
192: * @throws CmsIllegalArgumentException if the <code>resourcename</code> argument is null or of length 0
193: */
194: public CmsResource createResource(String resourcename, int type,
195: byte[] content, List properties) throws CmsException,
196: CmsIllegalArgumentException {
197:
198: CmsResource res = null;
199:
200: // iterate through all wrappers and call "createResource" till one does not return null
201: List wrappers = getWrappers();
202: Iterator iter = wrappers.iterator();
203: while (iter.hasNext()) {
204: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
205: .next();
206: res = wrapper.createResource(m_cms, resourcename, type,
207: content, properties);
208: if (res != null) {
209: break;
210: }
211: }
212:
213: // delegate the call to the CmsObject
214: if (res == null) {
215: res = m_cms.createResource(resourcename, type, content,
216: properties);
217: }
218:
219: return res;
220: }
221:
222: /**
223: * Deletes a resource given its name.<p>
224: *
225: * Iterates through all configured resource wrappers till the first returns <code>true</code>.<p>
226: *
227: * @see I_CmsResourceWrapper#deleteResource(CmsObject, String, CmsResource.CmsResourceDeleteMode)
228: * @see CmsObject#deleteResource(String, CmsResource.CmsResourceDeleteMode)
229: *
230: * @param resourcename the name of the resource to delete (full path)
231: * @param siblingMode indicates how to handle siblings of the deleted resource
232: *
233: * @throws CmsException if something goes wrong
234: */
235: public void deleteResource(String resourcename,
236: CmsResourceDeleteMode siblingMode) throws CmsException {
237:
238: boolean exec = false;
239:
240: // iterate through all wrappers and call "deleteResource" till one does not return false
241: List wrappers = getWrappers();
242: Iterator iter = wrappers.iterator();
243: while (iter.hasNext()) {
244: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
245: .next();
246: exec = wrapper.deleteResource(m_cms, resourcename,
247: siblingMode);
248: if (exec) {
249: break;
250: }
251: }
252:
253: // delegate the call to the CmsObject
254: if (!exec) {
255: m_cms.deleteResource(resourcename, siblingMode);
256: }
257: }
258:
259: /**
260: * Checks the availability of a resource in the VFS,
261: * using the {@link CmsResourceFilter#DEFAULT} filter.<p>
262: *
263: * Here it will be first checked if the resource exists in the VFS by calling
264: * {@link org.opencms.file.CmsObject#existsResource(String)}. Only if it doesn't exist
265: * in the VFS the method {@link I_CmsResourceWrapper#readResource(CmsObject, String, CmsResourceFilter)}
266: * in the configured resource wrappers are called till the first does not throw an exception or returns
267: * <code>null</code>.<p>
268: *
269: * @param resourcename the name of the resource to check (full path)
270: *
271: * @return <code>true</code> if the resource is available
272: */
273: public boolean existsResource(String resourcename) {
274:
275: // first try to find the resource
276: boolean ret = m_cms.existsResource(resourcename);
277:
278: // if not exists, ask the resource type wrappers
279: if (!ret) {
280:
281: List wrappers = getWrappers();
282: Iterator iter = wrappers.iterator();
283: while (iter.hasNext()) {
284: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
285: .next();
286: try {
287: CmsResource res = wrapper.readResource(m_cms,
288: resourcename, CmsResourceFilter.DEFAULT);
289: if (res != null) {
290: ret = true;
291: break;
292: }
293: } catch (CmsException ex) {
294: // noop
295: }
296: }
297:
298: }
299:
300: return ret;
301: }
302:
303: /**
304: * Returns the lock state for a specified resource.<p>
305: *
306: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
307: *
308: * @see I_CmsResourceWrapper#getLock(CmsObject, CmsResource)
309: * @see CmsObject#getLock(CmsResource)
310: *
311: * @param resource the resource to return the lock state for
312: *
313: * @return the lock state for the specified resource
314: *
315: * @throws CmsException if something goes wrong
316: */
317: public CmsLock getLock(CmsResource resource) throws CmsException {
318:
319: CmsLock lock = null;
320:
321: // iterate through all wrappers and call "getLock" till one does not return null
322: List wrappers = getWrappers();
323: Iterator iter = wrappers.iterator();
324: while (iter.hasNext()) {
325: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
326: .next();
327: lock = wrapper.getLock(m_cms, resource);
328: if (lock != null) {
329: break;
330: }
331: }
332:
333: // delegate the call to the CmsObject
334: if (lock == null) {
335: lock = m_cms.getLock(resource);
336: }
337:
338: return lock;
339: }
340:
341: /**
342: * Delegate method for {@link CmsObject#getRequestContext()}.<p>
343: *
344: * @see CmsObject#getRequestContext()
345:
346: * @return the current users request context
347: */
348: public CmsRequestContext getRequestContext() {
349:
350: return m_cms.getRequestContext();
351: }
352:
353: /**
354: * Returns all child resources of a resource, that is the resources
355: * contained in a folder.<p>
356: *
357: * First fetch all child resources from VFS by calling {@link CmsObject#getResourcesInFolder(String, CmsResourceFilter)}.
358: * After that all resource wrapper are called {@link I_CmsResourceWrapper#addResourcesToFolder(CmsObject, String, CmsResourceFilter)}
359: * to have the chance to add additional resources to those already existing. In that list every resource is given to
360: * the appropriate resource wrapper ({@link I_CmsResourceWrapper#wrapResource(CmsObject, CmsResource)}) to have the
361: * possibility to change the existing resources. The matching resource wrapper for a resource is found by a call to
362: * {@link I_CmsResourceWrapper#isWrappedResource(CmsObject, CmsResource)}.<p>
363: *
364: * @see I_CmsResourceWrapper#addResourcesToFolder(CmsObject, String, CmsResourceFilter)
365: * @see CmsObject#getResourcesInFolder(String, CmsResourceFilter)
366: *
367: * @param resourcename the full path of the resource to return the child resources for
368: * @param filter the resource filter to use
369: *
370: * @return a list of all child <code>{@link CmsResource}</code>s
371: *
372: * @throws CmsException if something goes wrong
373: */
374: public List getResourcesInFolder(String resourcename,
375: CmsResourceFilter filter) throws CmsException {
376:
377: List list = new ArrayList();
378:
379: // read children existing in the VFS
380: try {
381: list.addAll(m_cms
382: .getResourcesInFolder(resourcename, filter));
383: } catch (CmsException ex) {
384: //noop
385: }
386:
387: // iterate through all wrappers and call "addResourcesToFolder" and add the results to the list
388: List wrappers = getWrappers();
389: Iterator iter = wrappers.iterator();
390: while (iter.hasNext()) {
391: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
392: .next();
393: List added = wrapper.addResourcesToFolder(m_cms,
394: resourcename, filter);
395: if (added != null) {
396: list.addAll(added);
397: }
398: }
399:
400: // create a new list to add all resources
401: ArrayList wrapped = new ArrayList();
402:
403: // eventually wrap the found resources
404: iter = list.iterator();
405: while (iter.hasNext()) {
406: CmsResource res = (CmsResource) iter.next();
407:
408: // correct the length of the content if an UTF-8 marker would be added later
409: if (needUtf8Marker(res)) {
410: CmsWrappedResource wrap = new CmsWrappedResource(res);
411: wrap.setLength(res.getLength()
412: + CmsResourceWrapperUtils.UTF8_MARKER.length);
413:
414: res = wrap.getResource();
415: }
416:
417: // get resource type wrapper for the resource
418: I_CmsResourceWrapper resWrapper = getResourceTypeWrapper(res);
419:
420: if (resWrapper != null) {
421:
422: // adds the wrapped resources
423: wrapped.add(resWrapper.wrapResource(m_cms, res));
424: } else {
425:
426: // add the resource unwrapped
427: wrapped.add(res);
428: }
429: }
430:
431: // sort the wrapped list correctly
432: Collections
433: .sort(
434: wrapped,
435: CmsResource.COMPARE_ROOT_PATH_IGNORE_CASE_FOLDERS_FIRST);
436:
437: return wrapped;
438: }
439:
440: /**
441: * Delegate method for {@link CmsObject#getSitePath(CmsResource)}.<p>
442: *
443: * @see CmsObject#getSitePath(org.opencms.file.CmsResource)
444: *
445: * @param resource the resource to get the adjusted site root path for
446: *
447: * @return the absolute resource path adjusted for the current site
448: */
449: public String getSitePath(CmsResource resource) {
450:
451: return m_cms.getSitePath(resource);
452: }
453:
454: /**
455: * Returns the configured resource wrappers used by this instance.<p>
456: *
457: * Entries in list are from type {@link I_CmsResourceWrapper}.<p>
458: *
459: * @return the configured resource wrappers for this instance
460: */
461: public List getWrappers() {
462:
463: return m_wrappers;
464: }
465:
466: /**
467: * Locks a resource.<p>
468: *
469: * Iterates through all configured resource wrappers till the first returns <code>true</code>.<p>
470: *
471: * @see I_CmsResourceWrapper#lockResource(CmsObject, String)
472: * @see CmsObject#lockResource(String)
473: *
474: * @param resourcename the name of the resource to lock (full path)
475: *
476: * @throws CmsException if something goes wrong
477: */
478: public void lockResource(String resourcename) throws CmsException {
479:
480: boolean exec = false;
481:
482: // iterate through all wrappers and call "lockResource" till one does not return false
483: List wrappers = getWrappers();
484: Iterator iter = wrappers.iterator();
485: while (iter.hasNext()) {
486: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
487: .next();
488: exec = wrapper.lockResource(m_cms, resourcename);
489: if (exec) {
490: break;
491: }
492: }
493:
494: // delegate the call to the CmsObject
495: if (!exec) {
496: m_cms.lockResource(resourcename);
497: }
498: }
499:
500: /**
501: * Moves a resource to the given destination.<p>
502: *
503: * Iterates through all configured resource wrappers till the first returns <code>true</code>.<p>
504: *
505: * @see I_CmsResourceWrapper#moveResource(CmsObject, String, String)
506: * @see CmsObject#moveResource(String, String)
507: *
508: * @param source the name of the resource to move (full path)
509: * @param destination the destination resource name (full path)
510: *
511: * @throws CmsException if something goes wrong
512: */
513: public void moveResource(String source, String destination)
514: throws CmsException {
515:
516: boolean exec = false;
517:
518: // iterate through all wrappers and call "moveResource" till one does not return false
519: List wrappers = getWrappers();
520: Iterator iter = wrappers.iterator();
521: while (iter.hasNext()) {
522: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
523: .next();
524: exec = wrapper.moveResource(m_cms, source, destination);
525: if (exec) {
526: break;
527: }
528: }
529:
530: // delegate the call to the CmsObject
531: if (!exec) {
532: m_cms.moveResource(source, destination);
533: }
534: }
535:
536: /**
537: * Reads a file resource (including it's binary content) from the VFS,
538: * using the specified resource filter.<p>
539: *
540: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
541: *
542: * If the resource contains textual content and the encoding is UTF-8, then the byte order mask
543: * for UTF-8 is added at the start of the content to make sure that a client using this content
544: * displays it correctly.<p>
545: *
546: * @see I_CmsResourceWrapper#readFile(CmsObject, String, CmsResourceFilter)
547: * @see CmsObject#readFile(String, CmsResourceFilter)
548: *
549: * @param resourcename the name of the resource to read (full path)
550: * @param filter the resource filter to use while reading
551: *
552: * @return the file resource that was read
553: *
554: * @throws CmsException if the file resource could not be read for any reason
555: */
556: public CmsFile readFile(String resourcename,
557: CmsResourceFilter filter) throws CmsException {
558:
559: CmsFile res = null;
560:
561: // iterate through all wrappers and call "readFile" till one does not return null
562: List wrappers = getWrappers();
563: Iterator iter = wrappers.iterator();
564: while (iter.hasNext()) {
565: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
566: .next();
567: res = wrapper.readFile(m_cms, resourcename, filter);
568: if (res != null) {
569: break;
570: }
571: }
572:
573: // delegate the call to the CmsObject
574: if (res == null) {
575: res = m_cms.readFile(resourcename, filter);
576: }
577:
578: // for text based resources which are encoded in UTF-8 add the UTF marker at the start
579: // of the content
580: if (needUtf8Marker(res)) {
581:
582: if (LOG.isDebugEnabled()) {
583: LOG.debug(Messages.get().getBundle().key(
584: Messages.LOG_ADD_UTF8_MARKER_1,
585: res.getRootPath()));
586: }
587:
588: res.setContents(CmsResourceWrapperUtils.addUtf8Marker(res
589: .getContents()));
590: }
591:
592: return res;
593: }
594:
595: /**
596: * Delegate method for {@link CmsObject#readPropertyObject(CmsResource, String, boolean)}.<p>
597: *
598: * @see CmsObject#readPropertyObject(CmsResource, String, boolean)
599: *
600: * @param resource the resource where the property is attached to
601: * @param property the property name
602: * @param search if true, the property is searched on all parent folders of the resource,
603: * if it's not found attached directly to the resource
604: *
605: * @return the required property, or <code>{@link CmsProperty#getNullProperty()}</code> if the property was not found
606: *
607: * @throws CmsException if something goes wrong
608: */
609: public CmsProperty readPropertyObject(CmsResource resource,
610: String property, boolean search) throws CmsException {
611:
612: return m_cms.readPropertyObject(resource, property, search);
613: }
614:
615: /**
616: * Delegate method for {@link CmsObject#readResource(CmsUUID, CmsResourceFilter)}.<p>
617: *
618: * @see CmsObject#readResource(CmsUUID, CmsResourceFilter)
619: *
620: * @param structureID the ID of the structure to read
621: * @param filter the resource filter to use while reading
622: *
623: * @return the resource that was read
624: *
625: * @throws CmsException if the resource could not be read for any reason
626: */
627: public CmsResource readResource(CmsUUID structureID,
628: CmsResourceFilter filter) throws CmsException {
629:
630: return m_cms.readResource(structureID, filter);
631: }
632:
633: /**
634: * Reads a resource from the VFS,
635: * using the <code>{@link CmsResourceFilter#DEFAULT}</code> filter.<p>
636: *
637: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
638: *
639: * @see I_CmsResourceWrapper#readResource(CmsObject, String, CmsResourceFilter)
640: * @see CmsObject#readResource(String, CmsResourceFilter)
641: *
642: * @param resourcename The name of the resource to read (full path)
643: * @param filter the resource filter to use while reading
644: *
645: * @return the resource that was read
646: *
647: * @throws CmsException if the resource could not be read for any reason
648: */
649: public CmsResource readResource(String resourcename,
650: CmsResourceFilter filter) throws CmsException {
651:
652: CmsResource res = null;
653:
654: // iterate through all wrappers and call "readResource" till one does not return null
655: List wrappers = getWrappers();
656: Iterator iter = wrappers.iterator();
657: while (iter.hasNext()) {
658: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
659: .next();
660: res = wrapper.readResource(m_cms, resourcename, filter);
661: if (res != null) {
662: break;
663: }
664: }
665:
666: // delegate the call to the CmsObject
667: if (res == null) {
668: res = m_cms.readResource(resourcename, filter);
669: }
670:
671: // correct the length of the content if an UTF-8 marker would be added later
672: if (needUtf8Marker(res)) {
673: CmsWrappedResource wrap = new CmsWrappedResource(res);
674: wrap.setLength(res.getLength()
675: + CmsResourceWrapperUtils.UTF8_MARKER.length);
676:
677: return wrap.getResource();
678: }
679:
680: return res;
681: }
682:
683: /**
684: * Delegate method for {@link CmsObject#readUser(CmsUUID)}.<p>
685: *
686: * @see CmsObject#readUser(CmsUUID)
687: *
688: * @param userId the id of the user to be read
689: *
690: * @return the user with the given id
691: *
692: * @throws CmsException if something goes wrong
693: */
694: public CmsUser readUser(CmsUUID userId) throws CmsException {
695:
696: return m_cms.readUser(userId);
697: }
698:
699: /**
700: * Returns a link to an existing resource in the VFS.<p>
701: *
702: * Because it is possible through the <code>CmsObjectWrapper</code> to create "virtual" resources,
703: * which can not be found in the VFS, it is necessary to change the links in pages
704: * as well, so that they point to resources which really exists in the VFS.<p>
705: *
706: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
707: *
708: * @see #rewriteLink(String)
709: * @see I_CmsResourceWrapper#restoreLink(CmsObject, String)
710: *
711: * @param path the path to the resource
712: *
713: * @return the path for the resource which exists in the VFS
714: */
715: public String restoreLink(String path) {
716:
717: if ((path != null) && (path.startsWith("#"))) {
718: return path;
719: }
720:
721: String ret = null;
722:
723: // iterate through all wrappers and call "restoreLink" till one does not return null
724: List wrappers = getWrappers();
725: Iterator iter = wrappers.iterator();
726: while (iter.hasNext()) {
727: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
728: .next();
729: ret = wrapper.restoreLink(m_cms, m_cms.getRequestContext()
730: .removeSiteRoot(path));
731: if (ret != null) {
732: return ret;
733: }
734: }
735:
736: return path;
737: }
738:
739: /**
740: * Returns a link to a resource after it was wrapped by the CmsObjectWrapper.<p>
741: *
742: * Because it is possible to change the names of resources inside the VFS by this
743: * <code>CmsObjectWrapper</code>, it is necessary to change the links used in pages
744: * as well, so that they point to the changed name of the resource.<p>
745: *
746: * For example: <code>/sites/default/index.html</code> becomes to
747: * <code>/sites/default/index.html.jsp</code>, because it is a jsp page, the links
748: * in pages where corrected so that they point to the new name (with extension "jsp").<p>
749: *
750: * Used for the link processing in the class {@link org.opencms.relations.CmsLink}.<p>
751: *
752: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
753: *
754: * @see #restoreLink(String)
755: * @see I_CmsResourceWrapper#rewriteLink(CmsObject, CmsResource)
756: *
757: * @param path the full path where to find the resource
758: *
759: * @return the rewritten link for the resource
760: */
761: public String rewriteLink(String path) {
762:
763: CmsResource res = null;
764:
765: try {
766: res = readResource(m_cms.getRequestContext()
767: .removeSiteRoot(path), CmsResourceFilter.ALL);
768: if (res != null) {
769: String ret = null;
770:
771: // iterate through all wrappers and call "rewriteLink" till one does not return null
772: List wrappers = getWrappers();
773: Iterator iter = wrappers.iterator();
774: while (iter.hasNext()) {
775: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
776: .next();
777: ret = wrapper.rewriteLink(m_cms, res);
778: if (ret != null) {
779: return ret;
780: }
781: }
782: }
783: } catch (CmsException ex) {
784: // noop
785: }
786:
787: return path;
788: }
789:
790: /**
791: * Unlocks a resource.<p>
792: *
793: * Iterates through all configured resource wrappers till the first returns <code>true</code>.<p>
794: *
795: * @see I_CmsResourceWrapper#unlockResource(CmsObject, String)
796: * @see CmsObject#unlockResource(String)
797: *
798: * @param resourcename the name of the resource to unlock (full path)
799: *
800: * @throws CmsException if something goes wrong
801: */
802: public void unlockResource(String resourcename) throws CmsException {
803:
804: boolean exec = false;
805:
806: // iterate through all wrappers and call "lockResource" till one does not return false
807: List wrappers = getWrappers();
808: Iterator iter = wrappers.iterator();
809: while (iter.hasNext()) {
810: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
811: .next();
812: exec = wrapper.unlockResource(m_cms, resourcename);
813: if (exec) {
814: break;
815: }
816: }
817:
818: // delegate the call to the CmsObject
819: if (!exec) {
820: m_cms.unlockResource(resourcename);
821: }
822: }
823:
824: /**
825: * Writes a resource to the OpenCms VFS, including it's content.<p>
826: *
827: * Iterates through all configured resource wrappers till the first returns not <code>null</code>.<p>
828: *
829: * @see I_CmsResourceWrapper#writeFile(CmsObject, CmsFile)
830: * @see CmsObject#writeFile(CmsFile)
831: *
832: * @param resource the resource to write
833: *
834: * @return the written resource (may have been modified)
835: *
836: * @throws CmsException if something goes wrong
837: */
838: public CmsFile writeFile(CmsFile resource) throws CmsException {
839:
840: CmsFile res = null;
841:
842: // remove the added UTF-8 marker
843: if (needUtf8Marker(resource)) {
844: resource.setContents(CmsResourceWrapperUtils
845: .removeUtf8Marker(resource.getContents()));
846: }
847:
848: String resourcename = resource.getRootPath();
849: if (!m_cms.existsResource(resourcename)) {
850:
851: // iterate through all wrappers and call "writeFile" till one does not return null
852: List wrappers = getWrappers();
853: Iterator iter = wrappers.iterator();
854: while (iter.hasNext()) {
855: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
856: .next();
857: res = wrapper.writeFile(m_cms, resource);
858: if (res != null) {
859: break;
860: }
861: }
862:
863: // delegate the call to the CmsObject
864: if (res == null) {
865: res = m_cms.writeFile(resource);
866: }
867: } else {
868: res = m_cms.writeFile(resource);
869: }
870:
871: return res;
872: }
873:
874: /**
875: * Try to find a resource type wrapper for the resource.<p>
876: *
877: * Takes all configured resource type wrappers and ask if one of them is responsible
878: * for that resource. The first in the list which feels responsible is returned.
879: * If no wrapper could be found null will be returned.<p>
880: *
881: * @see I_CmsResourceWrapper#isWrappedResource(CmsObject, CmsResource)
882: *
883: * @param res the resource to find a resource type wrapper for
884: *
885: * @return the found resource type wrapper for the resource or null if not found
886: */
887: private I_CmsResourceWrapper getResourceTypeWrapper(CmsResource res) {
888:
889: Iterator iter = getWrappers().iterator();
890: while (iter.hasNext()) {
891: I_CmsResourceWrapper wrapper = (I_CmsResourceWrapper) iter
892: .next();
893:
894: if (wrapper.isWrappedResource(m_cms, res)) {
895: return wrapper;
896: }
897: }
898:
899: return null;
900: }
901:
902: /**
903: * Checks if the resource type needs an UTF-8 marker.<p>
904: *
905: * If the encoding of the resource is "UTF-8" and the resource
906: * type is one of the following:<br/>
907: * <ul>
908: * <li>{@link CmsResourceTypeJsp}</li>
909: * <li>{@link CmsResourceTypePlain}</li>
910: * <li>{@link CmsResourceTypeXmlContent}</li>
911: * <li>{@link CmsResourceTypeXmlPage}</li>
912: * </ul>
913: *
914: * it needs an UTF-8 marker.<p>
915: *
916: * @param res the resource to check if the content needs a UTF-8 marker
917: *
918: * @return <code>true</code> if the resource needs an UTF-8 maker otherwise <code>false</code>
919: */
920: private boolean needUtf8Marker(CmsResource res) {
921:
922: // if the encoding of the resource is not UTF-8 return false
923: String encoding = CmsLocaleManager.getResourceEncoding(m_cms,
924: res);
925: if (!CmsEncoder.ENCODING_UTF_8.equals(encoding)) {
926: return false;
927: }
928:
929: try {
930: I_CmsResourceType resType = OpenCms.getResourceManager()
931: .getResourceType(res.getTypeId());
932:
933: boolean typeMatch = false;
934: if (resType instanceof CmsResourceTypeJsp) {
935: typeMatch = true;
936: } else if (resType instanceof CmsResourceTypePlain) {
937: typeMatch = true;
938: } else if (resType instanceof CmsResourceTypeXmlContent) {
939: typeMatch = true;
940: } else if (resType instanceof CmsResourceTypeXmlPage) {
941: typeMatch = true;
942: }
943:
944: return typeMatch;
945: } catch (CmsLoaderException e) {
946: // noop
947: }
948:
949: return false;
950: }
951:
952: }
|